void CThreatMap::SetEnemyUnitRange(CEnemyUnit* e) const { CCircuitDef* cdef = e->GetCircuitDef(); assert(cdef != nullptr); const int slack = DEFAULT_SLACK * (cdef->IsMobile() ? 4 : 2); int range; int maxRange; range = cdef->HasAntiAir() ? ((int)cdef->GetMaxRange(CCircuitDef::RangeType::AIR) + slack) / squareSize : 0; e->SetRange(CEnemyUnit::RangeType::AIR, range); maxRange = range; range = cdef->HasAntiLand() ? ((int)cdef->GetMaxRange(CCircuitDef::RangeType::LAND) + slack) / squareSize : 0; e->SetRange(CEnemyUnit::RangeType::LAND, range); maxRange = std::max(maxRange, range); range = cdef->HasAntiWater() ? ((int)cdef->GetMaxRange(CCircuitDef::RangeType::WATER) + slack) / squareSize : 0; e->SetRange(CEnemyUnit::RangeType::WATER, range); maxRange = std::max(maxRange, range); e->SetRange(CEnemyUnit::RangeType::MAX, maxRange); e->SetRange(CEnemyUnit::RangeType::CLOAK, GetCloakRange(e)); }
void IFighterTask::OnUnitDamaged(CCircuitUnit* unit, CEnemyUnit* attacker) { CCircuitAI* circuit = manager->GetCircuit(); int frame = circuit->GetLastFrame(); CCircuitDef* cdef = unit->GetCircuitDef(); Unit* u = unit->GetUnit(); const float healthPerc = u->GetHealth() / u->GetMaxHealth(); if (unit->GetShield() != nullptr) { const float minShield = circuit->GetSetupManager()->GetEmptyShield(); if ((healthPerc > cdef->GetRetreat()) && unit->IsShieldCharged(minShield)) { if (cdef->IsRoleHeavy() && (healthPerc < 0.9f)) { circuit->GetBuilderManager()->EnqueueRepair(IBuilderTask::Priority::NOW, unit); } return; } } else if ((healthPerc > cdef->GetRetreat()) && !unit->IsDisarmed(frame)) { if (cdef->IsRoleHeavy() && (healthPerc < 0.9f)) { circuit->GetBuilderManager()->EnqueueRepair(IBuilderTask::Priority::NOW, unit); } return; } else if (healthPerc < 0.2f) { // stuck units workaround: they don't shoot and don't see distant threat CRetreatTask* task = manager->GetCircuit()->GetMilitaryManager()->EnqueueRetreat(); manager->AssignTask(unit, task); return; } CThreatMap* threatMap = circuit->GetThreatMap(); const float range = cdef->GetMaxRange(); if ((target == nullptr) || !target->IsInLOS()) { CRetreatTask* task = circuit->GetMilitaryManager()->EnqueueRetreat(); manager->AssignTask(unit, task); return; } const AIFloat3& pos = unit->GetPos(frame); if ((target->GetPos().SqDistance2D(pos) > SQUARE(range)) || (threatMap->GetThreatAt(unit, pos) * 2 > threatMap->GetUnitThreat(unit))) { CRetreatTask* task = circuit->GetMilitaryManager()->EnqueueRetreat(); manager->AssignTask(unit, task); return; } cowards.insert(unit); }