void CBuilderCAI::SlowUpdate() { if(gs->paused) // Commands issued may invoke SlowUpdate when paused return; if (commandQue.empty()) { CMobileCAI::SlowUpdate(); return; } if (owner->beingBuilt || owner->stunned) { return; } Command& c = commandQue.front(); if (OutOfImmobileRange(c)) { FinishCommand(); return; } switch (c.GetID()) { case CMD_STOP: { ExecuteStop(c); return; } case CMD_REPAIR: { ExecuteRepair(c); return; } case CMD_CAPTURE: { ExecuteCapture(c); return; } case CMD_GUARD: { ExecuteGuard(c); return; } case CMD_RECLAIM: { ExecuteReclaim(c); return; } case CMD_RESURRECT: { ExecuteResurrect(c); return; } case CMD_PATROL: { ExecutePatrol(c); return; } case CMD_FIGHT: { ExecuteFight(c); return; } case CMD_RESTORE: { ExecuteRestore(c); return; } default: { if (c.GetID() < 0) { ExecuteBuildCmd(c); } else { CMobileCAI::SlowUpdate(); } return; } } }
void CBuilderCAI::SlowUpdate() { if(commandQue.empty()){ CMobileCAI::SlowUpdate(); return; } Command& c=commandQue.front(); CBuilder* fac=(CBuilder*)owner; float3 curPos=owner->pos; map<int,string>::iterator boi; if((boi=buildOptions.find(c.id))!=buildOptions.end()){ const UnitDef* ud = unitDefHandler->GetUnitByName(boi->second); const float radius = GetUnitRadius(ud, c.id); if (inCommand) { if (building) { if (build.pos.distance2D(fac->pos) > fac->buildDistance+radius-8.0f) { owner->moveType->StartMoving(build.pos, fac->buildDistance*0.5f+radius); } else { StopMove(); owner->moveType->KeepPointingTo(build.pos, (fac->buildDistance+radius)*0.6f, false); //needed since above startmoving cancels this } if(!fac->curBuild && !fac->terraforming){ building=false; StopMove(); //cancel the effect of KeepPointingTo FinishCommand(); } } else { build.Parse(c); const float dist = build.pos.distance2D(fac->pos); if ((dist < (fac->buildDistance * 0.6f + radius)) || (!owner->unitDef->canmove && (dist <= (fac->buildDistance+radius-8.0f)))) { StopMove(); if(uh->unitsType[owner->team][build.def->id]>=build.def->maxThisUnit){ //unit restricted ENTER_MIXED; if(owner->team == gu->myTeam){ logOutput.Print("%s: Build failed, unit type limit reached",owner->unitDef->humanName.c_str()); logOutput.SetLastMsgPos(owner->pos); } ENTER_SYNCED; FinishCommand(); } else if(uh->maxUnits>(int)gs->Team(owner->team)->units.size()){ //max unitlimit reached buildRetries++; owner->moveType->KeepPointingTo(build.pos, fac->buildDistance*0.7f+radius, false); if(fac->StartBuild(build) || buildRetries>20){ building=true; } else { ENTER_MIXED; if(owner->team==gu->myTeam && !(buildRetries&7)){ logOutput.Print("%s: Build pos blocked",owner->unitDef->humanName.c_str()); logOutput.SetLastMsgPos(owner->pos); } ENTER_SYNCED; helper->BuggerOff(build.pos,radius); NonMoving(); } } } else { if(owner->moveType->progressState==CMoveType::Failed){ if(++buildRetries>5){ StopMove(); FinishCommand(); } } SetGoal(build.pos,owner->pos, fac->buildDistance*0.4f+radius); } } } else { //!inCommand BuildInfo bi; bi.pos.x=floor(c.params[0]/SQUARE_SIZE+0.5f)*SQUARE_SIZE; bi.pos.z=floor(c.params[2]/SQUARE_SIZE+0.5f)*SQUARE_SIZE; bi.pos.y=c.params[1]; CFeature* f=0; if (c.params.size()==4) bi.buildFacing = int(c.params[3]); bi.def = unitDefHandler->GetUnitByName(boi->second); uh->TestUnitBuildSquare(bi,f,owner->allyteam); if(f){ if (!owner->unitDef->canReclaim || !f->def->destructable) { // FIXME user shouldn't be able to queue buildings on top of features // in the first place (in this case). StopMove(); FinishCommand(); } else { Command c2; c2.id=CMD_RECLAIM; c2.options=0; c2.params.push_back(f->id+MAX_UNITS); commandQue.push_front(c2); SlowUpdate(); //this assumes that the reclaim command can never return directly without having reclaimed the target } } else { inCommand=true; SlowUpdate(); } } return; } switch (c.id) { case CMD_STOP: { ExecuteStop(c); return; } case CMD_REPAIR: { ExecuteRepair(c); return; } case CMD_CAPTURE: { ExecuteCapture(c); return; } case CMD_GUARD: { ExecuteGuard(c); return; } case CMD_RECLAIM: { ExecuteReclaim(c); return; } case CMD_RESURRECT: { ExecuteResurrect(c); return; } case CMD_PATROL: { ExecutePatrol(c); return; } case CMD_FIGHT: { ExecuteFight(c); return; } case CMD_RESTORE: { ExecuteRestore(c); return; } default: { CMobileCAI::SlowUpdate(); return; } } }
void CBuilderCAI::SlowUpdate() { if (commandQue.empty()) { CMobileCAI::SlowUpdate(); return; } if (owner->stunned) { return; } CBuilder* fac = (CBuilder*)owner; Command& c = commandQue.front(); if (OutOfImmobileRange(c)) { FinishCommand(); return; } map<int, string>::iterator boi = buildOptions.find(c.id); if (!owner->beingBuilt && boi != buildOptions.end()) { const UnitDef* ud = unitDefHandler->GetUnitByName(boi->second); const float radius = GetUnitDefRadius(ud, c.id); if (inCommand) { if (building) { if (f3SqDist(build.pos, fac->pos) > Square(fac->buildDistance + radius - 8.0f)) { owner->moveType->StartMoving(build.pos, fac->buildDistance * 0.5f + radius); } else { StopMove(); // needed since above startmoving cancels this owner->moveType->KeepPointingTo(build.pos, (fac->buildDistance + radius) * 0.6f, false); } if (!fac->curBuild && !fac->terraforming) { building = false; StopMove(); //cancel the effect of KeepPointingTo FinishCommand(); } // This can only be true if two builders started building // the restricted unit in the same simulation frame else if (uh->unitsByDefs[owner->team][build.def->id].size() > build.def->maxThisUnit) { // unit restricted building = false; fac->StopBuild(); CancelRestrictedUnit(boi->second); } } else { build.Parse(c); if (uh->unitsByDefs[owner->team][build.def->id].size() >= build.def->maxThisUnit) { // unit restricted, don't bother moving all the way // to the construction site first before telling us // (since greyed-out icons can still be clicked etc, // would be better to prevent that but doesn't cover // case where limit reached while builder en-route) CancelRestrictedUnit(boi->second); StopMove(); } else { build.pos = helper->Pos2BuildPos(build); const float sqdist = f3SqDist(build.pos, fac->pos); if ((sqdist < Square(fac->buildDistance * 0.6f + radius)) || (!owner->unitDef->canmove && (sqdist <= Square(fac->buildDistance + radius - 8.0f)))) { StopMove(); if (luaRules && !luaRules->AllowUnitCreation(build.def, owner, &build.pos)) { FinishCommand(); } else if (uh->maxUnits > (int) teamHandler->Team(owner->team)->units.size()) { // max unitlimit reached buildRetries++; owner->moveType->KeepPointingTo(build.pos, fac->buildDistance * 0.7f + radius, false); if (fac->StartBuild(build) || (buildRetries > 20)) { building = true; } else { ENTER_MIXED; if ((owner->team == gu->myTeam) && !(buildRetries & 7)) { logOutput.Print("%s: Build pos blocked", owner->unitDef->humanName.c_str()); logOutput.SetLastMsgPos(owner->pos); } ENTER_SYNCED; helper->BuggerOff(build.pos, radius); NonMoving(); } } } else { if (owner->moveType->progressState == AMoveType::Failed) { if (++buildRetries > 5) { StopMove(); FinishCommand(); } } SetGoal(build.pos, owner->pos, fac->buildDistance * 0.4f + radius); } } } } else { //!inCommand BuildInfo bi; bi.pos.x=floor(c.params[0]/SQUARE_SIZE+0.5f)*SQUARE_SIZE; bi.pos.z=floor(c.params[2]/SQUARE_SIZE+0.5f)*SQUARE_SIZE; bi.pos.y=c.params[1]; CFeature* f=0; if (c.params.size()==4) bi.buildFacing = int(c.params[3]); bi.def = unitDefHandler->GetUnitByName(boi->second); uh->TestUnitBuildSquare(bi,f,owner->allyteam); if (f) { if (!owner->unitDef->canReclaim || !f->def->reclaimable) { // FIXME user shouldn't be able to queue buildings on top of features // in the first place (in this case). StopMove(); FinishCommand(); } else { Command c2; c2.id=CMD_RECLAIM; c2.options=0; c2.params.push_back(f->id+MAX_UNITS); commandQue.push_front(c2); SlowUpdate(); //this assumes that the reclaim command can never return directly without having reclaimed the target } } else { inCommand=true; SlowUpdate(); } } return; } switch (c.id) { case CMD_STOP: { ExecuteStop(c); return; } case CMD_REPAIR: { ExecuteRepair(c); return; } case CMD_CAPTURE: { ExecuteCapture(c); return; } case CMD_GUARD: { ExecuteGuard(c); return; } case CMD_RECLAIM: { ExecuteReclaim(c); return; } case CMD_RESURRECT: { ExecuteResurrect(c); return; } case CMD_PATROL: { ExecutePatrol(c); return; } case CMD_FIGHT: { ExecuteFight(c); return; } case CMD_RESTORE: { ExecuteRestore(c); return; } default: { CMobileCAI::SlowUpdate(); return; } } }