void CSReclaimTask::Update() { CCircuitAI* circuit = manager->GetCircuit(); if (circuit->GetEconomyManager()->IsMetalFull()) { manager->AbortTask(this); } else if ((++updCount % 4 == 0) && !units.empty()) { // Check for damaged units CBuilderManager* builderManager = circuit->GetBuilderManager(); CAllyUnit* repairTarget = nullptr; circuit->UpdateFriendlyUnits(); auto us = std::move(circuit->GetCallback()->GetFriendlyUnitsIn(position, radius * 0.9f)); for (Unit* u : us) { CAllyUnit* candUnit = circuit->GetFriendlyUnit(u); if ((candUnit == nullptr) || builderManager->IsReclaimed(candUnit)) { continue; } if (!u->IsBeingBuilt() && (u->GetHealth() < u->GetMaxHealth())) { repairTarget = candUnit; break; } } utils::free_clear(us); if (repairTarget != nullptr) { // Repair task IBuilderTask* task = circuit->GetFactoryManager()->EnqueueRepair(IBuilderTask::Priority::NORMAL, repairTarget); decltype(units) tmpUnits = units; for (CCircuitUnit* unit : tmpUnits) { manager->AssignTask(unit, task); } manager->AbortTask(this); } } }
void IBuilderTask::Update() { CCircuitAI* circuit = manager->GetCircuit(); // for (auto unit : units) { // IUnitAction* action = static_cast<IUnitAction*>(unit->Begin()); // if (action->GetType() == IUnitAction::Type::PRE_BUILD) { // Unit* u = unit->GetUnit(); // const AIFloat3& vel = u->GetVel(); // Resource* metal = circuit->GetEconomyManager()->GetMetalRes(); // if ((vel == ZeroVector) && (u->GetResourceUse(metal) <= 0)) { // // TODO: Something is on build site, get standing units in radius and push them. // } // } // } // FIXME: Replace const 1000.0f with build time? if ((cost > 1000.0f) && (circuit->GetEconomyManager()->GetAvgMetalIncome() < savedIncome * 0.6f)) { manager->AbortTask(this); } }
IBuilderTask::IBuilderTask(ITaskManager* mgr, Priority priority, CCircuitDef* buildDef, const AIFloat3& position, BuildType type, float cost, bool isShake, int timeout) : IUnitTask(mgr, priority, Type::BUILDER) , position(position) , isShake(isShake) , buildDef(buildDef) , buildType(type) , buildPower(.0f) , cost(cost) , target(nullptr) , buildPos(-RgtVector) , facing(UNIT_COMMAND_BUILD_NO_FACING) , nextTask(nullptr) , timeout(timeout) , buildFails(0) { CCircuitAI* circuit = manager->GetCircuit(); lastTouched = circuit->GetLastFrame(); savedIncome = circuit->GetEconomyManager()->GetAvgMetalIncome(); }
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); } } }