示例#1
0
void CEnergyGrid::Init()
{
	for (auto& kv : circuit->GetCircuitDefs()) {
		const std::map<std::string, std::string>& customParams = kv.second->GetUnitDef()->GetCustomParams();
		auto it = customParams.find("pylonrange");
		if (it != customParams.end()) {
			pylonRanges[kv.first] = utils::string_to_float(it->second);
		}
	}
	// FIXME: const names
	const char* names[] = {"armestor", "armsolar", "armwin"};
	for (const char* name : names) {
		CCircuitDef* cdef = circuit->GetCircuitDef(name);
		rangePylons[pylonRanges[cdef->GetId()]] = cdef->GetId();
	}

	CMetalManager* metalManager = circuit->GetMetalManager();
	const CMetalData::Clusters& clusters = metalManager->GetClusters();
	const CMetalData::Graph& clusterGraph = metalManager->GetGraph();

	linkedClusters.resize(clusters.size(), false);

	links.reserve(boost::num_edges(clusterGraph));
	CMetalData::Graph::edge_iterator edgeIt, edgeEnd;
	std::tie(edgeIt, edgeEnd) = boost::edges(clusterGraph);
	for (; edgeIt != edgeEnd; ++edgeIt) {
		const CMetalData::EdgeDesc& edgeId = *edgeIt;
		int idx0 = boost::source(edgeId, clusterGraph);
		int idx1 = boost::target(edgeId, clusterGraph);
		links.emplace_back(idx0, clusters[idx0].geoCentr, idx1, clusters[idx1].geoCentr);
	}
	linkIt = boost::make_iterator_property_map(&links[0], boost::get(&CMetalData::SEdge::index, clusterGraph));

	ownedClusters = CMetalData::Graph(boost::num_vertices(clusterGraph));
}
示例#2
0
CCircuitDef* CAllyTeam::GetFactoryToBuild(CCircuitAI* circuit)
{
	for (int i = 0; i < factoryBuilds.size(); ++i) {
		CCircuitDef* cdef = circuit->GetCircuitDef(factoryBuilds[factoryIdx]);
		if (cdef->IsAvailable()) {
			return cdef;
		}
		AdvanceFactoryIdx();
	}
	return nullptr;
}
示例#3
0
void CBWaitTask::OnUnitDamaged(CCircuitUnit* unit, CEnemyUnit* attacker)
{
	CCircuitAI* circuit = manager->GetCircuit();
	const int frame = circuit->GetLastFrame();
	CCircuitDef* cdef = unit->GetCircuitDef();
	const float healthPerc = unit->GetHealthPercent();
	if ((healthPerc > cdef->GetRetreat()) && !unit->IsDisarmed(frame)) {
		return;
	}

	CRetreatTask* task = manager->GetCircuit()->GetBuilderManager()->EnqueueRetreat();
	manager->AssignTask(unit, task);
}
示例#4
0
void CEnergyGrid::ReadConfig()
{
	const Json::Value& root = circuit->GetSetupManager()->GetConfig();
	const std::string& cfgName = circuit->GetSetupManager()->GetConfigName();
	const Json::Value& pylon = root["economy"]["energy"]["pylon"];
	for (const Json::Value& pyl : pylon) {
		CCircuitDef* cdef = circuit->GetCircuitDef(pyl.asCString());
		if (cdef == nullptr) {
			circuit->LOG("CONFIG %s: has unknown UnitDef '%s'", cfgName.c_str(), pyl.asCString());
		} else {
			rangePylons[pylonRanges[cdef->GetId()]] = cdef->GetId();
		}
	}
}
示例#5
0
void CSuperTask::Update()
{
    CCircuitAI* circuit = manager->GetCircuit();
    int frame = circuit->GetLastFrame();
    CCircuitUnit* unit = *units.begin();
    CCircuitDef* cdef = unit->GetCircuitDef();
    if (cdef->IsHoldFire()) {
        if (targetFrame + (cdef->GetReloadTime() + TARGET_DELAY) > frame) {
            if ((State::ENGAGE == state) && (targetFrame + TARGET_DELAY <= frame)) {
                TRY_UNIT(circuit, unit,
                         unit->GetUnit()->Stop();
                        )
                state = State::ROAM;
            }
            return;
        }
示例#6
0
void IFighterTask::AssignTo(CCircuitUnit* unit)
{
	IUnitTask::AssignTo(unit);

	CCircuitDef* cdef = unit->GetCircuitDef();
	attackPower += cdef->GetPower();
	if (unit->GetShield() != nullptr) {
		shields.insert(unit);
	}

	if (unit->HasDGun()) {
		const float range = std::max(cdef->GetDGunRange() * 1.1f, cdef->GetLosRadius());
		CDGunAction* act = new CDGunAction(unit, range);
		unit->PushBack(act);
	}
}
示例#7
0
void CThreatMap::DelEnemyUnit(const CEnemyUnit* e)
{
	CCircuitDef* cdef = e->GetCircuitDef();
	if (cdef == nullptr) {
		DelEnemyUnitAll(e);
		return;
	}

	if (cdef->HasAntiAir()) {
		DelEnemyAir(e);
	}
	if (cdef->HasAntiLand() || cdef->HasAntiWater()) {
		DelEnemyAmph(e);
	}
	DelDecloaker(e);
}
示例#8
0
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;
		}
	}
}
示例#9
0
void CThreatMap::AddEnemyUnit(const CEnemyUnit* e, const float scale)
{
	CCircuitDef* cdef = e->GetCircuitDef();
	if (cdef == nullptr) {
		AddEnemyUnitAll(e, scale);
		return;
	}

	if (cdef->IsAntiAir()) {
		AddEnemyUnit(e, airThreat, scale);
	}
	if (cdef->IsAntiLand()) {
		AddEnemyUnit(e, landThreat, scale);
	}
	if (cdef->IsAntiWater()) {
		AddEnemyUnit(e, waterThreat, scale);
	}
	AddDecloaker(e, scale);
}
示例#10
0
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);
}
示例#11
0
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;
}
示例#12
0
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));
}
示例#13
0
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);
}
示例#14
0
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);
}