void CRetreatTask::OnUnitIdle(CCircuitUnit* unit) { CCircuitAI* circuit = manager->GetCircuit(); int frame = circuit->GetLastFrame(); CFactoryManager* factoryManager = circuit->GetFactoryManager(); AIFloat3 haven = (repairer != nullptr) ? repairer->GetPos(frame) : factoryManager->GetClosestHaven(unit); if (haven == -RgtVector) { haven = circuit->GetSetupManager()->GetBasePos(); } if (unit->GetCircuitDef()->IsPlane()) { // force rearm/repair | CMD_FIND_PAD unit->GetUnit()->Fight(haven, UNIT_COMMAND_OPTION_RIGHT_MOUSE_KEY, frame + FRAMES_PER_SEC * 60); return; } const float maxDist = factoryManager->GetAssistDef()->GetBuildDistance(); const AIFloat3& unitPos = unit->GetPos(frame); if (unitPos.SqDistance2D(haven) > maxDist * maxDist) { // TODO: push MoveAction into unit? to avoid enemy fire unit->GetUnit()->MoveTo(haven, UNIT_COMMAND_OPTION_RIGHT_MOUSE_KEY, frame + FRAMES_PER_SEC * 1); // TODO: Add fail counter? } else { // TODO: push WaitAction into unit // unit->GetUnit()->ExecuteCustomCommand(CMD_PRIORITY, {0.0f}); AIFloat3 pos = unitPos; const float size = SQUARE_SIZE * 16; CTerrainManager* terrainManager = circuit->GetTerrainManager(); float centerX = terrainManager->GetTerrainWidth() / 2; float centerZ = terrainManager->GetTerrainHeight() / 2; pos.x += (pos.x > centerX) ? size : -size; pos.z += (pos.z > centerZ) ? size : -size; AIFloat3 oldPos = pos; terrainManager->CorrectPosition(pos); if (oldPos.SqDistance2D(pos) > SQUARE_SIZE * SQUARE_SIZE) { pos = unitPos; pos.x += (pos.x > centerX) ? -size : size; pos.z += (pos.z > centerZ) ? -size : size; } CTerrainManager::TerrainPredicate predicate = [unitPos](const AIFloat3& p) { return unitPos.SqDistance2D(p) > SQUARE(SQUARE_SIZE * 8); }; pos = terrainManager->FindBuildSite(unit->GetCircuitDef(), pos, maxDist, UNIT_COMMAND_BUILD_NO_FACING, predicate); unit->GetUnit()->PatrolTo(pos); IUnitAction* act = static_cast<IUnitAction*>(unit->End()); if (act->IsAny(IUnitAction::Mask::MOVE | IUnitAction::Mask::FIGHT)) { static_cast<ITravelAction*>(act)->SetFinished(true); } } }
void CDefendTask::Execute(CCircuitUnit* unit) { CCircuitAI* circuit = manager->GetCircuit(); CTerrainManager* terrainManager = circuit->GetTerrainManager(); AIFloat3 pos = utils::get_radial_pos(position, SQUARE_SIZE * 32); terrainManager->CorrectPosition(pos); pos = terrainManager->FindBuildSite(unit->GetCircuitDef(), pos, 300.0f, UNIT_COMMAND_BUILD_NO_FACING); TRY_UNIT(circuit, unit, unit->GetUnit()->Fight(pos, UNIT_COMMAND_OPTION_RIGHT_MOUSE_KEY, circuit->GetLastFrame() + FRAMES_PER_SEC * 60); unit->GetUnit()->SetWantedMaxSpeed(MAX_UNIT_SPEED); ) }
void CBReclaimTask::Update() { if (!isMetal) { return; } CCircuitAI* circuit = manager->GetCircuit(); if (circuit->GetEconomyManager()->IsMetalFull()) { manager->AbortTask(this); } else if (!units.empty()) { /* * Update reclaim position */ // FIXME: Works only with 1 task per worker CCircuitUnit* unit = *units.begin(); int frame = circuit->GetLastFrame(); const AIFloat3& pos = unit->GetPos(frame); auto enemies = std::move(circuit->GetCallback()->GetEnemyUnitsIn(pos, 300.0f)); if (!enemies.empty()) { for (Unit* enemy : enemies) { if ((enemy != nullptr) && enemy->IsBeingBuilt()) { unit->GetUnit()->ReclaimUnit(enemy, UNIT_COMMAND_OPTION_INTERNAL_ORDER, frame + FRAMES_PER_SEC * 60); utils::free_clear(enemies); return; } } utils::free_clear(enemies); } auto features = std::move(circuit->GetCallback()->GetFeaturesIn(pos, 500.0f)); if (!features.empty()) { CTerrainManager* terrainManager = circuit->GetTerrainManager(); circuit->GetThreatMap()->SetThreatType(unit); AIFloat3 reclPos; float minSqDist = std::numeric_limits<float>::max(); Resource* metalRes = circuit->GetEconomyManager()->GetMetalRes(); for (Feature* feature : features) { AIFloat3 featPos = feature->GetPosition(); terrainManager->CorrectPosition(featPos); // Impulsed flying feature if (!terrainManager->CanBuildAt(unit, featPos)) { continue; } FeatureDef* featDef = feature->GetDef(); float reclaimValue = featDef->GetContainedResource(metalRes)/* * feature->GetReclaimLeft()*/; delete featDef; if (reclaimValue < 1.0f) { continue; } float sqDist = pos.SqDistance2D(featPos); if (sqDist < minSqDist) { reclPos = featPos; minSqDist = sqDist; } } if (minSqDist < std::numeric_limits<float>::max()) { const float radius = 8.0f; // unit->GetCircuitDef()->GetBuildDistance(); unit->GetUnit()->ReclaimInArea(reclPos, radius, UNIT_COMMAND_OPTION_INTERNAL_ORDER, frame + FRAMES_PER_SEC * 60); } utils::free_clear(features); } } }