CCommandQueue::iterator CCommandAI::GetCancelQueued(const Command& c, CCommandQueue& q) { CCommandQueue::iterator ci = q.end(); while (ci != q.begin()) { --ci; //iterate from the end and dont check the current order const Command& c2 = *ci; const int cmdID = c.GetID(); const int cmd2ID = c2.GetID(); const bool attackAndFight = (cmdID == CMD_ATTACK && cmd2ID == CMD_FIGHT && c2.params.size() == 1); if (c2.params.size() != c.params.size()) continue; if ((cmdID == cmd2ID) || (cmdID < 0 && cmd2ID < 0) || attackAndFight) { if (c.params.size() == 1) { // assume the param is a unit-ID or feature-ID if ((c2.params[0] == c.params[0]) && (cmd2ID != CMD_SET_WANTED_MAX_SPEED)) { return ci; } } else if (c.params.size() >= 3) { if (cmdID < 0) { BuildInfo bc1(c); BuildInfo bc2(c2); if (bc1.def == NULL) continue; if (bc2.def == NULL) continue; if (math::fabs(bc1.pos.x - bc2.pos.x) * 2 <= std::max(bc1.GetXSize(), bc2.GetXSize()) * SQUARE_SIZE && math::fabs(bc1.pos.z - bc2.pos.z) * 2 <= std::max(bc1.GetZSize(), bc2.GetZSize()) * SQUARE_SIZE) { return ci; } } else { // assume c and c2 are positional commands const float3& c1p = c.GetPos(0); const float3& c2p = c2.GetPos(0); if ((c1p - c2p).SqLength2D() >= (COMMAND_CANCEL_DIST * COMMAND_CANCEL_DIST)) continue; if ((c.options & SHIFT_KEY) != 0 && (c.options & INTERNAL_ORDER) != 0) continue; return ci; } } } } return q.end(); }
/** * @brief Finds the queued command that would be canceled by the Command c * @return An iterator located at the command, or commandQue.end() if no such queued command exsists **/ CCommandQueue::iterator CCommandAI::GetCancelQueued(const Command &c, CCommandQueue& q) { CCommandQueue::iterator ci = q.end(); while (ci != q.begin()) { ci--; //iterate from the end and dont check the current order const Command& t = *ci; if (((c.id == t.id) || ((c.id < 0) && (t.id < 0)) || (t.id == CMD_FIGHT && c.id == CMD_ATTACK && t.params.size() == 1)) && (t.params.size() == c.params.size())) { if (c.params.size() == 1) { // assume the param is a unit of feature id if ((t.params[0] == c.params[0]) && (t.id != CMD_SET_WANTED_MAX_SPEED)) { return ci; } } else if (c.params.size() >= 3) { if (c.id < 0) { BuildInfo bc(c); BuildInfo bt(t); if (bc.def && bt.def && fabs(bc.pos.x - bt.pos.x) * 2 <= std::max(bc.GetXSize(), bt.GetXSize()) * SQUARE_SIZE && fabs(bc.pos.z - bt.pos.z) * 2 <= std::max(bc.GetZSize(), bt.GetZSize()) * SQUARE_SIZE) { return ci; } } else { // assume this means that the first 3 makes a position float3 cp(c.params[0], c.params[1], c.params[2]); float3 tp(t.params[0], t.params[1], t.params[2]); if ((cp - tp).SqLength2D() < (17.0f * 17.0f)) { return ci; } } } } } return q.end(); }
CCommandQueue::iterator CCommandAI::GetCancelQueued(const Command& c, CCommandQueue& q) { CCommandQueue::iterator ci = q.end(); while (ci != q.begin()) { --ci; //iterate from the end and dont check the current order const Command& c2 = *ci; const int& cmd_id = c.GetID(); const int& cmd2_id = c2.GetID(); if (((cmd_id == cmd2_id) || ((cmd_id < 0) && (cmd2_id < 0)) || (cmd2_id == CMD_FIGHT && cmd_id == CMD_ATTACK && c2.params.size() == 1)) && (c2.params.size() == c.params.size())) { if (c.params.size() == 1) { // assume the param is a unit-ID or feature-ID if ((c2.params[0] == c.params[0]) && (cmd2_id != CMD_SET_WANTED_MAX_SPEED)) { return ci; } } else if (c.params.size() >= 3) { if (cmd_id < 0) { BuildInfo bc(c); BuildInfo bc2(c2); if (bc.def && bc2.def && fabs(bc.pos.x - bc2.pos.x) * 2 <= std::max(bc.GetXSize(), bc2.GetXSize()) * SQUARE_SIZE && fabs(bc.pos.z - bc2.pos.z) * 2 <= std::max(bc.GetZSize(), bc2.GetZSize()) * SQUARE_SIZE) { return ci; } } else { // assume this means that the first 3 makes a position float3 cp(c.params[0], c.params[1], c.params[2]); float3 c2p(c2.params[0], c2.params[1], c2.params[2]); if ((cp - c2p).SqLength2D() < (17.0f * 17.0f)) { return ci; } } } } } return q.end(); }
std::vector<Command> CCommandAI::GetOverlapQueued(const Command& c, CCommandQueue& q) { CCommandQueue::iterator ci = q.end(); std::vector<Command> v; BuildInfo cbi(c); if (ci != q.begin()) { do { --ci; //iterate from the end and dont check the current order const Command& t = *ci; if (t.params.size() != c.params.size()) continue; if (t.GetID() == c.GetID() || (c.GetID() < 0 && t.GetID() < 0)) { if (c.params.size() == 1) { // assume the param is a unit or feature id if (t.params[0] == c.params[0]) { v.push_back(t); } } else if (c.params.size() >= 3) { // assume c and t are positional commands // NOTE: uses a BuildInfo structure, but <t> can be ANY command BuildInfo tbi; if (tbi.Parse(t)) { const float dist2X = 2.0f * math::fabs(cbi.pos.x - tbi.pos.x); const float dist2Z = 2.0f * math::fabs(cbi.pos.z - tbi.pos.z); const float addSizeX = SQUARE_SIZE * (cbi.GetXSize() + tbi.GetXSize()); const float addSizeZ = SQUARE_SIZE * (cbi.GetZSize() + tbi.GetZSize()); const float maxSizeX = SQUARE_SIZE * std::max(cbi.GetXSize(), tbi.GetXSize()); const float maxSizeZ = SQUARE_SIZE * std::max(cbi.GetZSize(), tbi.GetZSize()); if (cbi.def == NULL) continue; if (tbi.def == NULL) continue; if (((dist2X > maxSizeX) || (dist2Z > maxSizeZ)) && ((dist2X < addSizeX) && (dist2Z < addSizeZ))) { v.push_back(t); } } else { if ((cbi.pos - tbi.pos).SqLength2D() >= (COMMAND_CANCEL_DIST * COMMAND_CANCEL_DIST)) continue; if ((c.options & SHIFT_KEY) != 0 && (c.options & INTERNAL_ORDER) != 0) continue; v.push_back(t); } } } } while (ci != q.begin()); } return v; }
int CCommandAI::CancelCommands(const Command &c, CCommandQueue& q, bool& first) { first = false; int cancelCount = 0; while (true) { CCommandQueue::iterator ci = GetCancelQueued(c, q); if (ci == q.end()) { return cancelCount; } first = first || (ci == q.begin()); cancelCount++; CCommandQueue::iterator firstErase = ci; CCommandQueue::iterator lastErase = ci; ci++; if ((ci != q.end()) && (ci->id == CMD_SET_WANTED_MAX_SPEED)) { lastErase = ci; cancelCount++; ci++; } if ((ci != q.end()) && (ci->id == CMD_WAIT)) { waitCommandsAI.RemoveWaitCommand(owner, *ci); lastErase = ci; cancelCount++; ci++; } lastErase++; // STL: erase the range [first, last) q.erase(firstErase, lastErase); if (c.id >= 0) { return cancelCount; // only delete one non-build order } } return cancelCount; }
std::vector<Command> CCommandAI::GetOverlapQueued(const Command &c, CCommandQueue& q) { CCommandQueue::iterator ci = q.end(); std::vector<Command> v; BuildInfo cbi(c); if (ci != q.begin()){ do { ci--; //iterate from the end and dont check the current order const Command& t = *ci; if (((t.id == c.id) || ((c.id < 0) && (t.id < 0))) && (t.params.size() == c.params.size())){ if (c.params.size()==1) { // assume the param is a unit or feature id if (t.params[0] == c.params[0]) { v.push_back(t); } } else if (c.params.size() >= 3) { // assume this means that the first 3 makes a position BuildInfo tbi; if (tbi.Parse(t)) { const float dist2X = 2.0f * fabs(cbi.pos.x - tbi.pos.x); const float dist2Z = 2.0f * fabs(cbi.pos.z - tbi.pos.z); const float addSizeX = SQUARE_SIZE * (cbi.GetXSize() + tbi.GetXSize()); const float addSizeZ = SQUARE_SIZE * (cbi.GetZSize() + tbi.GetZSize()); const float maxSizeX = SQUARE_SIZE * std::max(cbi.GetXSize(), tbi.GetXSize()); const float maxSizeZ = SQUARE_SIZE * std::max(cbi.GetZSize(), tbi.GetZSize()); if (cbi.def && tbi.def && ((dist2X > maxSizeX) || (dist2Z > maxSizeZ)) && ((dist2X < addSizeX) && (dist2Z < addSizeZ))) { v.push_back(t); } } else { if ((cbi.pos - tbi.pos).SqLength2D() < (17.0f * 17.0f)) { v.push_back(t); } } } } } while (ci != q.begin()); } return v; }
void CWaitCommandsAI::ClearUnitQueue(CUnit* unit, const CCommandQueue& queue) { if ((unit->team != gu->myTeam) || waitMap.empty()) { return; } CCommandQueue::const_iterator qit; for (qit = queue.begin(); qit != queue.end(); ++qit) { const Command& cmd = *qit; if ((cmd.GetID() == CMD_WAIT) && (cmd.params.size() == 2)) { const KeyType key = Wait::GetKeyFromFloat(cmd.params[1]); WaitMap::iterator wit = waitMap.find(key); if (wit != waitMap.end()) { wit->second->RemoveUnit(unit); } } } }
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; }