map<AIKey,string> CGroupHandler::GetSuitedAis(const CUnitSet& units)
{
	typedef bool (* ISUNITSUITED)(unsigned aiNumber,const UnitDef* unitDef);
	ISUNITSUITED IsUnitSuited;

	map<AIKey,string> suitedAis;
	suitedAis[defaultKey]="default";

	map<AIKey,string>::iterator aai;
	for(aai=availableAI.begin();aai!=availableAI.end();++aai)
	{
		SharedLib *lib;
		const AIKey& aiKey = aai->first;
		lib = SharedLib::Instantiate(aiKey.dllName);
		IsUnitSuited = (ISUNITSUITED)lib->FindAddress("IsUnitSuited");
		bool suited = false;
		CUnitSet::const_iterator ui;
		for(ui=units.begin();ui!=units.end();++ui)
		{
			const UnitDef* ud = (*ui)->unitDef;
			if(IsUnitSuited(aiKey.aiNumber,ud))
			{
				suited = true;
				break;
			}
		}
		if(suited)
			suitedAis[aiKey]=aai->second;
		delete lib;
	}

	lastSuitedAis = suitedAis;
	return suitedAis;
}
CWaitCommandsAI::DeathWait::DeathWait(const Command& cmd)
: Wait(CMD_WAITCODE_DEATHWAIT)
{
	GML_RECMUTEX_LOCK(sel); // DeathWait

	const CUnitSet& selUnits = selectedUnits.selectedUnits;

	if (cmd.params.size() == 1) {
		const int unitID = (int)cmd.params[0];
		if ((unitID < 0) || (static_cast<size_t>(unitID) >= uh->MaxUnits())) {
			return;
		}
		CUnit* unit = uh->units[unitID];
		if (unit == NULL) {
			return;
		}
		if (selUnits.find(unit) != selUnits.end()) {
			return;
		}
		deathUnits.insert(unit);
	}
	else if (cmd.params.size() == 6) {
		const float3 pos0(cmd.params[0], cmd.params[1], cmd.params[2]);
		const float3 pos1(cmd.params[3], cmd.params[4], cmd.params[5]);
		CUnitSet tmpSet;
		SelectAreaUnits(pos0, pos1, tmpSet, false);
		CUnitSet::iterator it;
		for (it = tmpSet.begin(); it != tmpSet.end(); ++it) {
			if (selUnits.find(*it) == selUnits.end()) {
				deathUnits.insert(*it);
			}
		}
		if (deathUnits.empty()) {
			return;
		}
	}
	else {
		return; // unknown param config
	}

	valid = true;
	key = GetNewKey();

	waitUnits = selUnits;

	Command waitCmd(CMD_WAIT, cmd.options);
	waitCmd.params.push_back(code);
	waitCmd.params.push_back(GetFloatFromKey(key));
	selectedUnits.GiveCommand(waitCmd);

	CUnitSet::iterator it;
	for (it = waitUnits.begin(); it != waitUnits.end(); ++it) {
		AddDeathDependence((CObject*)(*it));
	}
	for (it = deathUnits.begin(); it != deathUnits.end(); ++it) {
		AddDeathDependence((CObject*)(*it));
	}

	return;
}
Beispiel #3
0
void CGroup::PostLoad()
{
	CUnitSet unitBackup = units;

	for (CUnitSet::const_iterator ui = unitBackup.begin(); ui != unitBackup.end(); ++ui) {
		units.erase(*ui);
		(*ui)->group = NULL;
	}
}
CUnitSet::iterator CWaitCommandsAI::Wait::RemoveUnitFromSet(CUnitSet::iterator it, CUnitSet& unitSet)
{
	CUnitSet::iterator tmp = it;
	++tmp;
	unitSet.erase(it);
	return tmp;
}
void CWaitCommandsAI::AddTimeWait(const Command& cmd)
{
	GML_RECMUTEX_LOCK(sel); // AddTimeWait

	// save the current selection
	const CUnitSet tmpSet = selectedUnits.selectedUnits;
	CUnitSet::const_iterator it;
	for (it = tmpSet.begin(); it != tmpSet.end(); ++it) {
		InsertWaitObject(TimeWait::New(cmd, *it));
	}
	// restore the selection
	selectedUnits.ClearSelected();
	for (it = tmpSet.begin(); it != tmpSet.end(); ++it) {
		selectedUnits.AddUnit(*it);
	}
}
Beispiel #6
0
bool CProgAndPlay::allUnitsIdled() {
	CUnitSet *tmp = &(teamHandler->Team(gu->myTeam)->units);
	if (tmp->size() == 0)
		return false;
	CUnitSet::iterator it = tmp->begin();
	while (it != tmp->end()) {
		const CCommandAI* commandAI = (*it)->commandAI;
		if (commandAI != NULL) {
			const CCommandQueue* queue = &commandAI->commandQue;
			if (queue->size() > 0)
				return false;
		}
		it++;
	}
	return true;
}
void CWaitCommandsAI::Wait::SendCommand(const Command& cmd,
																				const CUnitSet& unitSet)
{
	GML_RECMUTEX_LOCK(sel); // SendCommand

	if (unitSet.empty()) {
		return;
	}

	const CUnitSet& selUnits = selectedUnits.selectedUnits;
	if (unitSet == selUnits) {
		selectedUnits.GiveCommand(cmd, false);
		return;
	}

	CUnitSet tmpSet = selUnits;
	CUnitSet::const_iterator it;

	selectedUnits.ClearSelected();
	for (it = unitSet.begin(); it != unitSet.end(); ++it) {
		selectedUnits.AddUnit(*it);
	}

	selectedUnits.GiveCommand(cmd, false);

	selectedUnits.ClearSelected();
	for (it = tmpSet.begin(); it != tmpSet.end(); ++it) {
		selectedUnits.AddUnit(*it);
	}
}
void CWaitCommandsAI::DeathWait::SelectAreaUnits(
	const float3& pos0, const float3& pos1, CUnitSet& units, bool enemies)
{
	units.clear();

	const float3 mins(std::min(pos0.x, pos1.x), 0.0f, std::min(pos0.z, pos1.z));
	const float3 maxs(std::max(pos0.x, pos1.x), 0.0f, std::max(pos0.z, pos1.z));

	const std::vector<CUnit*> &tmpUnits = qf->GetUnitsExact(mins, maxs);

	const int count = (int)tmpUnits.size();
	for (int i = 0; i < count; i++) {
		CUnit* unit = tmpUnits[i];
		if (enemies && teamHandler->Ally(unit->allyteam, gu->myAllyTeam)) {
			continue;
		}
		if (!(unit->losStatus[gu->myAllyTeam] & (LOS_INLOS | LOS_INRADAR))) {
			continue;
		}
		units.insert(unit);
	}
}
void CWaitCommandsAI::DeathWait::Update()
{
	if (waitUnits.empty()) {
		delete this;
		return;
	}

	unitPos.clear();

	if (!deathUnits.empty()) {
		return; // more must die
	}

	CUnitSet unblockSet;
	CUnitSet::iterator it = waitUnits.begin();
	while (it != waitUnits.end()) {
		WaitState state = GetWaitState(*it);
		if (state == Active) {
			unblockSet.insert(*it);
			DeleteDeathDependence(*it);
			it = RemoveUnitFromSet(it, waitUnits);
			continue;
		}
		else if (state == Queued) {
			// do nothing
		}
		else if (state == Missing) {
			DeleteDeathDependence(*it);
			it = RemoveUnitFromSet(it, waitUnits);
			continue;
		}
		++it;
	}
	SendWaitCommand(unblockSet);
	if (waitUnits.empty()) {
		delete this;
		return;
	}
}
void CWaitCommandsAI::TimeWait::Update()
{
	if (unit == NULL) {
		delete this;
		return;
	}

	WaitState state = GetWaitState(unit);

	if (state == Active) {
		if (!enabled) {
			enabled = true;
			endFrame = (gs->frameNum + duration);
		}
		else {
			if (endFrame <= gs->frameNum) {
				CUnitSet smallSet;
				smallSet.insert(unit);
				SendWaitCommand(smallSet);
				if (!factory) {
					delete this;
					return;
				} else {
					enabled = false;
				}
			}
		}
	}
	else if (state == Queued) {
		return;
	}
	else if (state == Missing) {
		if (!factory) { // FIXME
			delete this;
			return;
		}
	}
}
void CWaitCommandsAI::SquadWait::Update()
{
	if (buildUnits.empty() && ((int)waitUnits.size() < squadCount)) {
		// FIXME -- unblock remaining waitUnits ?
		delete this;
		return;
	}

	if ((int)waitUnits.size() >= squadCount) {
		CUnitSet unblockSet;
		CUnitSet::iterator it = waitUnits.begin();
		while (it != waitUnits.end()) {
			WaitState state = GetWaitState(*it);
			if (state == Active) {
				unblockSet.insert(*it);
				if ((int)unblockSet.size() >= squadCount) {
					break; // we've got our squad
				}
			}
			else if (state == Queued) {
				// do nothing
			}
			else if (state == Missing) {
				DeleteDeathDependence(*it);
				it = RemoveUnitFromSet(it, waitUnits);
				continue;
			}
			++it;
		}

		if ((int)unblockSet.size() >= squadCount) {
			// FIXME -- rebuild the order queue so
			//          that formations are created?
			SendWaitCommand(unblockSet);
			for (it = unblockSet.begin(); it != unblockSet.end(); ++it) {
				DeleteDeathDependence(*it);
				waitUnits.erase(*it);
			}
		}
	}

	UpdateText();
	// FIXME -- clean builders
}
void CSpawnScript::Update()
{
	switch(gs->frameNum){
	case 0:
		LoadSpawns();

		const std::string startUnit0 = sideParser.GetStartUnit(0);

		if (startUnit0.length() == 0) {
			throw content_error ("Unable to load a startUnit for the first side");
		}

		MapParser mapParser(stupidGlobalMapname);
		if (!mapParser.IsValid()) {
			throw content_error("MapParser: " + mapParser.GetErrorLog());
		}
		float3 startPos0(1000.0f, 80.0f, 1000.0f);
		mapParser.GetStartPos(0, startPos0);

		// Set the TEAM0 startpos as spawnpos if we're supposed to be
		// autonomous, load the commander for the player if not.
		if (autonomous) {
			spawnPos.push_back(startPos0);
		} else {
			unitLoader.LoadUnit(startUnit0, startPos0, 0, false, 0, NULL);
		}

		// load the start positions for teams 1 - 3
		for (int teamID = 1; teamID <= 3; teamID++) {
			float3 sp(1000.0f, 80.0f, 1000.0f);
			mapParser.GetStartPos(teamID, sp);
			spawnPos.push_back(sp);
		}
	}

	if(!spawns.empty()){
		while(curSpawn->frame+frameOffset<gs->frameNum){
			int num = gs->randInt() % spawnPos.size();
			int team = autonomous ? (num & 1) : 1;
			float3 pos;
			float dist=200;
			CFeature* feature;
			do {
				pos=spawnPos[num]+gs->randVector()*dist;
				dist*=1.05f;
			} while (dist < 500 && uh->TestUnitBuildSquare(BuildInfo(curSpawn->name,pos,0),feature,team) != 2);

			// Ignore unit if it really doesn't fit.
			// (within 18 tries, 200*1.05f^18 < 500 < 200*1.05f^19)
			if (dist < 500) {
				CUnit* u = unitLoader.LoadUnit(curSpawn->name, pos, team, false, 0, NULL);

				Unit unit;
				unit.id=u->id;
				unit.target=-1;
				unit.team=team;
				myUnits.push_back(unit);
				if(myUnits.size()==1)
					curUnit=myUnits.begin();
			}

			++curSpawn;
			if(curSpawn==spawns.end()){
				curSpawn=spawns.begin();
				frameOffset+=spawns.back().frame;
			}
		}
	}

	if(!myUnits.empty() && !gs->Team(1 - curUnit->team)->units.empty()) {
		if(uh->units[curUnit->id]){
			if(curUnit->target<0 || uh->units[curUnit->target]==0){
				// We can't rely on the ordering of units in a std::set<CUnit*>,
				// because they're sorted on memory address. Hence we must first
				// build a set of IDs and then pick an unit from that.
				// This guarantees the script doesn't desync in multiplayer games.
				int num = gs->randInt() % gs->Team(1 - curUnit->team)->units.size();
				std::set<int> unitids;
				CUnitSet* tu = &gs->Team(1 - curUnit->team)->units;
				for (CUnitSet::iterator u = tu->begin(); u != tu->end(); ++u)
					unitids.insert((*u)->id);
				std::set<int>::iterator ui = unitids.begin();
				for(int a=0;a<num;++a)
					++ui;
				curUnit->target=(*ui);
				curUnit->lastTargetPos.x=-500;
			}
			float3 pos=uh->units[curUnit->target]->pos;
			if(pos.distance2D(curUnit->lastTargetPos)>100){
				curUnit->lastTargetPos=pos;
				Command c;
				c.id=CMD_PATROL;
				c.options=0;
				c.params.push_back(pos.x);
				c.params.push_back(pos.y);
				c.params.push_back(pos.z);
				uh->units[curUnit->id]->commandAI->GiveCommand(c);
			}
			curUnit++;
		} else {
			curUnit=myUnits.erase(curUnit);
		}
		if(curUnit==myUnits.end())
			curUnit=myUnits.begin();
	}
}
Beispiel #13
0
bool CProgAndPlay::allUnitsDead() {
	CUnitSet *tmp = &(teamHandler->Team(gu->myTeam)->units);
	return tmp->size() == 0;
}