// Gets the fuel system for the engines. Replaces the m_fuel_source variable. CHSFuelSystem* CHSSysEngines::GetFuelSource(void) { CHSShip *cShip = (CHSShip *) GetOwnerObject(); if (!cShip) return NULL; return (CHSFuelSystem *)cShip->GetSystems().GetSystem(HSS_FUEL_SYSTEM); }
void CHSSysEngines::CutPower(HS_INT32 level) { if (level == 0) { if (GetOwnerObject() && GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *cShip; cShip = (CHSShip *) GetOwnerObject(); if (hsInterface.AtrGet(cShip->GetDbref(), "HSMSG_ENGINES_CUT")) { HS_DBREF idx = cShip->GetDbref(); char *msg = hsInterface.EvalExpression(hsInterface.m_buffer, idx, idx, idx); cShip->NotifySrooms(msg); } else { cShip->NotifySrooms(HSCONF.engines_cut); } } } }
void CHSDamCon::UnassignCrew(HS_DBREF player, int iCrew) { // Be certain this is a valid crew ID. if ((iCrew < 1) || (iCrew > (int) GetNumCrews())) { return; } // Grab this crew's structure from the vector. THSDamageCrew & rtCrew = m_vecCrews[iCrew]; // Only one crew can be assigned to a system at any one time. HS_INT32 iNumCrews = GetNumCrews(); for (int idx = 0; idx < iNumCrews; idx++) { // If this crew is the one we're assigning, ignore it. if (idx == iCrew) { rtCrew.pAssignedTo = NULL; rtCrew.iSecondsLeft = 0; if (GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *pOwnerShip = static_cast <CHSShip * > (GetOwnerObject()); pOwnerShip->NotifyConsoles(hsInterface. HSPrintf( "%s%s-%s Damage Control crew %i now available.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL, iCrew), MSG_ENGINEERING); } } } }
// Gets the fuel system for the engines. Replaces the m_fuel_source variable. CHSFuelSystem* CHSJumpDrive::GetFuelSource(void) { CHSShip *cShip = (CHSShip *) GetOwnerObject(); if (!cShip) { return NULL; } return (CHSFuelSystem *)cShip->GetSystems().GetSystem(HSS_FUEL_SYSTEM); }
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 CHSJumpDrive::DoCycle() { float rate; // Do base stuff first CHSEngSystem::DoCycle(); // Charge jumpers? if ((GetCurrentPower() > 0) && (m_fChargeLevel < 100)) { rate = GetChargeRate(true); if (rate > 0) { m_fChargeLevel += rate; // Make sure we don't overcharge if (m_fChargeLevel > 100) { m_fChargeLevel = 100; } if (m_fChargeLevel == 100) { if (GetOwnerObject() && GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *cShip; cShip = (CHSShip *) GetOwnerObject(); if (cShip) { cShip->NotifyConsoles(hsInterface. HSPrintf ("%s%s-%s Jump Drive charged.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL), MSG_ENGINEERING); } } } } } // If engaged, consume fuel. if (m_bEngaged) { ConsumeFuelBySpeed(m_uiSublightSpeed * m_iJumpSpeedMultiplier); } }
void CHSSysThrusters::PowerUp(int level) { if (!GetOwnerObject()) { return; } if (GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *cShip; cShip = (CHSShip *) GetOwnerObject(); if (hsInterface. AtrGet(cShip->GetDbref(), "HSMSG_THRUSTERS_ACTIVATING")) { char *msg = hsInterface.EvalExpression(hsInterface.m_buffer, cShip->GetDbref(), cShip->GetDbref(), cShip->GetDbref()); cShip->NotifySrooms(msg); } else { cShip->NotifySrooms(HSCONF.thrusters_activating); } } }
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!!"); } } }
void CHSJumpDrive::CutPower(HS_INT32 level) { if (level == 0) { if (GetOwnerObject() && (GetOwnerObject()->GetType() == HST_SHIP)) { CHSShip *cShip; cShip = (CHSShip *) GetOwnerObject(); if (hsInterface.AtrGet(cShip->GetDbref(), "HSMSG_JUMPERS_CUT")) { char *msg = hsInterface.EvalExpression(hsInterface.m_buffer, cShip->GetDbref(), cShip->GetDbref(), cShip->GetDbref()); cShip->NotifySrooms(msg); } else { cShip->NotifySrooms(HSCONF.jumpers_cut); } } // Set charge level to 0. m_fChargeLevel = 0; // If jumpers are engaged and power is set to 0, then // disengage. if (GetEngaged()) { HS_INT8 tbuf[128]; m_bEngaged = false; sprintf(tbuf, "%s%s-%s Jump drive disengaged.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL); if (GetOwnerObject()) { GetOwnerObject()->HandleMessage(tbuf, MSG_ENGINEERING); } } } }
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; }
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 CHSDamCon::AssignCrew(HS_DBREF player, int iCrew, CHSEngSystem * pSystem) { // Be certain this is a valid crew ID. if ((iCrew < 1) || (iCrew > (int) GetNumCrews())) { return; } // Grab this crew's structure from the vector. THSDamageCrew & rtCrew = m_vecCrews[iCrew]; // If we're assigning to a valid system, try that. // Otherwise, unassign this crew. if (pSystem) { // Only one crew can be assigned to a system at any one time. HS_INT32 iNumCrews = GetNumCrews(); for (int idx = 0; idx < iNumCrews; idx++) { // If this crew is the one we're assigning, ignore it. if (idx == iCrew) { continue; } THSDamageCrew & rtAssignedCrew = m_vecCrews[idx]; // Is this crew assigned to the system we want? if (rtAssignedCrew.pAssignedTo == pSystem) { hsStdError(player, "A repair crew is already working on that system."); return; } } // This crew is now assigned. rtCrew.pAssignedTo = pSystem; rtCrew.iSecondsLeft = HSCONF.damage_repair_time; if (0 == rtCrew.iSecondsLeft) { rtCrew.iSecondsLeft = 1; } if (GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *pOwnerShip = static_cast < CHSShip * >(GetOwnerObject()); pOwnerShip->NotifyConsoles(hsInterface. HSPrintf ("%s%s-%s Damage Control crew %i assigned to %s.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL, iCrew, pSystem->GetName()), MSG_ENGINEERING); } } else { // This crew is unassigned. rtCrew.pAssignedTo = NULL; rtCrew.iSecondsLeft = 0; if (GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *pOwnerShip = static_cast < CHSShip * >(GetOwnerObject()); pOwnerShip->NotifyConsoles(hsInterface. HSPrintf ("%s%s-%s Damage Control crew %i now idle.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL, iCrew), MSG_ENGINEERING); } } }
void CHSDamCon::DoCycle() { // First we do the basic cycle, stress and such. CHSEngSystem::DoCycle(); // Now we'll just go through our damage crews. HS_INT32 iEfficiency; HS_INT32 iRandNum; // Calculate percentage of power allocated to damage control. if (GetCurrentPower() != 0 && GetOptimalPower(false) != 0) { iEfficiency = (int) (100 * ((GetCurrentPower() * 1.00) / (GetOptimalPower(false) * 1.00))); } else { iEfficiency = 0; } iRandNum = hsInterface.GetRandom(99) + 1; // If we roll a random number greater than the power allocated to damage // control, then this round of damage control goes into the toilet. if (iRandNum > iEfficiency) { return; } // Insure that our number of crews matches the vector size. m_vecCrews.resize(GetNumCrews() + 1); // Run through all of our damage crews. // Those that are assigned get their time remaining reduced. unsigned int idx; for (idx = 1; idx <= GetNumCrews(); idx++) { THSDamageCrew & rtCrew = m_vecCrews[idx]; // Is this crew working on anything? if (!rtCrew.pAssignedTo) { continue; } // This crew's time decreases. if (rtCrew.iSecondsLeft > 0) { rtCrew.iSecondsLeft--; } // If the crew is done working, reduce the damage on the system. if (rtCrew.iSecondsLeft <= 0) { rtCrew.pAssignedTo->ReduceDamage(); // If this system is fully repaired, notify everyone, and pull this // crew off duty. if (rtCrew.pAssignedTo->GetDamageLevel() == DMG_NONE) { // If this system is part of a ship, // notify all consoles that repairs are complete. if (GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *pOwnerShip = static_cast < CHSShip * >(GetOwnerObject()); pOwnerShip->NotifyConsoles(hsInterface. HSPrintf ("%s%s-%s %s repairs complete.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL, rtCrew.pAssignedTo-> GetName()), MSG_ENGINEERING); } // This crew is no longer assigned. rtCrew.pAssignedTo = NULL; } else { // This system is not repaired. Reassign the crew to another // round of repairs. rtCrew.iSecondsLeft = HSCONF.damage_repair_time; if (0 == rtCrew.iSecondsLeft) { rtCrew.iSecondsLeft = 1; } if (GetOwnerObject()->GetType() == HST_SHIP) { CHSShip *pOwnerShip = static_cast < CHSShip * >(GetOwnerObject()); pOwnerShip->NotifyConsoles(hsInterface. HSPrintf ("%s%s-%s %s repairs incomplete, continuing repairs.", ANSI_HILITE, ANSI_GREEN, ANSI_NORMAL, rtCrew.pAssignedTo-> GetName()), MSG_ENGINEERING); } } } } }
// 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(); }