void CFactoryCAI::CancelRestrictedUnit(const Command& c, BuildOption& buildOption) { if(!repeatOrders || c.options & DONT_REPEAT) { buildOption.numQued--; if (owner->team == gu->myTeam) { if(lastRestrictedWarning+100<gs->frameNum) { logOutput.Print("%s: Build failed, unit type limit reached",owner->unitDef->humanName.c_str()); logOutput.SetLastMsgPos(owner->pos); lastRestrictedWarning = gs->frameNum; } } } UpdateIconName(c.id, buildOption); FinishCommand(); }
void CFactoryCAI::InsertBuildCommand(CCommandQueue::iterator& it, const Command& newCmd) { map<int, BuildOption>::iterator boi = buildOptions.find(newCmd.id); if (boi != buildOptions.end()) { boi->second.numQued++; UpdateIconName(newCmd.id, boi->second); } if (!commandQue.empty() && (it == commandQue.begin())) { // ExecuteStop(), without the pop_front() CFactory* fac = (CFactory*)owner; building = false; fac->StopBuild(); } commandQue.insert(it, newCmd); }
void CFactoryCAI::RemoveBuildCommand(CCommandQueue::iterator& it) { Command& cmd = *it; map<int, BuildOption>::iterator boi = buildOptions.find(cmd.id); if (boi != buildOptions.end()) { boi->second.numQued--; UpdateIconName(cmd.id, boi->second); } if (!commandQue.empty() && (it == commandQue.begin())) { ExecuteStop(cmd); return; } if (cmd.id < 0) { cmd.id = CMD_STOP; cmd.tag = 0; } }
void CFactoryCAI::SlowUpdate() { if(commandQue.empty() || owner->beingBuilt) return; CFactory* fac=(CFactory*)owner; unsigned int oldSize; do{ Command& c=commandQue.front(); oldSize=commandQue.size(); map<int,BuildOption>::iterator boi; if((boi=buildOptions.find(c.id))!=buildOptions.end()){ if(building){ if(!fac->curBuild && !fac->quedBuild){ building=false; if(owner->group) owner->group->CommandFinished(owner->id,commandQue.front().id); if(!repeatOrders) boi->second.numQued--; UpdateIconName(c.id,boi->second); FinishCommand(); } } else { if(uh->maxUnits>gs->Team(owner->team)->units.size()){ fac->StartBuild(boi->second.fullName); building=true; } } } else { switch(c.id){ case CMD_STOP: building=false; fac->StopBuild(); commandQue.pop_front(); break; default: CCommandAI::SlowUpdate(); return; } } }while(oldSize!=commandQue.size() && !commandQue.empty()); return; }
bool CFactoryCAI::RemoveBuildCommand(CCommandQueue::iterator& it) { Command& cmd = *it; map<int, BuildOption>::iterator boi = buildOptions.find(cmd.GetID()); if (boi != buildOptions.end()) { boi->second.numQued--; UpdateIconName(cmd.GetID(), boi->second); } if (!commandQue.empty() && (it == commandQue.begin())) { ExecuteStop(cmd); return true; } if (cmd.GetID() < 0) { // build command, convert into a stop command cmd = Command(CMD_STOP); } return false; }
void CFactoryCAI::SlowUpdate() { if (commandQue.empty() || owner->beingBuilt) { return; } CFactory* fac=(CFactory*)owner; unsigned int oldSize; do { Command& c=commandQue.front(); oldSize=commandQue.size(); map<int,BuildOption>::iterator boi; if((boi=buildOptions.find(c.id))!=buildOptions.end()){ const UnitDef *def = unitDefHandler->GetUnitByName(boi->second.name); if(building){ if(!fac->curBuild && !fac->quedBuild){ building=false; if(owner->group) owner->group->CommandFinished(owner->id,commandQue.front().id); if(!repeatOrders || c.options & DONT_REPEAT) boi->second.numQued--; UpdateIconName(c.id,boi->second); FinishCommand(); } // This can only be true if two factories started building // the restricted unit in the same simulation frame else if(uh->unitsByDefs[owner->team][def->id].size() > def->maxThisUnit){ //unit restricted? CFactory* fac=(CFactory*)owner; building = false; fac->StopBuild(); CancelRestrictedUnit(c, boi->second); } } else { const UnitDef *def = unitDefHandler->GetUnitByName(boi->second.name); if(luaRules && !luaRules->AllowUnitCreation(def, owner, NULL)) { if(!repeatOrders || c.options & DONT_REPEAT){ boi->second.numQued--; } UpdateIconName(c.id,boi->second); FinishCommand(); } else if(uh->unitsByDefs[owner->team][def->id].size() >= def->maxThisUnit){ //unit restricted? CancelRestrictedUnit(c, boi->second); } else if(uh->maxUnits>gs->Team(owner->team)->units.size()){ //max unitlimit reached? fac->StartBuild(boi->second.fullName); building=true; } } } else { switch(c.id){ case CMD_STOP: { ExecuteStop(c); break; } default: { CCommandAI::SlowUpdate(); return; } } } } while ((oldSize != commandQue.size()) && !commandQue.empty()); return; }
void CFactoryCAI::GiveCommandReal(const Command& c, bool fromSynced) { // move is always allowed for factories (passed to units it produces) if ((c.id == CMD_SET_WANTED_MAX_SPEED) || ((c.id != CMD_MOVE) && !AllowedCommand(c))) { return; } map<int, BuildOption>::iterator boi = buildOptions.find(c.id); // not a build order so queue it to built units if (boi == buildOptions.end()) { if ((nonQueingCommands.find(c.id) != nonQueingCommands.end()) || (c.id == CMD_INSERT) || (c.id == CMD_REMOVE) || (!(c.options & SHIFT_KEY) && ((c.id == CMD_WAIT) || (c.id == CMD_SELFD)))) { CCommandAI::GiveAllowedCommand(c); return; } if (!(c.options & SHIFT_KEY)) { waitCommandsAI.ClearUnitQueue(owner, newUnitCommands); newUnitCommands.clear(); } if (c.id != CMD_STOP) { if ((c.id == CMD_WAIT) || (c.id == CMD_SELFD)) { if (!newUnitCommands.empty() && (newUnitCommands.back().id == c.id)) { if (c.id == CMD_WAIT) { waitCommandsAI.RemoveWaitCommand(owner, c); } newUnitCommands.pop_back(); } else { newUnitCommands.push_back(c); } } else { bool dummy; if (CancelCommands(c, newUnitCommands, dummy) > 0) { return; } else { if (GetOverlapQueued(c, newUnitCommands).empty()) { newUnitCommands.push_back(c); } else { return; } } } } // the first new-unit build order can not be WAIT or SELFD while (!newUnitCommands.empty()) { const int id = newUnitCommands.front().id; if ((id == CMD_WAIT) || (id == CMD_SELFD)) { if (c.id == CMD_WAIT) { waitCommandsAI.RemoveWaitCommand(owner, c); } newUnitCommands.pop_front(); } else { break; } } return; } BuildOption &bo = boi->second; int numItems = 1; if (c.options & SHIFT_KEY) { numItems *= 5; } if (c.options & CONTROL_KEY) { numItems *= 20; } if (c.options & RIGHT_MOUSE_KEY) { bo.numQued -= numItems; if (bo.numQued < 0) { bo.numQued = 0; } int numToErase = numItems; if (c.options & ALT_KEY) { for (unsigned int cmdNum = 0; cmdNum < commandQue.size() && numToErase; ++cmdNum) { if (commandQue[cmdNum].id == c.id) { commandQue[cmdNum].id = CMD_STOP; numToErase--; } } } else { for (int cmdNum = commandQue.size() - 1; cmdNum != -1 && numToErase; --cmdNum) { if (commandQue[cmdNum].id == c.id) { commandQue[cmdNum].id = CMD_STOP; numToErase--; } } } UpdateIconName(c.id,bo); SlowUpdate(); } else { if (c.options & ALT_KEY) { for (int a = 0; a < numItems; ++a) { if (repeatOrders) { Command nc(c); nc.options |= DONT_REPEAT; if (commandQue.empty()) { commandQue.push_front(nc); } else { commandQue.insert(commandQue.begin()+1, nc); } } else { commandQue.push_front(c); } } if (!repeatOrders) { building=false; CFactory* fac = (CFactory*)owner; fac->StopBuild(); } } else { for (int a = 0; a < numItems; ++a) { commandQue.push_back(c); } } bo.numQued += numItems; UpdateIconName(c.id, bo); SlowUpdate(); } }
void CFactoryCAI::GiveCommandReal(const Command& c, bool fromSynced) { const int cmdID = c.GetID(); // move is always allowed for factories (passed to units it produces) if ((cmdID == CMD_SET_WANTED_MAX_SPEED) || ((cmdID != CMD_MOVE) && !AllowedCommand(c, fromSynced))) { return; } map<int, BuildOption>::iterator boi = buildOptions.find(cmdID); // not a build order (or a build order we do not support, eg. if multiple // factories of different types were selected) so queue it to built units if (boi == buildOptions.end()) { if (cmdID < 0) return; if ((nonQueingCommands.find(cmdID) != nonQueingCommands.end()) || (cmdID == CMD_INSERT) || (cmdID == CMD_REMOVE) || (!(c.options & SHIFT_KEY) && ((cmdID == CMD_WAIT) || (cmdID == CMD_SELFD)))) { CCommandAI::GiveAllowedCommand(c); return; } if (!(c.options & SHIFT_KEY)) { waitCommandsAI.ClearUnitQueue(owner, newUnitCommands); CCommandAI::ClearCommandDependencies(); newUnitCommands.clear(); } CCommandAI::AddCommandDependency(c); if (cmdID != CMD_STOP) { if ((cmdID == CMD_WAIT) || (cmdID == CMD_SELFD)) { if (!newUnitCommands.empty() && (newUnitCommands.back().GetID() == cmdID)) { if (cmdID == CMD_WAIT) { waitCommandsAI.RemoveWaitCommand(owner, c); } newUnitCommands.pop_back(); } else { newUnitCommands.push_back(c); } } else { bool dummy; if (CancelCommands(c, newUnitCommands, dummy) > 0) { return; } else { if (GetOverlapQueued(c, newUnitCommands).empty()) { newUnitCommands.push_back(c); } else { return; } } } } // the first new-unit build order can not be WAIT or SELFD while (!newUnitCommands.empty()) { const Command& newUnitCommand = newUnitCommands.front(); const int id = newUnitCommand.GetID(); if ((id == CMD_WAIT) || (id == CMD_SELFD)) { if (cmdID == CMD_WAIT) { waitCommandsAI.RemoveWaitCommand(owner, c); } newUnitCommands.pop_front(); } else { break; } } return; } BuildOption& bo = boi->second; int numItems = 1; if (c.options & SHIFT_KEY) { numItems *= 5; } if (c.options & CONTROL_KEY) { numItems *= 20; } if (c.options & RIGHT_MOUSE_KEY) { bo.numQued -= numItems; bo.numQued = std::max(bo.numQued, 0); int numToErase = numItems; if (c.options & ALT_KEY) { for (unsigned int cmdNum = 0; cmdNum < commandQue.size() && numToErase; ++cmdNum) { if (commandQue[cmdNum].GetID() == cmdID) { commandQue[cmdNum] = Command(CMD_STOP); numToErase--; } } } else { for (int cmdNum = commandQue.size() - 1; cmdNum != -1 && numToErase; --cmdNum) { if (commandQue[cmdNum].GetID() == cmdID) { commandQue[cmdNum] = Command(CMD_STOP); numToErase--; } } } UpdateIconName(cmdID, bo); SlowUpdate(); } else { if (c.options & ALT_KEY) { for (int a = 0; a < numItems; ++a) { if (repeatOrders) { Command nc(c); nc.options |= INTERNAL_ORDER; if (commandQue.empty()) { commandQue.push_front(nc); } else { commandQue.insert(commandQue.begin()+1, nc); } } else { commandQue.push_front(c); } } if (!repeatOrders) { CFactory* fac = static_cast<CFactory*>(owner); fac->StopBuild(); } } else { for (int a = 0; a < numItems; ++a) { commandQue.push_back(c); } } bo.numQued += numItems; UpdateIconName(cmdID, bo); SlowUpdate(); } }
void CFactoryCAI::GiveCommand(Command& c) { map<int,BuildOption>::iterator boi; if((boi=buildOptions.find(c.id))==buildOptions.end()){ //not a build order so que it to built units if(nonQueingCommands.find(c.id)!=nonQueingCommands.end()){ CCommandAI::GiveCommand(c); return; } if(!(c.options & SHIFT_KEY)){ newUnitCommands.clear(); } if(c.id!=CMD_STOP){ std::deque<Command>::iterator ci = GetCancelQueued(c); if(ci == this->newUnitCommands.end()){ newUnitCommands.push_back(c); } else { this->newUnitCommands.erase(ci); } } return; } BuildOption &bo=boi->second; int numItems=1; if(c.options& SHIFT_KEY) numItems*=5; if(c.options & CONTROL_KEY) numItems*=20; if(c.options & RIGHT_MOUSE_KEY){ bo.numQued-=numItems; if(bo.numQued<0) bo.numQued=0; int numToErase=numItems; if(c.options & ALT_KEY){ for(unsigned int cmdNum=0;cmdNum<commandQue.size() && numToErase;++cmdNum){ if(commandQue[cmdNum].id==c.id){ commandQue[cmdNum].id=CMD_STOP; numToErase--; } } } else { for(int cmdNum=commandQue.size()-1;cmdNum!=-1 && numToErase;--cmdNum){ if(commandQue[cmdNum].id==c.id){ commandQue[cmdNum].id=CMD_STOP; numToErase--; } } } UpdateIconName(c.id,bo); SlowUpdate(); } else { if(c.options & ALT_KEY){ for(int a=0;a<numItems;++a){ commandQue.push_front(c); } building=false; CFactory* fac=(CFactory*)owner; fac->StopBuild(); } else { for(int a=0;a<numItems;++a){ commandQue.push_back(c); } } bo.numQued+=numItems; UpdateIconName(c.id,bo); SlowUpdate(); } }