void CCommandAI::ExecuteRemove(const Command& c) { // disable repeating during the removals const bool prevRepeat = repeatOrders; repeatOrders = false; CCommandQueue* queue = &commandQue; bool facBuildQueue = false; CFactoryCAI* facCAI = dynamic_cast<CFactoryCAI*>(this); if (facCAI) { if (c.options & CONTROL_KEY) { // check the build order facBuildQueue = true; } else { // use the new commands queue = &facCAI->newUnitCommands; } } if ((c.params.size() <= 0) || (queue->size() <= 0)) { return; } // erase commands by a list of command types bool active = false; for (unsigned int p = 0; p < c.params.size(); p++) { const int removeValue = (int)c.params[p]; // tag or id if (facBuildQueue && (removeValue == 0) && !(c.options & ALT_KEY)) { continue; // don't remove tag=0 commands from build queues, they // are used the same way that CMD_STOP is, to void orders } CCommandQueue::iterator ci; do { for (ci = queue->begin(); ci != queue->end(); ++ci) { const Command& qc = *ci; if (c.options & ALT_KEY) { if (qc.id != removeValue) { continue; } } else { if (qc.tag != removeValue) { continue; } } if (qc.id == CMD_WAIT) { waitCommandsAI.RemoveWaitCommand(owner, qc); } if (facBuildQueue) { facCAI->RemoveBuildCommand(ci); ci = queue->begin(); break; // the removal may have corrupted the iterator } if (!facCAI && (ci == queue->begin())) { if (!active) { active = true; FinishCommand(); ci = queue->begin(); break; } active = true; } queue->erase(ci); ci = queue->begin(); break; // the removal may have corrupted the iterator } } while (ci != queue->end()); } repeatOrders = prevRepeat; return; }
void CCommandAI::ExecuteInsert(const Command& c, bool fromSynced) { if (c.params.size() < 3) { return; } // make the command Command newCmd; newCmd.id = (int)c.params[1]; newCmd.options = (unsigned char)c.params[2]; for (int p = 3; p < (int)c.params.size(); p++) { newCmd.params.push_back(c.params[p]); } // validate the command if (!AllowedCommand(newCmd, fromSynced)) { return; } CCommandQueue* queue = &commandQue; bool facBuildQueue = false; CFactoryCAI* facCAI = dynamic_cast<CFactoryCAI*>(this); if (facCAI) { if (c.options & CONTROL_KEY) { // check the build order const map<int, CFactoryCAI::BuildOption>& bOpts = facCAI->buildOptions; if ((newCmd.id != CMD_STOP) && (newCmd.id != CMD_WAIT) && ((newCmd.id >= 0) || (bOpts.find(newCmd.id) == bOpts.end()))) { return; } facBuildQueue = true; } else { // use the new commands queue = &facCAI->newUnitCommands; } } // FIXME: handle CMD_LOOPBACKATTACK, etc... CCommandQueue::iterator insertIt = queue->begin(); if (c.options & ALT_KEY) { // treat param0 as a position int pos = (int)c.params[0]; const unsigned int qsize = queue->size(); if (pos < 0) { pos = qsize + pos + 1; // convert the negative index if (pos < 0) { pos = 0; } } if (pos > qsize) { pos = qsize; } std::advance(insertIt, pos); } else { // treat param0 as a command tag const unsigned int tag = (unsigned int)c.params[0]; CCommandQueue::iterator ci; bool found = false; for (ci = queue->begin(); ci != queue->end(); ++ci) { const Command& qc = *ci; if (qc.tag == tag) { insertIt = ci; found = true; break; } } if (!found) { return; } if ((c.options & RIGHT_MOUSE_KEY) && (insertIt != queue->end())) { insertIt++; // insert after the tagged command } } if (facBuildQueue) { facCAI->InsertBuildCommand(insertIt, newCmd); if (!owner->stunned) { SlowUpdate(); } return; } // shutdown the current order if the insertion is at the beginning if (!queue->empty() && (insertIt == queue->begin())) { inCommand = false; targetDied = false; unimportantMove = false; orderTarget = NULL; const Command& cmd = commandQue.front(); eoh->CommandFinished(*owner, cmd); eventHandler.UnitCmdDone(owner, cmd.id, cmd.tag); } queue->insert(insertIt, newCmd); if (!owner->stunned) { SlowUpdate(); } return; }
void CCommandAI::ExecuteRemove(const Command& c) { CCommandQueue* queue = &commandQue; CFactoryCAI* facCAI = dynamic_cast<CFactoryCAI*>(this); // if false, remove commands by tag const bool removeByID = (c.options & ALT_KEY); // disable repeating during the removals const bool prevRepeat = repeatOrders; // erase commands by a list of command types bool active = false; bool facBuildQueue = false; if (facCAI) { if (c.options & CONTROL_KEY) { // keep using the build-order queue facBuildQueue = true; } else { // use the command-queue for new units queue = &facCAI->newUnitCommands; } } if ((c.params.size() <= 0) || (queue->size() <= 0)) { return; } repeatOrders = false; for (unsigned int p = 0; p < c.params.size(); p++) { const int removeValue = c.params[p]; // tag or id if (facBuildQueue && !removeByID && (removeValue == 0)) { // don't remove commands with tag 0 from build queues, they // are used the same way that CMD_STOP is (to void orders) continue; } CCommandQueue::iterator ci; do { for (ci = queue->begin(); ci != queue->end(); ++ci) { const Command& qc = *ci; if (removeByID) { if (qc.GetID() != removeValue) { continue; } } else { if (qc.tag != removeValue) { continue; } } if (qc.GetID() == CMD_WAIT) { waitCommandsAI.RemoveWaitCommand(owner, qc); } if (facBuildQueue) { // if ci == queue->begin() and !queue->empty(), this pop_front()'s // via CFAI::ExecuteStop; otherwise only modifies *ci (not <queue>) if (facCAI->RemoveBuildCommand(ci)) { ci = queue->begin(); break; } } if (!facCAI && (ci == queue->begin())) { if (!active) { active = true; FinishCommand(); ci = queue->begin(); break; } active = true; } queue->erase(ci); ci = queue->begin(); // the removal may have corrupted the iterator break; } } while (ci != queue->end()); } repeatOrders = prevRepeat; }
int CProgAndPlay::execPendingCommands(){ //log("ProgAndPLay::execPendingCommands begin"); int nbCmd = 0; PP_PendingCmds* pendingCommands = PP_GetPendingCommands(); if (pendingCommands == NULL) return -1; else{ nbCmd = pendingCommands->size; for (int i = 0 ; i < pendingCommands->size ; i++){ PP_PendingCmd pc = pendingCommands->pendingCommand[i]; // Check for affecting group if (pc.group != -2){ // Check if unit exists CUnit* tmp = uh->GetUnit(pc.unitId); if (tmp != NULL){ if (tmp->team == gu->myTeam){ // Check the grouphandlers for my team if (grouphandlers[gu->myTeam]){ // Check if it's a command to withdraw unit from its current group if (pc.group == -1){ // suppression de l'unité de sons groupe tmp->SetGroup(NULL); } else{ // Check if the number of groups is being enough while (pc.group >= grouphandlers[gu->myTeam]->groups.size()){ // add a new group grouphandlers[gu->myTeam]->CreateNewGroup(); } // Check if the group exists if (!grouphandlers[gu->myTeam]->groups[pc.group]){ // recreate all groups until recreate this group CGroup * gTmp; do { // création d'un groupe intermédiaire manquant gTmp = grouphandlers[gu->myTeam]->CreateNewGroup(); } while (gTmp->id != pc.group); } if (pc.group >= 0){ // devote the unit to this group tmp->SetGroup(grouphandlers[gu->myTeam]->groups[pc.group]); } } } } } } // Check if a command must be executed bool ok = true, found = false; switch (pc.commandType){ case -1 : // the command is invalid => do not execute this command ok = false; break; case 0 : // the command target a position // indicates the y value pc.command.param[1] = ground->GetHeight(pc.command.param[0], pc.command.param[2]); break; case 1 : // the command targets a unit // Find targeted unit for (int t = 0 ; t < teamHandler->ActiveTeams() && !found ; t++){ CUnit* tmp = uh->GetUnit((int)pc.command.param[0]); if (tmp != NULL){ if (tmp->team == t){ // check if this unit is visible by the player if (!loshandler->InLos(tmp, gu->myAllyTeam)) ok = false; found = true; } } } break; case 2 : // the command is untargeted // nothing to do break; default : PP_SetError("Spring : commandType unknown"); PP_FreePendingCommands(pendingCommands); return -1; } // send command if (ok){ if (pc.command.code == -7658){ // This code is a Prog&Play reserved code defined in constantList files // Clear CommandQueue of factory CUnit* fact = uh->GetUnit(pc.unitId); if (fact){ CFactoryCAI* facAI = dynamic_cast<CFactoryCAI*>(fact->commandAI); if (facAI) { Command c; c.options = RIGHT_MOUSE_KEY; // Set RIGHT_MOUSE_KEY option in order to decrement building order CCommandQueue& buildCommands = facAI->commandQue; CCommandQueue::iterator it; std::vector<Command> clearCommands; clearCommands.reserve(buildCommands.size()); for (it = buildCommands.begin(); it != buildCommands.end(); ++it) { c.id = it->id; clearCommands.push_back(c); } for (int i = 0; i < (int)clearCommands.size(); i++) { facAI->GiveCommand(clearCommands[i]); } } } } else{ // Copy pc.command.param in a vector to pass it at SendAICommand std::vector<float> stdParam; for (int j = 0 ; j < pc.command.nbParam ; j++) stdParam.push_back(pc.command.param[j]); net->Send(CBaseNetProtocol::Get().SendAICommand(gu->myPlayerNum, pc.unitId, pc.command.code, 0, stdParam)); /* // Permet de gérer les commandes plus correctement mais produit des // erreurs de synchronisation (à utiliser en SYNCED_MODE) CUnitSet *tmp = &(gs->Team(gu->myTeam)->units); CUnitSetConstIterator it = tmp->find(pc.unitId); if (it != tmp->end() && (*it)->commandAI){ Command cTmp; cTmp.id = pc.command.code; cTmp.params = stdParam; (*it)->commandAI->GiveCommand(cTmp); }*/ } } } } PP_FreePendingCommands(pendingCommands); //log("ProgAndPLay::execPendingCommands end"); return nbCmd; }
// owner->curBuild can remain NULL for several frames after calling // QueueBuild(); hence we need a callback or listen for an event to // detect when the build-process actually finished // // NOTE: // only called if Factory::QueueBuild returned FACTORY_NEXT_BUILD_ORDER // (meaning the order was not rejected and the callback was installed) void FactoryFinishBuildCallBack(CFactory* factory, const Command& command) { CFactoryCAI* cai = dynamic_cast<CFactoryCAI*>(factory->commandAI); CFactoryCAI::BuildOption& bo = cai->buildOptions[command.GetID()]; cai->DecreaseQueueCount(command, bo, true); }
void CUnit::ChangeTeamReset() { Command c; // clear the commands (newUnitCommands for factories) c.id = CMD_STOP; commandAI->GiveCommand(c); // clear the build commands for factories CFactoryCAI* facAI = dynamic_cast<CFactoryCAI*>(commandAI); if (facAI) { c.options = RIGHT_MOUSE_KEY; // clear option CCommandQueue& buildCommands = facAI->commandQue; CCommandQueue::iterator it; std::vector<Command> clearCommands; for (it = buildCommands.begin(); it != buildCommands.end(); ++it) { c.id = it->id; clearCommands.push_back(c); } for (int i = 0; i < (int)clearCommands.size(); i++) { facAI->GiveCommand(clearCommands[i]); } } // deactivate to prevent the old give metal maker trick c.id = CMD_ONOFF; c.params.push_back(0); // always off commandAI->GiveCommand(c); c.params.clear(); // reset repeat state c.id = CMD_REPEAT; c.params.push_back(0); commandAI->GiveCommand(c); c.params.clear(); // reset cloak state if (unitDef->canCloak) { c.id = CMD_CLOAK; c.params.push_back(0); // always off commandAI->GiveCommand(c); c.params.clear(); } // reset move state if (unitDef->canmove || unitDef->builder) { c.id = CMD_MOVE_STATE; c.params.push_back(1); commandAI->GiveCommand(c); c.params.clear(); } // reset fire state if (!unitDef->noAutoFire && (!unitDef->weapons.empty() || (unitDef->type == "Factory"))) { c.id = CMD_FIRE_STATE; c.params.push_back(2); commandAI->GiveCommand(c); c.params.clear(); } // reset trajectory state if (unitDef->highTrajectoryType > 1) { c.id = CMD_TRAJECTORY; c.params.push_back(0); commandAI->GiveCommand(c); c.params.clear(); } }