예제 #1
0
// Prints information about all of the universes in the array
// to a given player.
void CHSUniverseDBDef::PrintInfo(int player)
{
    if (m_mapUniverses.empty())
    {
        hsInterface.Notify(player, "No universes currently loaded.");
        return;
    }

    hsInterface.Notify(player,
                       "[Room#] Name                            Objects    Active");

    CSTLUniverseMap::iterator iter;
    for (iter = m_mapUniverses.begin(); iter != m_mapUniverses.end(); iter++)
    {
        CHSUniverse *pUniverse = iter->second;
        if (pUniverse)
        {
            hsInterface.Notify(player,
                               hsInterface.
                               HSPrintf("[%5d] %-32s%4d       %4d",
                                        pUniverse->GetID(),
                                        pUniverse->GetName(),
                                        pUniverse->GetNumObjects(),
                                        pUniverse->GetNumActiveObjects()));
        }
    }
}
예제 #2
0
HS_BOOL8 CHSUniverseDBDef::DeleteUniverse(HS_UINT32 uid)
{
    CSTLUniverseMap::iterator iter;
    CHSUniverse *pUniverse = NULL;

    if ((iter = m_mapUniverses.find(uid)) != m_mapUniverses.end())
    {
        pUniverse = (*iter).second;
    }

    if (!pUniverse)
    {
        return false;
    }

    // Check to see if the universe is empty
    if (!pUniverse->IsEmpty())
    {
        return false;
    }

    // Delete it
    pUniverse->Release();

    m_mapUniverses.erase(iter);

    return true;
}
예제 #3
0
void CHSHandlerUniverse::HandleGetUniverseList(CHSPacket * pPacket)
{
    hs_log("ADMIN SERVER: Handle packet GetUniverseList");
    CHSPGetUniverseList *cmdGetList =
        static_cast < CHSPGetUniverseList * >(pPacket);

    // Create a class list packet as a response.
    CHSPUniverseList cmdList;
    cmdList.SetPacketAddress(cmdGetList->GetPacketAddress());

    THSUniverseIterator tIter;
    HS_BOOL8 bContinue;

    for (bContinue = CHSUniverseDB::GetInstance().GetFirstUniverse(tIter);
         bContinue;
         bContinue = CHSUniverseDB::GetInstance().GetNextUniverse(tIter))
    {
        if (tIter.pValue != NULL)
        {
            CHSUniverse *pUniverse = (CHSUniverse *) tIter.pValue;

            CHSPUniverseList::THSUniverse tEntry;

            tEntry.uiID = pUniverse->GetID();
            tEntry.strName = pUniverse->GetName();
            tEntry.uiNumObjects = pUniverse->GetNumObjects();
            tEntry.uiNumActiveObjects = pUniverse->GetNumActiveObjects();

            cmdList.AddUniverse(tEntry);
        }
    }

    HSNetwork.SendPacket(cmdList);
}
예제 #4
0
void CHSHandlerClass::HandleDeleteClass(CHSPacket * pPacket)
{
    CHSPDeleteClass *pDelete = static_cast < CHSPDeleteClass * >(pPacket);
    CHSPDeleteClassResponse cmdResponse;

    cmdResponse.SetPacketAddress(pDelete->GetPacketAddress());
    cmdResponse.m_bDeleted = true;

    // Check to see if any ships remain with that class.
    // If so, don't allow it to be deleted.
    THSUniverseIterator tIter;
    HS_BOOL8 bIter;
    for (bIter = CHSUniverseDB::GetInstance().GetFirstUniverse(tIter); bIter;
         bIter = CHSUniverseDB::GetInstance().GetNextUniverse(tIter))
    {
        CHSUniverse *pUniverse = tIter.pValue;

        // Search ships in the universe
        THSObjectIterator tIterator;
        HS_BOOL8 bContinue;
        for (bContinue = pUniverse->GetFirstObject(tIterator, HST_SHIP);
             bContinue;
             bContinue = pUniverse->GetNextObject(tIterator, HST_SHIP))
        {
            if (tIterator.pValue)
            {
                CHSShip *pShip = static_cast < CHSShip * >(tIterator.pValue);
                if (pShip->ClassNum() == pDelete->m_uiClassID)
                {
                    // This class is still in use.
                    cmdResponse.m_bDeleted = false;
                    break;
                }
            }
        }

        if (bContinue)
        {
            // Inner loop exited prematurely.
            break;
        }
    }

    // Can we delete this class?
    if (cmdResponse.m_bDeleted)
    {
        cmdResponse.m_bDeleted =
            CHSClassDB::GetInstance().RemoveClass(pDelete->m_uiClassID);
    }

    HSNetwork.SendPacket(cmdResponse);
}
void CHSAsteroid::DoCycle(void)
{
	CHSObject *cObj;
	CHSUniverse *uSrc;
	CHSShip *Target;
	int idx;
	double dDistance;

		
	  uSrc = uaUniverses.FindUniverse(GetUID());
	  if (!uSrc)
		  return;
	
	  // Grab all of the objects in the universe, and see if they're in the area.
	  for (idx = 0; idx < HS_MAX_OBJECTS; idx++)
	  {
		  cObj = uSrc->GetUnivObject(idx);
		  if (!cObj)
			  continue;
		  if (cObj->GetType() != HST_SHIP)
			  continue;

		  Target = (CHSShip *) cObj;
		  dDistance = Dist3D(GetX(),GetY(),GetZ(),Target->GetX(),Target->GetY(),Target->GetZ());
		  
		  if (dDistance > GetSize() * 100)
			  continue;

		  if (GetDensity() < getrandom(50 / Target->GetSize() * ((Target->GetSpeed() + 1) / 1000)))
			  continue;

		  int strength;

		  strength = getrandom(GetDensity() * Target->GetSize() * ((Target->GetSpeed() + 1) / 1000));

		  Target->m_hull_points -= strength;

		  Target->NotifySrooms("The ship shakes as asteroids impact on the hull");

		  	// Is hull < 0?
			if (Target->m_hull_points < 0)
			{
				Target->ExplodeMe();
				if (!hsInterface.HasFlag(m_objnum, TYPE_THING, THING_HSPACE_SIM))
					Target->KillShipCrew("THE SHIP EXPLODES!!");
			} 

	  }

}
void CHSBlackHole::DoCycle(void)
{
	CHSObject *cObj;
	CHSUniverse *uSrc;
	CHSShip *Target;
	int idx;
	double dDistance;

		
	  uSrc = uaUniverses.FindUniverse(GetUID());
	  if (!uSrc)
		  return;
	
	  // Grab all of the objects in the universe, and see if they're in the area.
	  for (idx = 0; idx < HS_MAX_OBJECTS; idx++)
	  {
		  cObj = uSrc->GetUnivObject(idx);
		  if (!cObj)
			  continue;
		  if (cObj->GetType() != HST_SHIP)
			  continue;

		  Target = (CHSShip *) cObj;
		  dDistance = Dist3D(GetX(),GetY(),GetZ(),Target->GetX(),Target->GetY(),Target->GetZ());
		  
		  if (dDistance > GetSize() * 100 - 0.01)
			  continue;

		  int strength;

		  strength = (GetSize() * 100) / dDistance * 100 - 100;

		  Target->MoveTowards(m_x, m_y, m_z, strength);

		  Target->m_hull_points -= strength;

		  Target->NotifySrooms("The hull buckles from the black hole's gravity.");

		  	// Is hull < 0?
			if (Target->m_hull_points < 0)
			{
				Target->ExplodeMe();
				if (!hsInterface.HasFlag(m_objnum, TYPE_THING, THING_HSPACE_SIM))
					Target->KillShipCrew("THE SHIP EXPLODES!!");
			} 

	  }

}
예제 #7
0
// Runs through the list of universes, telling them to
// save to the specified file.
void CHSUniverseDBDef::SaveToFile(const char *lpstrPath)
{
    FILE *fp;
    char tbuf[256];

    // Is the file path good?
    if (!lpstrPath || strlen(lpstrPath) == 0)
    {
        hs_log
            ("Attempt to save the universe database, but no path specified.  Could be a config file problem.");
        return;
    }

    // Any universes to save?
    if (m_mapUniverses.size() == 0)
    {
        return;
    }

    // Open the database
    fopen_s(&fp, lpstrPath, "w");
    if (!fp)
    {
        sprintf_s(tbuf, "ERROR: Unable to write universes to %s.", lpstrPath);
        hs_log(tbuf);
        return;
    }

    // Print dbversion
    fprintf(fp, "DBVERSION=4.0\n");

    // Save all of the universes.
    CSTLUniverseMap::iterator iter;

    for (iter = m_mapUniverses.begin(); iter != m_mapUniverses.end(); iter++)
    {
        CHSUniverse *pUniverse;

        pUniverse = (*iter).second;

        if (pUniverse)
        {
            pUniverse->SaveToFile(fp);
        }
    }
    fprintf(fp, "*END*\n");
    fclose(fp);
}
예제 #8
0
CHSUniverseDBDef::~CHSUniverseDBDef()
{
    CSTLUniverseMap::iterator iter;

    // Free up the universes we've loaded.
    for (iter = m_mapUniverses.begin(); iter != m_mapUniverses.end(); iter++)
    {
        CHSUniverse *pUniverse;

        pUniverse = (*iter).second;

        if (pUniverse)
        {
            pUniverse->Release();
        }
    }
}
void CHSWormHole::GateShip(CHSShip *cShip)
{
	if (!cShip)
		return;

	BOOL succeed;

	if (getrandom(100) <= m_stability)
		succeed = TRUE;
	else
		succeed = FALSE;
	
	cShip->NotifyConsoles("The ship enters the wormhole and an infinite amount of colors can be seen.", MSG_SENSOR);
	cShip->NotifySrooms("The ship shakes slightly as it enters a wormhole.");

	CHSUniverse *uDest;
	uDest = uaUniverses.FindUniverse(cShip->GetUID());
	if (uDest) {
			uDest->SendContactMessage("In the distance a ship gates a wormhole.", 
			DETECTED, cShip);
			uDest->SendContactMessage(
				tprintf("In the distance the %s gates a wormhole.",cShip->GetName()), IDENTIFIED, cShip);
	} 


	if (succeed)
	{
		if (m_destx)
			cShip->SetX(m_destx);
		if (m_desty)
			cShip->SetY(m_desty);
		if (m_destz)
			cShip->SetZ(m_destz);
		
		CHSUniverse *uSource;

		uDest = uaUniverses.FindUniverse(m_destuid);
		if (uDest)
		{
			// Grab the source universe
			uSource = uaUniverses.FindUniverse(cShip->GetUID());

			// Now pull it from one, and put it in another
			uSource->RemoveObject(cShip);
			cShip->SetUID(m_destuid);
			uDest->AddObject(cShip);
		}

		cShip->NotifyConsoles("The ship safely emerges on the other side of the wormhole.", MSG_SENSOR);
	} else {
		cShip->NotifyConsoles("The wormhole collapses and the structural integrity is comprimised.", MSG_SENSOR);
		cShip->ExplodeMe();
		if (!hsInterface.HasFlag(cShip->GetDbref(), TYPE_THING, THING_HSPACE_SIM))
				cShip->KillShipCrew("The ship explodes as the structural integrity fails!");
	}
}
예제 #10
0
void CHSMissile::DoCycle()
{
    // Do we need to delete ourselves?
    if (m_delete_me)
    {
        // Remove us from space
        CHSUniverse *cSource;
        cSource = GetUniverse();
        if (cSource)
        {
            cSource->RemoveObject(this);
        }

        // Purge the object representing the missile prior to deallocating
        // memory
        if (hsInterface.ValidObject(GetDbref()))
        {
            hsInterface.DestroyObject(GetDbref());
        }

        return;
    }

    // If we have no target or no parent, remove us from space.
    if (!m_target || !m_pData || !m_target->IsActive())
    {
        hs_log("CHSMissile::DoCycle() Missile Data Invalid - Removing Object.");
        m_delete_me = true;
        return;
    }

    // Do we know how much time is left until we die?
    if (m_timeleft < 0)
    {
        CalculateTimeLeft();
    }
    else
    {
        m_timeleft--;
    }

    // Missile depleted?
    if (0 == m_timeleft)
    {

        m_delete_me = true;
        return;
    }

    // Change the missile heading toward the target
    ChangeHeading();

    // Move us closer to the target.
    MoveTowardTarget();

    // The MoveTowardTarget() checks to see if the missile hits
    // so we just have to check our flag.
    if (m_target_hit)
    {

        // If we aren't designated to miss, apply damage
        if (m_specified_miss != true)
        {
            // BOOM!
            HitTarget();
        }

        m_delete_me = true;     // Delete next time around
    }
}
예제 #11
0
void CHSMTube::AttackObject(CHS3DObject * cSource,
                            CHS3DObject * cTarget,
                            CHSConsole * cConsole,
                            HS_INT32 iSysType, HS_INT32 hit_flag)
{
    HS_DBREF dbUser;

    // Grab the user of the console.
    dbUser = hsInterface.ConsoleUser(cConsole->m_objnum);

    if (cSource->GetType() == HST_SHIP)
    {
        CHSSysCloak *cCloak;
        CHSShip *ptr;

        ptr = (CHSShip *) cSource;

        // Look for the cloaking device.
        cCloak = (CHSSysCloak *) ptr->GetEngSystem(HSS_CLOAK);
        if (cCloak)
            if (cCloak->GetEngaged())
            {
                if (dbUser != HSNOTHING)
                    hsStdError(dbUser, "You cannot fire while cloaked.");
                return;
            }
    }

    // Can we attack that object?
    if (!CanAttackObject(cTarget))
    {
        if (dbUser != HSNOTHING)
            hsStdError(dbUser,
                       "You cannot attack that target with that weapon.");
    }

    // Create a missile object, and put it in space
    CHSMissile *cMiss;
    cMiss = new CHSMissile;
    cMiss->SetUID(cSource->GetUID());

    if (hit_flag == 0)
    {
        cMiss->SetAutoMiss();
    }

    // Add it to the universe
    CHSUniverse *uDest;
    uDest = cMiss->GetUniverse();
    if (!uDest)
    {
        if (dbUser != HSNOTHING)
        {
            hsInterface.Notify(dbUser,
                               "Error finding a universe to put the missile in.");
        }
        delete cMiss;
        return;
    }
    uDest->AddObject(cMiss);

    // Set missile coords
    cMiss->SetX(cSource->GetX());
    cMiss->SetY(cSource->GetY());
    cMiss->SetZ(cSource->GetZ());

    // Set missile heading
    cMiss->SetHeading(cConsole->GetXYHeading(), cConsole->GetZHeading());

    // Set missile type
    cMiss->SetWeaponData(this);

    // Set source info
    cMiss->SetSourceConsole(cConsole);
    cMiss->SetSourceObject(cSource);
    cMiss->SetTargetObject(cTarget);


#ifdef PENNMUSH
    HS_DBREF obj_num = hsInterface.CreateNewGameObject();
#else
    HS_DBREF obj_num = hsInterface.CreateNewGameObject(TYPE_THING);
#endif

    if (hsInterface.ValidObject(obj_num))
    {
        cMiss->SetDbref(obj_num);

        // Try to set the name of the missile properly but default
        // just in case
        if (NULL == m_pWeaponData)
        {
            hsInterface.SetObjectName(obj_num, "Missile");
        }
        else
        {
            hsInterface.SetObjectName(obj_num,
                                      static_cast < CHSMissileData * >(m_pWeaponData)->Name());
        }

        hsInterface.MoveObject(obj_num, uDest->GetID());
        hsInterface.SetToggle(obj_num, THING_HSPACE_OBJECT);
        hsInterface.SetObjectOwner(obj_num, hsInterface.GetGodDbref());

        // Missile objects are temporary, clear them if the game
        // is restarted while the missile is still in existance
        hsInterface.AtrAdd(obj_num, "STARTUP", "@destroy me",
                           hsInterface.GetGodDbref());
    }
    else
    {
        // Set missile HS_DBREF to some very high number that's
        // probably not duplicated.
        cMiss->SetDbref(hsInterface.GetRandom(10000) + 28534);
        hs_log("CHSMTube::AttackObject() -- Deprecated fake dbref method \
                utilized.");
    }

    if (dbUser != HSNOTHING)
    {
        hsStdError(dbUser, "Missile launched.");
    }

    m_loaded = false;
}
예제 #12
0
// Loads universes from the universe db.  It does this by
// loading each line in the db and splitting it up into
// a key/value pair.
HS_BOOL8 CHSUniverseDBDef::LoadFromFile(const char *lpstrPath)
{
    char tbuf[256];
    char strKey[256];
    char strValue[256];
    FILE *fp;
    char *ptr;
    CHSUniverse *pNewUniverse = NULL;

    sprintf_s(tbuf, "LOADING: %s", lpstrPath);
    hs_log(tbuf);

    fopen_s(&fp, lpstrPath, "r");
    if (!fp)
    {
        hs_log("ERROR: Unable to open object database for loading!");
        return false;
    }

    // Load in the lines from the database, splitting the
    // line into key/value pairs.  Each OBJNUM key specifies
    // the beginning of a new universe definition.
    while (fgets(tbuf, 256, fp))
    {
        // Truncate newline chars
        if ((ptr = strchr(tbuf, '\n')) != NULL)
            *ptr = '\0';
        if ((ptr = strchr(tbuf, '\r')) != NULL)
            *ptr = '\0';

        // Check for end of DB
        if (!strcmp(tbuf, "*END*"))
            break;

        // Extract key and value
        extract(tbuf, strKey, 0, 1, '=');
        extract(tbuf, strValue, 1, 1, '=');

        // Determine key type, then do something.
        if (!strcmp(strKey, "DBVERSION"))
        {
        }
        else if (!strcmp(strKey, "OBJNUM"))
        {
            pNewUniverse = new CHSUniverse;

            HS_UINT32 uiID = atoi(strValue);
            if (hsInterface.ValidObject(uiID) == false)
            {
                return false;
            }

            pNewUniverse->SetID(uiID);
            hsInterface.SetToggle(uiID, ROOM_HSPACE_UNIVERSE);

            m_mapUniverses[uiID] = pNewUniverse;
        }
        else
        {
            // Just try to set the attribute on the universe.
            if (pNewUniverse
                && !pNewUniverse->SetAttributeValue(strKey, strValue))
            {
                sprintf_s(tbuf,
                        "WARNING: Key \"%s\" encountered but not handled.",
                        strKey);
                hs_log(tbuf);
            }
        }
    }

    fclose(fp);
    sprintf_s(tbuf, "LOADING: %d universes loaded.", m_mapUniverses.size());
    hs_log(tbuf);

    return true;
}
// Attacks a target object.
void CHSLaser::AttackObject(CHSObject *cSource,
							CHSObject *cTarget,
							CHSConsole *cConsole,
							int iSysType)
{
	dbref dbUser;
	int   iAttackRoll;
	int   iDefendRoll;
	int i;
	CHSObject *cCTarget;
	double sX, sY, sZ; // Source object coords
	double tX, tY, tZ; // Target object coords;

	// Grab the user of the console.
	dbUser = hsInterface.ConsoleUser(cConsole->m_objnum);

	// Can we attack that object?
	if (cSource->GetType() == HST_SHIP)
	{
		CHSSysCloak *cCloak;
		CHSShip *ptr;
		float rval;

		ptr = (CHSShip *)cSource;

		// Look for the cloaking device.
		cCloak = (CHSSysCloak *)ptr->GetEngSystem(HSS_CLOAK);
		if (cCloak)
			if (cCloak->GetEngaged())
			{
				if (dbUser != NOTHING)
					hsStdError(dbUser, "You cannot fire while cloaked.");
				return;
			}
	}

	if (!CanAttackObject(cTarget))
	{
		if (dbUser != NOTHING)
			hsStdError(dbUser,
			"You cannot attack that target with that weapon.");
	}

 	// Calculate distance to object
	sX = cSource->GetX();
	sY = cSource->GetY();
	sZ = cSource->GetZ();
	tX = cTarget->GetX();
	tY = cTarget->GetY();
	tZ = cTarget->GetZ();

	double dDistance;
	dDistance = Dist3D(sX, sY, sZ, tX, tY, tZ) + .00001;

	// Size of a target ship matters relative to distance.
	// The closer a target gets to the ship, the larger
	// it effectively is.  That is to say it takes up more
	// of the view angle.  When the target is right next
	// to the ship, in front of the gun, it is essentially
	// the broad side of a barn, which everyone can hit.
	// Thus, to handle this we'll calculate the size of
	// the target and the viewing angle it takes up.

	double dSize; // Size of the side of the target
	double dAngle; // Amount of viewing angle taken up by size

	dSize = cTarget->GetSize();
	dSize = (.7 * dSize) * (.7 * dSize);

	// Halve the size, and divide by distance.  This
	// gives us the tangent of the angle taken up by
	// the target.
	dSize = (dSize * .5) / dDistance;

	// Take the inverse tangent to get angle.
	dAngle = atan(dSize);

	// Double the angle because we used half of the size
	// to get the angle of a right triangle.
	dAngle *= 2;

	// We now have the viewing angle consumed by the 
	// target.  There's a maximum possible value of 180,
	// so divide by that to determine how much of the viewing
	// angle is taken up by the target.
	dSize = dAngle * .005555;

	// Subtract from 1 to get maximum values of 1 when the
	// angle is small.
	dSize = 1 - dSize;

	// Now multiply by 6 to get relative difficulty of hitting
	// target.
	iDefendRoll = (int) (6 * dSize) + getrandom(6);
    iAttackRoll = GetAccuracy() + getrandom(6);

	// Simulate difficulty when a target is moving.
	// If the target is moving toward or away from the
	// attacker, it's not very difficult.  Thus, we
	// calculate the change in angle for the target
	// during one cycle.  The maximum change is 180
	// degrees.
	CHSVector tVec;
	CHSVector aVec;
	tVec = cTarget->GetMotionVector();
	aVec = cSource->GetMotionVector();

	// Calculate vector to target now.
	double dx, dy, dz;
	dx = tX - sX;
	dy = tY - sY;
	dz = tZ - sZ;

	// Make a unit vector
	dx /= dDistance;
	dy /= dDistance;
	dz /= dDistance;

	CHSVector nowVec(dx, dy, dz);

	// Now calculate coordinate for source and target
	// in one cycle.
	double sX2, sY2, sZ2;
	double tX2, tY2, tZ2;
	double aSpeed, tSpeed;

	// Grab both object speeds, and bring them down
	// to per-second levels.
	aSpeed = cSource->GetSpeed() * .0002778;
	tSpeed = cTarget->GetSpeed() * .0002778;

	// Calculate coordinates for next cycle.
	sX2 = sX + (aVec.i() * aSpeed);
	sY2 = sY + (aVec.j() * aSpeed);
	sZ2 = sZ + (aVec.k() * aSpeed);
	tX2 = tX + (tVec.i() * tSpeed);
	tY2 = tY + (tVec.j() * tSpeed);
	tZ2 = tZ + (tVec.k() * tSpeed);

	// Calculate vector to target after next cycle
	dx = tX2 - sX2;
	dy = tY2 - sY2;
	dz = tZ2 - sZ2;

	// Divide by distance to make a unit vector
	double dDistance2;
	dDistance2 = Dist3D(sX2, sY2, sZ2, tX2, tY2, tZ2);
	dx /= dDistance2;
	dy /= dDistance2;
	dz /= dDistance2;

	CHSVector nextVec(dx, dy, dz);

	// Calculate the dot product between the previous
	// and the next cycle vectors.
	double dp;
	dp = nowVec.DotProduct(nextVec);

	// Calculate the angle change.  This is in radians.
	dAngle = acos(dp);

	// Now divide angle change by 2pi to get change in angle
	// from 0 to 1, where 1 is a huge change in angle and,
	// therefore, high difficulty.
	dAngle *= .15915;

	// Add up to 6 points of defense for "evasion" by angle
	// change.
	iDefendRoll += (int) (6 * dAngle);


	// If distance is farther than our range, the shot always
	// misses.

	double range;
	range = GetRange();
				
	CHSUniverse *uDest;
	char tbuf[256];
	char fstat1[128];
	char fstat2[128];

	if (dDistance >= range || iDefendRoll > iAttackRoll) {
		sprintf(fstat1, "%s%smisses%s",ANSI_HILITE,ANSI_GREEN,ANSI_NORMAL);
		sprintf(fstat2, "%s%smissed%s",ANSI_HILITE,ANSI_GREEN,ANSI_NORMAL);
	} else {
		sprintf(fstat1, "%s%shits%s",ANSI_HILITE,ANSI_RED,ANSI_NORMAL);
		sprintf(fstat2, "%s%shit%s",ANSI_HILITE,ANSI_RED,ANSI_NORMAL);
	}
		
	uDest = uaUniverses.FindUniverse(cSource->GetUID());

	CHSSysSensors *cSensors;
	SENSOR_CONTACT *cContactS;
	SENSOR_CONTACT *cContactD;
	for (i = 0; i < HS_MAX_ACTIVE_OBJECTS; i++)
	{
		cCTarget = uDest->GetActiveUnivObject(i);
		if (!cCTarget)
			continue;
		if (cCTarget == cSource || cCTarget == cTarget)
			continue;

		cSensors = (CHSSysSensors *)cCTarget->GetEngSystem(HSS_SENSORS);
		if (!cSensors)
			continue;

		cContactS = cSensors->GetContact(cSource);
		cContactD = cSensors->GetContact(cTarget);


		if (!cContactS && !cContactD)
			continue;

		if (!cContactS && cContactD) {
			if (cContactD->status == DETECTED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - Unknown contact is being fired upon and %s",cTarget->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactD->m_id,ANSI_NORMAL,cTarget->GetObjectColor(),ANSI_NORMAL, fstat2);
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			} else if (cContactD->status == IDENTIFIED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - The %s is being fired upon and %s",cTarget->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactD->m_id,ANSI_NORMAL,cTarget->GetObjectColor(),ANSI_NORMAL, cSource->GetName(), fstat2);
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			}
			continue;
		}
						
											
		if (cContactS && !cContactD) {
			if (cContactS->status == DETECTED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - Unknown contact is firing upon something",cSource->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactS->m_id,ANSI_NORMAL,cSource->GetObjectColor(),ANSI_NORMAL);
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			} else if (cContactS->status == IDENTIFIED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - The %s is firing upon something",cSource->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactS->m_id,ANSI_NORMAL,cSource->GetObjectColor(),ANSI_NORMAL, cSource->GetName());
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			}
			continue;
		}

		if (cContactS && cContactD)
			if (cContactS->status == DETECTED && cContactD->status == DETECTED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - Unknown contact fires and %s unknown contact %s[%s%s%d%s%s]%s",cSource->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactS->m_id,ANSI_NORMAL,cSource->GetObjectColor(),ANSI_NORMAL, fstat1,cTarget->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactD->m_id,ANSI_NORMAL,cTarget->GetObjectColor(),ANSI_NORMAL);
				cCTarget->HandleMessage(tbuf,MSG_SENSOR, (long *)cCTarget);
			} else if (cContactS->status == IDENTIFIED && cContactD->status == IDENTIFIED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - The %s fires and %s the %s",cSource->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactS->m_id,ANSI_NORMAL,cSource->GetObjectColor(),ANSI_NORMAL, cSource->GetName(), fstat1, cTarget->GetName());
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			} else if (cContactS->status == IDENTIFIED && cContactD->status == DETECTED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - The %s fires and %s unknown contact %s[%s%s%d%s%s]%s",cSource->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactS->m_id,ANSI_NORMAL,cSource->GetObjectColor(),ANSI_NORMAL, cSource->GetName(), fstat1,cTarget->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactD->m_id,ANSI_NORMAL,cTarget->GetObjectColor(),ANSI_NORMAL);
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			} else if (cContactS->status == DETECTED && cContactD->status == IDENTIFIED) {
				sprintf(tbuf, "%s[%s%s%d%s%s]%s - Unknown contact fires and %s the %s",cSource->GetObjectColor(),ANSI_NORMAL,ANSI_HILITE,cContactS->m_id,ANSI_NORMAL,cSource->GetObjectColor(),ANSI_NORMAL, fstat1, cTarget->GetName());
				cCTarget->HandleMessage(tbuf, MSG_SENSOR, (long *)cCTarget);
			}

	}
	
	
	
	
	
	if (dDistance >= range)
    {
		if (dbUser != NOTHING)
			hsStdError(
			dbUser,
			"Your shot dissipates short of its target.");

		strcpy(tbuf,
			"An incoming energy shot has missed us.");
		cTarget->HandleMessage(tbuf, MSG_COMBAT, (long *)cSource);
	}
    else if (iAttackRoll > iDefendRoll)
	{
		// The weapon hits!
		// Determine strength based on base weapon
		// strength and range to target.
		int strength;

		strength = GetStrength();
		if (dDistance > (range * .333))
		{
			strength = (int)(strength * 
				(.333 + (1 - (dDistance / (range + .0001)))));
		}

		// If iSysType is not HSS_NOTYPE, then do a roll
		// against the accuracy of the weapon to see if
		// the system gets hit.
		if (iSysType != HSS_NOTYPE)
		{
			UINT ARoll, SRoll;
		
			ARoll = getrandom(GetAccuracy());
			SRoll = getrandom(10);

			if (SRoll > ARoll)
				iSysType = HSS_NOTYPE; // Didn't succeed
		}

		// Tell the target to take damage
		cTarget->HandleDamage(cSource, this, strength,
			cConsole, iSysType);
	
	}
	else
	{
		// The weapon misses. :(
		if (dbUser != NOTHING)
			hsStdError(dbUser,
			"Your shot skims past your target and out into space.");

		strcpy(tbuf,
			"An incoming energy shot has missed us.");
		cTarget->HandleMessage(tbuf, MSG_COMBAT, (long *)cSource);
	}

	Regenerate();
}