void CUnitScript::DropUnit(int u) { #ifndef _CONSOLE CTransportUnit* tu = dynamic_cast<CTransportUnit*>(unit); if (tu && uh->units[u]) { tu->DetachUnit(uh->units[u]); } #endif }
void CTransportCAI::ExecuteUnloadUnit(Command &c) { CTransportUnit* transport = (CTransportUnit*)owner; if (inCommand) { if (!owner->cob->busy) { // if(scriptReady) FinishCommand(); } } else { const std::list<CTransportUnit::TransportedUnit>& transList = transport->transported; if (transList.empty()) { FinishCommand(); return; } float3 pos(c.params[0], c.params[1], c.params[2]); if(goalPos.distance2D(pos) > 20){ SetGoal(pos, owner->pos); } CUnit* unit = NULL; if (c.params.size() < 4) { unit = transList.front().unit; } else { const int unitID = (int)c.params[3]; std::list<CTransportUnit::TransportedUnit>::const_iterator it; for (it = transList.begin(); it != transList.end(); ++it) { CUnit* carried = it->unit; if (unitID == carried->id) { unit = carried; break; } } if (unit == NULL) { FinishCommand(); return; } } if (pos.distance2D(owner->pos) < (owner->unitDef->loadingRadius * 0.9f)) { CTAAirMoveType* am = dynamic_cast<CTAAirMoveType*>(owner->moveType); if (am != NULL) { // handle air transports differently pos.y = ground->GetHeight(pos.x, pos.z); const float3 wantedPos = pos + UpVector * unit->model->height; SetGoal(wantedPos, owner->pos); am->SetWantedAltitude(unit->model->height); am->maxDrift = 1; if ((owner->pos.distance(wantedPos) < 8) && (owner->updir.dot(UpVector) > 0.99f)) { am->dontLand = false; owner->cob->Call("EndTransport"); transport->DetachUnit(unit); const float3 fix = owner->pos + owner->frontdir * 20; SetGoal(fix, owner->pos); //move the transport away slightly FinishCommand(); } } else { inCommand = true; scriptReady = false; StopMove(); std::vector<int> args; args.push_back(transList.front().unit->id); args.push_back(PACKXZ(pos.x, pos.z)); owner->cob->Call("TransportDrop", args, ScriptCallback, this, 0); } } } return; }
void CTransportCAI::UnloadLand(Command& c) { // default unload CTransportUnit* transport = static_cast<CTransportUnit*>(owner); CUnit* transportee = NULL; float3 wantedPos = c.GetPos(0); if (inCommand) { if (!owner->script->IsBusy()) { FinishCommand(); } } else { const std::list<CTransportUnit::TransportedUnit>& transportees = transport->GetTransportedUnits(); if (transportees.empty()) { FinishCommand(); return; } SetGoal(wantedPos, owner->pos); if (c.params.size() < 4) { // unload the first transportee transportee = (transportees.front()).unit; } else { const int unitID = c.params[3]; // unload a specific transportee for (auto it = transportees.begin(); it != transportees.end(); ++it) { CUnit* carried = it->unit; if (unitID == carried->id) { transportee = carried; break; } } if (transportee == NULL) { FinishCommand(); return; } } if (wantedPos.SqDistance2D(owner->pos) < Square(owner->unitDef->loadingRadius * 0.9f)) { CHoverAirMoveType* am = dynamic_cast<CHoverAirMoveType*>(owner->moveType); wantedPos.y = static_cast<CTransportUnit*>(owner)->GetTransporteeWantedHeight(wantedPos, transportee); if (am != NULL) { // handle air transports differently SetGoal(wantedPos, owner->pos); am->SetWantedAltitude(wantedPos.y - CGround::GetHeightAboveWater(wantedPos.x, wantedPos.z)); am->ForceHeading(static_cast<CTransportUnit*>(owner)->GetTransporteeWantedHeading(transportee)); am->maxDrift = 1.0f; // FIXME: kill the hardcoded constants, use the command's radius // NOTE: 2D distance-check would mean units get dropped from air const bool b1 = (owner->pos.SqDistance(wantedPos) < Square(AIRTRANSPORT_DOCKING_RADIUS)); const bool b2 = (std::abs(owner->heading - am->GetForcedHeading()) < AIRTRANSPORT_DOCKING_ANGLE); const bool b3 = (owner->updir.dot(UpVector) > 0.99f); if (b1 && b2 && b3) { wantedPos.y -= transportee->radius; if (!SpotIsClearIgnoreSelf(wantedPos, transportee)) { // chosen spot is no longer clear to land, choose a new one // if a new spot cannot be found, don't unload at all float3 newWantedPos; if (FindEmptySpot(wantedPos, std::max(16.0f * SQUARE_SIZE, transportee->radius * 4.0f), transportee->radius, newWantedPos, transportee)) { c.SetPos(0, newWantedPos); SetGoal(newWantedPos + UpVector * transportee->model->height, owner->pos); return; } } else { transport->DetachUnit(transportee); if (transportees.empty()) { am->SetAllowLanding(true); owner->script->EndTransport(); } } // move the transport away slightly SetGoal(owner->pos + owner->frontdir * 20.0f, owner->pos); FinishCommand(); } } else { inCommand = true; StopMove(); owner->script->TransportDrop(transportee, wantedPos); } } } }
void CTransportCAI::UnloadLand(Command& c) { //default unload CTransportUnit* transport = static_cast<CTransportUnit*>(owner); if (inCommand) { if (!owner->script->IsBusy()) { FinishCommand(); } } else { const std::list<CTransportUnit::TransportedUnit>& transList = transport->GetTransportedUnits(); if (transList.empty()) { FinishCommand(); return; } float3 pos = c.GetPos(0); if (goalPos.SqDistance2D(pos) > 400) { SetGoal(pos, owner->pos); } CUnit* unit = NULL; if (c.params.size() < 4) { unit = transList.front().unit; } else { const int unitID = (int)c.params[3]; std::list<CTransportUnit::TransportedUnit>::const_iterator it; for (it = transList.begin(); it != transList.end(); ++it) { CUnit* carried = it->unit; if (unitID == carried->id) { unit = carried; break; } } if (unit == NULL) { FinishCommand(); return; } } if (pos.SqDistance2D(owner->pos) < Square(owner->unitDef->loadingRadius * 0.9f)) { CHoverAirMoveType* am = dynamic_cast<CHoverAirMoveType*>(owner->moveType); pos.y = static_cast<CTransportUnit*>(owner)->GetLoadUnloadHeight(pos, unit); if (am != NULL) { // handle air transports differently SetGoal(pos, owner->pos); am->SetWantedAltitude(pos.y - ground->GetHeightAboveWater(pos.x, pos.z)); float unloadHeading = static_cast<CTransportUnit*>(owner)->GetLoadUnloadHeading(unit); am->ForceHeading(unloadHeading); am->maxDrift = 1; if ((owner->pos.SqDistance(pos) < 64) && (owner->updir.dot(UpVector) > 0.99f) && math::fabs(owner->heading - unloadHeading) < AIRTRANSPORT_DOCKING_ANGLE) { pos.y -= unit->radius; if (!SpotIsClearIgnoreSelf(pos, unit)) { // chosen spot is no longer clear to land, choose a new one // if a new spot cannot be found, don't unload at all float3 newpos; if (FindEmptySpot(pos, std::max(16.0f * SQUARE_SIZE, unit->radius * 4.0f), unit->radius, newpos, unit)) { c.SetPos(0, newpos); SetGoal(newpos + UpVector * unit->model->height, owner->pos); return; } } else { transport->DetachUnit(unit); if (transport->GetTransportedUnits().empty()) { am->dontLand = false; owner->script->EndTransport(); } } const float3 fix = owner->pos + owner->frontdir * 20; SetGoal(fix, owner->pos); // move the transport away slightly FinishCommand(); } } else { inCommand = true; StopMove(); owner->script->TransportDrop(unit, pos); } } } }