void CCommandAI::DependentDied(CObject* o) { if (o == orderTarget) { targetDied = true; orderTarget = NULL; } if (commandDeathDependences.erase(o) && o != owner) { CFactoryCAI* facCAI = dynamic_cast<CFactoryCAI*>(this); CCommandQueue& dq = facCAI ? facCAI->newUnitCommands : commandQue; int lastTag; int curTag = -1; do { lastTag = curTag; for (CCommandQueue::iterator qit = dq.begin(); qit != dq.end(); ++qit) { Command &c = *qit; int cpos; if (c.IsObjectCommand(cpos) && (c.params[cpos] == CSolidObject::GetDeletingRefID())) { Command removeCmd(CMD_REMOVE, 0); curTag = c.tag; removeCmd.params.push_back(curTag); ExecuteRemove(removeCmd); break; } } } while(curTag != lastTag); } }
void CCommandAI::GiveAllowedCommand(const Command& c, bool fromSynced) { if (ExecuteStateCommand(c)) { return; } switch (c.id) { case CMD_SELFD: { if (owner->unitDef->canSelfD) { if (!(c.options & SHIFT_KEY) || commandQue.empty()) { if (owner->selfDCountdown != 0) { owner->selfDCountdown = 0; } else { owner->selfDCountdown = owner->unitDef->selfDCountdown*2+1; } } else { if (commandQue.back().id == CMD_SELFD) { commandQue.pop_back(); } else { commandQue.push_back(c); } } } return; } case CMD_SET_WANTED_MAX_SPEED: { if (CanSetMaxSpeed() && (commandQue.empty() || (commandQue.back().id != CMD_SET_WANTED_MAX_SPEED))) { // bail early, do not check for overlaps or queue cancelling commandQue.push_back(c); if (commandQue.size()==1 && !owner->beingBuilt) { SlowUpdate(); } } return; } case CMD_WAIT: { GiveWaitCommand(c); return; } case CMD_INSERT: { ExecuteInsert(c, fromSynced); return; } case CMD_REMOVE: { ExecuteRemove(c); return; } } // flush the queue for immediate commands if (!(c.options & SHIFT_KEY)) { if (!commandQue.empty()) { if ((commandQue.front().id == CMD_DGUN) || (commandQue.front().id == CMD_ATTACK) || (commandQue.front().id == CMD_AREA_ATTACK)) { owner->AttackUnit(0,true); } waitCommandsAI.ClearUnitQueue(owner, commandQue); commandQue.clear(); } inCommand=false; if(orderTarget){ DeleteDeathDependence(orderTarget); orderTarget=0; } } if (c.id == CMD_PATROL) { CCommandQueue::iterator ci = commandQue.begin(); for (; ci != commandQue.end() && ci->id != CMD_PATROL; ci++) { // just increment } if (ci == commandQue.end()) { if (commandQue.empty()) { Command c2; c2.id = CMD_PATROL; c2.params.push_back(owner->pos.x); c2.params.push_back(owner->pos.y); c2.params.push_back(owner->pos.z); c2.options = c.options; commandQue.push_back(c2); } else { do { ci--; if (ci->params.size() >= 3) { Command c2; c2.id = CMD_PATROL; c2.params = ci->params; c2.options = c.options; commandQue.push_back(c2); break; } else if (ci == commandQue.begin()) { Command c2; c2.id = CMD_PATROL; c2.params.push_back(owner->pos.x); c2.params.push_back(owner->pos.y); c2.params.push_back(owner->pos.z); c2.options = c.options; commandQue.push_back(c2); break; } } while (ci != commandQue.begin()); } } } // cancel duplicated commands bool first; if (CancelCommands(c, commandQue, first) > 0) { if (first) { Command stopCommand; stopCommand.id = CMD_STOP; commandQue.push_front(stopCommand); SlowUpdate(); } return; } // do not allow overlapping commands if (!GetOverlapQueued(c).empty()) { return; } if (c.id == CMD_ATTACK) { // avoid weaponless units moving to 0 distance when given attack order if (owner->weapons.empty() && (owner->unitDef->canKamikaze == false)) { Command c2; c2.id = CMD_STOP; commandQue.push_back(c2); return; } } commandQue.push_back(c); if (commandQue.size() == 1 && !owner->beingBuilt && !owner->stunned) { SlowUpdate(); } }
void CCommandAI::GiveAllowedCommand(const Command& c, bool fromSynced) { if (ExecuteStateCommand(c)) { return; } switch (c.GetID()) { case CMD_SELFD: { if (owner->unitDef->canSelfD) { if (!(c.options & SHIFT_KEY) || commandQue.empty()) { if (owner->selfDCountdown != 0) { owner->selfDCountdown = 0; } else { owner->selfDCountdown = owner->unitDef->selfDCountdown*2+1; } } else if (commandQue.back().GetID() == CMD_SELFD) { commandQue.pop_back(); } else { commandQue.push_back(c); } } return; } case CMD_SET_WANTED_MAX_SPEED: { if (CanSetMaxSpeed() && (commandQue.empty() || (commandQue.back().GetID() != CMD_SET_WANTED_MAX_SPEED))) { // bail early, do not check for overlaps or queue cancelling commandQue.push_back(c); if (commandQue.size()==1 && !owner->beingBuilt) { SlowUpdate(); } } return; } case CMD_WAIT: { GiveWaitCommand(c); return; } case CMD_INSERT: { ExecuteInsert(c, fromSynced); return; } case CMD_REMOVE: { ExecuteRemove(c); return; } } // flush the queue for immediate commands // NOTE: CMD_STOP can be a queued order (!) if (!(c.options & SHIFT_KEY)) { waitCommandsAI.ClearUnitQueue(owner, commandQue); ClearTargetLock((commandQue.empty())? Command(CMD_STOP): commandQue.front()); ClearCommandDependencies(); SetOrderTarget(NULL); // if c is an attack command, the actual order-target // gets set via ExecuteAttack (called from SlowUpdate // at the end of this function) commandQue.clear(); assert(commandQue.empty()); inCommand = false; } AddCommandDependency(c); if (c.GetID() == CMD_PATROL) { CCommandQueue::iterator ci = commandQue.begin(); for (; ci != commandQue.end() && ci->GetID() != CMD_PATROL; ++ci) { // just increment } if (ci == commandQue.end()) { if (commandQue.empty()) { Command c2(CMD_PATROL, c.options, owner->pos); commandQue.push_back(c2); } else { do { --ci; if (ci->params.size() >= 3) { Command c2(CMD_PATROL, c.options); c2.params = ci->params; commandQue.push_back(c2); break; } else if (ci == commandQue.begin()) { Command c2(CMD_PATROL, c.options, owner->pos); commandQue.push_back(c2); break; } } while (ci != commandQue.begin()); } } } // cancel duplicated commands bool first; if (CancelCommands(c, commandQue, first) > 0) { if (first) { Command stopCommand(CMD_STOP); commandQue.push_front(stopCommand); SlowUpdate(); } return; } // do not allow overlapping commands if (!GetOverlapQueued(c).empty()) { return; } if (c.GetID() == CMD_ATTACK) { // avoid weaponless units moving to 0 distance when given attack order if (owner->weapons.empty() && (!owner->unitDef->canKamikaze)) { Command c2(CMD_STOP); commandQue.push_back(c2); return; } } commandQue.push_back(c); if (commandQue.size() == 1 && !owner->beingBuilt && !owner->IsStunned()) { SlowUpdate(); } }