void CDefendTask::FindTarget() { CCircuitAI* circuit = manager->GetCircuit(); auto enemies = std::move(circuit->GetCallback()->GetEnemyUnitsIn(GetPosition(), radius)); if (enemies.empty()) { enemies = std::move(circuit->GetCallback()->GetEnemyUnitsIn(circuit->GetSetupManager()->GetBasePos(), radius)); if (enemies.empty()) { SetTarget(nullptr); return; } } CEnemyUnit* bestTarget = nullptr; float minSqDist = std::numeric_limits<float>::max(); for (Unit* e : enemies) { if (e == nullptr) { continue; } CEnemyUnit* enemy = circuit->GetEnemyUnit(e); if (enemy != nullptr) { float sqDist = GetPosition().SqDistance2D(enemy->GetPos()); if (minSqDist > sqDist) { minSqDist = sqDist; bestTarget = enemy; } } delete e; } SetTarget(bestTarget); }
void CAttackTask::Execute(CCircuitUnit* unit, bool isUpdating) { Unit* u = unit->GetUnit(); CCircuitAI* circuit = manager->GetCircuit(); CTerrainManager* terrainManager = circuit->GetTerrainManager(); float minSqDist; CEnemyUnit* bestTarget = FindBestTarget(unit, minSqDist); if (bestTarget == nullptr) { if (!isUpdating) { float x = rand() % (terrainManager->GetTerrainWidth() + 1); float z = rand() % (terrainManager->GetTerrainHeight() + 1); position = AIFloat3(x, circuit->GetMap()->GetElevationAt(x, z), z); } } else { position = bestTarget->GetPos(); float range = u->GetMaxRange(); if (minSqDist < range * range) { u->Attack(bestTarget->GetUnit(), UNIT_COMMAND_OPTION_INTERNAL_ORDER, circuit->GetLastFrame() + FRAMES_PER_SEC * 300); return; } } u->Fight(position, UNIT_COMMAND_OPTION_INTERNAL_ORDER, circuit->GetLastFrame() + FRAMES_PER_SEC * 300); }
CEnemyUnit* CAttackTask::FindBestTarget(CCircuitUnit* unit, float& minSqDist) { CCircuitAI* circuit = manager->GetCircuit(); CTerrainManager* terrainManager = circuit->GetTerrainManager(); CThreatMap* threatMap = circuit->GetThreatMap(); const AIFloat3& pos = unit->GetUnit()->GetPos(); STerrainMapArea* area = unit->GetArea(); float power = threatMap->GetUnitThreat(unit); int canTargetCat = unit->GetCircuitDef()->GetTargetCategory(); CEnemyUnit* bestTarget = nullptr; minSqDist = std::numeric_limits<float>::max(); threatMap->SetThreatType(unit); const CCircuitAI::EnemyUnits& enemies = circuit->GetEnemyUnits(); for (auto& kv : enemies) { CEnemyUnit* enemy = kv.second; if (enemy->IsHidden() || (threatMap->GetThreatAt(enemy->GetPos()) >= power) || !terrainManager->CanMoveToPos(area, enemy->GetPos())) { continue; } if (((canTargetCat & circuit->GetWaterCategory()) == 0) && (enemy->GetPos().y < -SQUARE_SIZE * 4)) { continue; } CCircuitDef* edef = enemy->GetCircuitDef(); if ((edef != nullptr) && ((edef->GetCategory() & canTargetCat) == 0)) { continue; } float sqDist = pos.SqDistance2D(enemy->GetPos()); if (sqDist < minSqDist) { bestTarget = enemy; minSqDist = sqDist; } } return bestTarget; }