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; }
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); } }
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(); } }
bool CProgAndPlay::allUnitsDead() { CUnitSet *tmp = &(teamHandler->Team(gu->myTeam)->units); return tmp->size() == 0; }