void CThreatMap::AddEnemyMetal(const CEnemyUnit* e, const float scale) { CCircuitDef* cdef = e->GetCircuitDef(); assert(cdef != nullptr); const float cost = cdef->GetCost() * scale; if (cdef->IsAbleToFly()) { airMetal += cost; } else if (cdef->IsMobile()) { STerrainMapMobileType* mt = circuit->GetTerrainManager()->GetMobileTypeById(cdef->GetMobileId()); if (mt->maxElevation > SQUARE_SIZE * 5) { landMetal += cost; } if (mt->minElevation < -SQUARE_SIZE * 5) { waterMetal += cost; } } else { STerrainMapImmobileType* it = circuit->GetTerrainManager()->GetImmobileTypeById(cdef->GetImmobileId()); if (it->maxElevation > SQUARE_SIZE * 5) { landMetal += cost; } if (it->minElevation < -SQUARE_SIZE * 5) { waterMetal += cost; } if (cdef->HasAntiLand()) { staticMetal += cost; } } }
void CPathFinder::SetMapData(CCircuitUnit* unit, CThreatMap* threatMap, int frame) { CCircuitDef* cdef = unit->GetCircuitDef(); STerrainMapMobileType::Id mobileTypeId = cdef->GetMobileId(); bool* moveArray = (mobileTypeId < 0) ? airMoveArray : moveArrays[mobileTypeId]; float* costArray; if ((unit->GetPos(frame).y < .0f) && !cdef->IsSonarStealth()) { costArray = threatMap->GetAmphThreatArray(); // cloak doesn't work under water } else if (unit->GetUnit()->IsCloaked()) { costArray = threatMap->GetCloakThreatArray(); } else if (cdef->IsAbleToFly()) { costArray = threatMap->GetAirThreatArray(); } else if (cdef->IsAmphibious()) { costArray = threatMap->GetAmphThreatArray(); } else { costArray = threatMap->GetSurfThreatArray(); } micropather->SetMapData(moveArray, costArray); }
void CAllyTeam::Init(CCircuitAI* circuit) { if (initCount++ > 0) { return; } TeamRulesParam* trp = circuit->GetTeam()->GetTeamRulesParamByName("start_box_id"); if (trp != nullptr) { int boxId = trp->GetValueFloat(); startBox = circuit->GetGameAttribute()->GetSetupData().GetStartBox(boxId); delete trp; } metalManager = std::make_shared<CMetalManager>(circuit, &circuit->GetGameAttribute()->GetMetalData()); if (metalManager->HasMetalSpots() && !metalManager->HasMetalClusters() && !metalManager->IsClusterizing()) { metalManager->ClusterizeMetal(); } // Init after parallel clusterization circuit->GetScheduler()->RunParallelTask(CGameTask::emptyTask, std::make_shared<CGameTask>(&CMetalManager::Init, metalManager)); energyLink = std::make_shared<CEnergyGrid>(circuit); defence = std::make_shared<CDefenceMatrix>(circuit); pathfinder = std::make_shared<CPathFinder>(&circuit->GetGameAttribute()->GetTerrainData()); // TODO: Move factory selection into CFactoryManager? // Can't figure how as this should work per ally team. const char* factories[] = { "factorycloak", "factoryamph", "factoryhover", "factoryjump", "factoryshield", "factoryspider", "factorytank", "factoryveh", "factoryplane", "factorygunship", "factoryship", }; const int size = sizeof(factories) / sizeof(factories[0]); factoryBuilds.reserve(size); std::map<STerrainMapMobileType::Id, float> percents; CTerrainData& terrainData = circuit->GetGameAttribute()->GetTerrainData(); const std::vector<STerrainMapImmobileType>& immobileType = terrainData.areaData0.immobileType; const std::vector<STerrainMapMobileType>& mobileType = terrainData.areaData0.mobileType; for (const char* fac : factories) { CCircuitDef* cdef = circuit->GetCircuitDef(fac); STerrainMapImmobileType::Id itId = cdef->GetImmobileId(); if ((itId < 0) || !immobileType[itId].typeUsable) { continue; } STerrainMapMobileType::Id mtId = cdef->GetMobileId(); if (mtId < 0) { factoryBuilds.push_back(cdef->GetId()); percents[cdef->GetId()] = 60.0 + rand() / (float)RAND_MAX * 50.0; } else if (mobileType[mtId].typeUsable) { factoryBuilds.push_back(cdef->GetId()); float shift = rand() / (float)RAND_MAX * 40.0 - 20.0; percents[cdef->GetId()] = mobileType[mtId].areaLargest->percentOfMap + shift; } } auto cmp = [circuit, &percents](const CCircuitDef::Id aId, const CCircuitDef::Id bId) { return percents[aId] > percents[bId]; }; std::sort(factoryBuilds.begin(), factoryBuilds.end(), cmp); }