void CTransportCAI::ExecuteLoadUnits(Command &c) { CTransportUnit* transport=(CTransportUnit*)owner; if(c.params.size()==1){ //load single unit if(transport->transportCapacityUsed >= owner->unitDef->transportCapacity){ FinishCommand(); return; } CUnit* unit=uh->units[(int)c.params[0]]; if(c.options & INTERNAL_ORDER) { if(unit->commandAI->commandQue.empty()){ if(!LoadStillValid(unit)){ FinishCommand(); return; } } else { Command & currentUnitCommand = unit->commandAI->commandQue[0]; if(currentUnitCommand.id == CMD_LOAD_ONTO && currentUnitCommand.params.size() == 1 && int(currentUnitCommand.params[0]) == owner->id){ if((unit->moveType->progressState == CMoveType::Failed) && (owner->moveType->progressState == CMoveType::Failed)){ unit->commandAI->FinishCommand(); FinishCommand(); return; } } else if(!LoadStillValid(unit)) { FinishCommand(); return; } } } if(inCommand){ if(!owner->cob->busy) FinishCommand(); return; } if(unit && CanTransport(unit) && UpdateTargetLostTimer(int(c.params[0]))){ toBeTransportedUnitId=unit->id; unit->toBeTransported=true; if(unit->mass+transport->transportMassUsed > owner->unitDef->transportMass){ FinishCommand(); return; } if(goalPos.distance2D(unit->pos)>10){ float3 fix = unit->pos; SetGoal(fix,owner->pos,64); } if(unit->pos.distance2D(owner->pos)<owner->unitDef->loadingRadius*0.9f){ if(CTAAirMoveType* am=dynamic_cast<CTAAirMoveType*>(owner->moveType)){ //handle air transports differently float3 wantedPos=unit->pos+UpVector*unit->model->height; SetGoal(wantedPos,owner->pos); am->dontCheckCol=true; am->ForceHeading(unit->heading); am->SetWantedAltitude(unit->model->height); am->maxDrift=1; //logOutput.Print("cai dist %f %f %f",owner->pos.distance(wantedPos),owner->pos.distance2D(wantedPos),owner->pos.y-wantedPos.y); if(owner->pos.distance(wantedPos)<4 && abs(owner->heading-unit->heading)<50 && owner->updir.dot(UpVector)>0.995f){ am->dontCheckCol=false; am->dontLand=true; std::vector<int> args; args.push_back((int)(unit->model->height*65536)); owner->cob->Call("BeginTransport",args); std::vector<int> args2; args2.push_back(0); args2.push_back((int)(unit->model->height*65536)); owner->cob->Call("QueryTransport",args2); ((CTransportUnit*)owner)->AttachUnit(unit,args2[0]); am->SetWantedAltitude(0); FinishCommand(); return; } } else { inCommand=true; scriptReady=false; StopMove(); std::vector<int> args; args.push_back(unit->id); owner->cob->Call("TransportPickup",args,ScriptCallback,this,0); } } } else { FinishCommand(); } } else if(c.params.size()==4){ //load in radius if(lastCall==gs->frameNum) //avoid infinite loops return; lastCall=gs->frameNum; float3 pos(c.params[0],c.params[1],c.params[2]); float radius=c.params[3]; CUnit* unit=FindUnitToTransport(pos,radius); if(unit && ((CTransportUnit*)owner)->transportCapacityUsed < owner->unitDef->transportCapacity){ Command c2; c2.id=CMD_LOAD_UNITS; c2.params.push_back(unit->id); c2.options=c.options | INTERNAL_ORDER; commandQue.push_front(c2); inCommand=false; SlowUpdate(); return; } else { FinishCommand(); return; } } return; }
void CTransportCAI::ExecuteLoadUnits(Command& c) { CTransportUnit* transport = reinterpret_cast<CTransportUnit*>(owner); if (c.params.size() == 1) { // load single unit CUnit* unit = unitHandler->GetUnit(c.params[0]); if (!unit) { FinishCommand(); return; } if (c.options & INTERNAL_ORDER) { if (unit->commandAI->commandQue.empty()) { if (!LoadStillValid(unit)) { FinishCommand(); return; } } else { Command& currentUnitCommand = unit->commandAI->commandQue[0]; if ((currentUnitCommand.GetID() == CMD_LOAD_ONTO) && (currentUnitCommand.params.size() == 1) && (int(currentUnitCommand.params[0]) == owner->id)) { if ((unit->moveType->progressState == AMoveType::Failed) && (owner->moveType->progressState == AMoveType::Failed)) { unit->commandAI->FinishCommand(); FinishCommand(); return; } } else if (!LoadStillValid(unit)) { FinishCommand(); return; } } } if (inCommand) { if (!owner->script->IsBusy()) { FinishCommand(); } return; } if (unit && CanTransport(unit) && UpdateTargetLostTimer(int(c.params[0]))) { SetTransportee(unit); const float sqDist = unit->pos.SqDistance2D(owner->pos); const bool inLoadingRadius = (sqDist <= Square(owner->unitDef->loadingRadius)); CHoverAirMoveType* am = dynamic_cast<CHoverAirMoveType*>(owner->moveType); // subtracting 1 square to account for pathfinder/groundmovetype inaccuracy if (goalPos.SqDistance2D(unit->pos) > Square(owner->unitDef->loadingRadius - SQUARE_SIZE) || (!inLoadingRadius && (!owner->isMoving || (am && am->aircraftState != AAirMoveType::AIRCRAFT_FLYING)))) { SetGoal(unit->pos, owner->pos, std::min(64.0f, owner->unitDef->loadingRadius)); } if (inLoadingRadius) { if (am) { // handle air transports differently float3 wantedPos = unit->pos; wantedPos.y = static_cast<CTransportUnit*>(owner)->GetLoadUnloadHeight(wantedPos, unit); SetGoal(wantedPos, owner->pos); am->loadingUnits = true; am->ForceHeading(static_cast<CTransportUnit*>(owner)->GetLoadUnloadHeading(unit)); am->SetWantedAltitude(wantedPos.y - ground->GetHeightAboveWater(wantedPos.x, wantedPos.z)); am->maxDrift = 1; if ((owner->pos.SqDistance(wantedPos) < Square(AIRTRANSPORT_DOCKING_RADIUS)) && (abs(owner->heading-unit->heading) < AIRTRANSPORT_DOCKING_ANGLE) && (owner->updir.dot(UpVector) > 0.995f)) { am->loadingUnits = false; am->dontLand = true; owner->script->BeginTransport(unit); SetTransportee(NULL); transport->AttachUnit(unit, owner->script->QueryTransport(unit)); am->SetWantedAltitude(0); FinishCommand(); return; } } else { inCommand = true; StopMove(); owner->script->TransportPickup(unit); } } else if (owner->moveType->progressState == AMoveType::Failed && sqDist < (200 * 200)) { // if we're pretty close already but CGroundMoveType fails because it considers // the goal clogged (with the future passenger...), just try to move to the // point halfway between the transport and the passenger. SetGoal((unit->pos + owner->pos) * 0.5f, owner->pos); } } else { FinishCommand(); } } else if (c.params.size() == 4) { // area-load if (lastCall == gs->frameNum) { // avoid infinite loops return; } lastCall = gs->frameNum; const float3 pos = c.GetPos(0); const float radius = c.params[3]; CUnit* unit = FindUnitToTransport(pos, radius); if (unit && CanTransport(unit)) { Command c2(CMD_LOAD_UNITS, c.options|INTERNAL_ORDER, unit->id); commandQue.push_front(c2); inCommand = false; SlowUpdate(); return; } else { FinishCommand(); return; } } isFirstIteration = true; startingDropPos = float3(-1.0f, -1.0f, -1.0f); }