int BrigadeClass::UpdateParentStatistics (void) { GridIndex nx,ny,x,y; int engaged=0,combat=0,loss=0,te=0; Unit e; // Update unit wide statistics. NOTE: some delay here- since elements are unmoved. nx = ny = te = 0; e = GetFirstUnitElement(); while (e) { if (e->Engaged()) engaged = 1; if (e->Combat()) combat = 1; if (e->Losses()) loss = 1; e->GetLocation(&x,&y); // nx += x; // ny += y; if (!nx && !ny) e->GetLocation(&nx,&ny); te++; e = GetNextUnitElement(); } if (!te) { KillUnit(); return 0; } if (!engaged) { SetEngaged(0); SetTarget(NULL); } SetEngaged(engaged); SetCombat(combat); SetLosses(loss); // Set our new averaged position // x = nx / te; // y = ny / te; // SetLocation(x,y); ShiAssert (nx && ny); // Set our position to our first element SetLocation(nx,ny); return te; }
int TaskForceClass::ChooseTarget (void) { FalconEntity *artTarget,*react_against=NULL,*air_react_against=NULL; CampEntity e; float d,react_distance,air_react_distance; int react,best_reaction=1,best_air_react=1,combat,retval=0,pass=0,spot=0,estr=0,capture=0,nomove=0; int search_dist; Team who; if (IsChecked()) return Engaged(); who = GetTeam(); react_distance = air_react_distance = 9999.0F; #ifdef DEBUG DWORD timec = GetTickCount(); #endif // Special case for fire support if (Targeted()) artTarget = GetTarget(); // Save our target else artTarget = NULL; SetEngaged(0); SetCombat(0); SetChecked(); search_dist = GetDetectionRange(Air); if (search_dist < MAX_GROUND_SEARCH) search_dist = MAX_GROUND_SEARCH; #ifdef VU_GRID_TREE_Y_MAJOR VuGridIterator detit(RealUnitProxList,YPos(),XPos(),(BIG_SCALAR)GridToSim(search_dist)); #else VuGridIterator detit(RealUnitProxList,XPos(),YPos(),(BIG_SCALAR)GridToSim(search_dist)); #endif // CalculateSOJ(detit); 2002-02-19 REMOVED BY S.G. eFalcon 1.10 SOJ code removed e = (CampEntity)detit.GetFirst(); while (e) { if (GetRoE(who,e->GetTeam(),ROE_GROUND_FIRE) == ROE_ALLOWED) { combat = 0; react = DetectVs(e,&d,&combat,&spot); if (!e->IsFlight() && react >= best_reaction && d < react_distance) { // React vs a ground/Naval target best_reaction = react; react_distance = d; react_against = e; SetEngaged(1); SetCombat(combat); } else if (e->IsFlight() && react >= best_air_react && d < air_react_distance) { // React vs an air target - best_air_react = react; air_react_distance = d; air_react_against = e; if (!e->IsAggregate()) { // Pick a specific aircraft in the flight if it's deaggregated CampEnterCriticalSection(); if (e->GetComponents()) { VuListIterator cit(e->GetComponents()); FalconEntity *fe; float rsq,brsq=FLT_MAX; fe = (FalconEntity *)cit.GetFirst(); while (fe) { rsq = DistSqu(XPos(),YPos(),fe->XPos(),fe->YPos()); if (rsq < brsq) { air_react_against = fe; air_react_distance = (float)sqrt(rsq); brsq = rsq; } fe = (FalconEntity *)cit.GetNext(); } } CampLeaveCriticalSection(); } // Make sure our radar is on (if we have one) if (!IsEmitting() && class_data->RadarVehicle < 255 && GetNumVehicles(class_data->RadarVehicle)) SetEmitting(1); SetEngaged(1); SetCombat(combat); } } e = (CampEntity)detit.GetNext(); } SetOdds ((GetTotalVehicles() * 10) / (estr+10)); if (!Parent() && best_reaction > 1) EngageParent(this,react_against); if (air_react_against) { SetAirTarget(air_react_against); retval = 1; } if (react_against) { SetTarget(react_against); SetTargeted(0); retval = 1; } else if (artTarget && (!artTarget->IsUnit() || ((Unit)artTarget)->Engaged()) && orders == GORD_SUPPORT) { // Keep blowing away this target until the target gets out of range, disengages, or we get new orders // (Target will get reset after a null DoCombat result) SetTarget(artTarget); SetTargeted(1); SetEngaged(1); SetCombat(1); return -1; // We want to sit here and shoot until we can't any longer } if (nomove) return -1; return retval; }
int TaskForceClass::DoCombat (void) { int combat; SetCombatTime(TheCampaign.CurrentTime); #if 0 // JPO mthis stuff now done in Choose Target - like Battalion // KCK: Super simple targetting (c) Team who = GetTeam(); CampEntity e; FalconEntity *react_against=NULL,*air_react_against=NULL; int react,spot,best_reaction=1,best_air_react=1; int search_dist; float react_distance,air_react_distance,d; react_distance = air_react_distance = 9999.0F; SetEngaged(0); SetCombat(0); SetChecked(); search_dist = GetDetectionRange(Air); #ifdef VU_GRID_TREE_Y_MAJOR VuGridIterator detit(RealUnitProxList,YPos(),XPos(),(BIG_SCALAR)GridToSim(search_dist)); #else VuGridIterator detit(RealUnitProxList,XPos(),YPos(),(BIG_SCALAR)GridToSim(search_dist)); #endif e = (CampEntity)detit.GetFirst(); while (e) { if (GetRoE(who,e->GetTeam(),ROE_GROUND_FIRE) == ROE_ALLOWED) { combat = 0; react = DetectVs(e,&d,&combat,&spot); if (!e->IsFlight() && react >= best_reaction && d < react_distance) { // React vs a ground/Naval target best_reaction = react; react_distance = d; react_against = e; SetEngaged(1); SetCombat(combat); } else if (e->IsFlight() && react >= best_air_react && d < air_react_distance) { // React vs an air target - best_air_react = react; air_react_distance = d; air_react_against = e; if (!e->IsAggregate()) { // Pick a specific aircraft in the flight if it's deaggregated CampEnterCriticalSection(); if (e->GetComponents()) { VuListIterator cit(e->GetComponents()); FalconEntity *fe; float rsq,brsq=FLT_MAX; fe = (FalconEntity *)cit.GetFirst(); while (fe) { rsq = DistSqu(XPos(),YPos(),fe->XPos(),fe->YPos()); if (rsq < brsq) { air_react_against = fe; air_react_distance = (float)sqrt(rsq); brsq = rsq; } fe = (FalconEntity *)cit.GetNext(); } } CampLeaveCriticalSection(); } SetEngaged(1); SetCombat(combat); } } e = (CampEntity)detit.GetNext(); } if (air_react_against) SetAirTarget(air_react_against); if (react_against) SetTarget(react_against); #endif if (Engaged()) { FalconEntity *e = GetTarget(); FalconEntity *a = GetAirTarget(); // Check vs our Ground Target if (!e) SetTarget(NULL); else { if (Combat() && IsAggregate()) { combat = ::DoCombat(this,e); if (combat <= 0 || Targeted()) SetTargeted(0); } } // Check vs our Air Target if (!a) SetAirTarget(NULL); else if (Combat() && IsAggregate()) { combat = ::DoCombat(this,a); if (combat < 0) SetAirTarget(NULL); // Clear targeting data so we can look for another } } return 0; }
void CombatManager::AttackSomeone(gemActor *attacker,gemObject *target,Stance stance) { psCharacter *attacker_character = attacker->GetCharacterData(); //we don't allow an overweight or defeated char to fight if (attacker->GetMode() == PSCHARACTER_MODE_DEFEATED || attacker->GetMode() == PSCHARACTER_MODE_OVERWEIGHT) return; if (attacker->GetMode() == PSCHARACTER_MODE_COMBAT) // Already fighting { SetCombat(attacker,stance); // switch stance from Bloody to Defensive, etc. return; } else { if (attacker->GetMode() == PSCHARACTER_MODE_SIT) //we are sitting force the char to stand attacker->Stand(); attacker_character->ResetSwings(csGetTicks()); } // Indicator of whether any weapons are available to attack with bool startedAttacking=false; bool haveWeapon=false; // Step through each current slot and queue events for all that can attack for (int slot=0; slot<PSCHARACTER_SLOT_BULK1; slot++) { // See if this slot is able to attack if (attacker_character->Inventory().CanItemAttack((INVENTORY_SLOT_NUMBER) slot)) { INVENTORY_SLOT_NUMBER weaponSlot = (INVENTORY_SLOT_NUMBER) slot; // Get the data for the "weapon" that is used in this slot psItem *weapon=attacker_character->Inventory().GetEffectiveWeaponInSlot(weaponSlot); csString response; if (weapon!=NULL && weapon->CheckRequirements(attacker_character,response) ) { haveWeapon = true; Debug5(LOG_COMBAT,attacker->GetClientID(),"%s tries to attack with %s weapon %s at %.2f range", attacker->GetName(),(weapon->GetIsRangeWeapon()?"range":"melee"),weapon->GetName(), attacker->RangeTo(target,false)); Debug3(LOG_COMBAT,attacker->GetClientID(),"%s started attacking with %s",attacker->GetName(), weapon->GetName()); // start the ball rolling QueueNextEvent(attacker,weaponSlot,target,attacker->GetClientID(),target->GetClientID()); startedAttacking=true; } else { if( weapon && attacker_character->GetActor()) { Debug3(LOG_COMBAT,attacker->GetClientID(),"%s tried attacking with %s but can't use it.", attacker->GetName(),weapon->GetName()); #ifdef COMBAT_DEBUG psserver->SendSystemError(attacker_character->GetActor()->GetClientID(), response); #endif } } } } /* Only notify the target if any attacks were able to start. Otherwise there are * no available weapons with which to attack. */ if (haveWeapon) { if (startedAttacking) { // The attacker should now enter combat mode if (attacker->GetMode() != PSCHARACTER_MODE_COMBAT) { SetCombat(attacker,stance); } } else { psserver->SendSystemError(attacker->GetClientID(),"You are too far away to attack!"); return; } } else { psserver->SendSystemError(attacker->GetClientID(),"You have no weapons equipped!"); return; } }