Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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);
}