bool AAirMoveType::HaveLandedOnPad(const float3& padPos) { const AircraftState landingState = GetLandingState(); const float landingPadHeight = CGround::GetHeightAboveWater(padPos.x, padPos.z); reservedLandingPos = padPos; wantedHeight = padPos.y - landingPadHeight; const float3 padVector = (padPos - owner->pos).SafeNormalize2D(); const float curOwnerAltitude = (owner->pos.y - landingPadHeight); const float minOwnerAltitude = (wantedHeight + 1.0f); if (aircraftState != landingState) SetState(landingState); if (aircraftState == AIRCRAFT_LANDED) return true; if (curOwnerAltitude <= minOwnerAltitude) { // deal with overshooting aircraft: "tractor" them in // once they descend down to the landing pad altitude // this is a no-op for HAMT planes which do not apply // speed updates at this point owner->SetVelocityAndSpeed((owner->speed + (padVector * accRate)) * XZVector); } if (Square(owner->rightdir.y) < 0.01f && owner->frontdir.dot(padVector) > 0.01f) { owner->frontdir = padVector; owner->rightdir = owner->frontdir.cross(UpVector); owner->updir = owner->rightdir.cross(owner->frontdir); owner->SetHeadingFromDirection(); } if (curOwnerAltitude > minOwnerAltitude) return false; return ((owner->pos.SqDistance2D(padPos) <= 1.0f || owner->unitDef->IsHoveringAirUnit())); }
bool AAirMoveType::MoveToRepairPad() { CUnit* airBase = reservedPad->GetUnit(); if (airBase->beingBuilt || airBase->stunned) { // pad became inoperable after being reserved DependentDied(airBase); return false; } else { const float3& relPadPos = airBase->script->GetPiecePos(reservedPad->GetPiece()); const float3 absPadPos = airBase->pos + (airBase->frontdir * relPadPos.z) + (airBase->updir * relPadPos.y) + (airBase->rightdir * relPadPos.x); if (padStatus == 0) { // approaching pad if (aircraftState != AIRCRAFT_FLYING && aircraftState != AIRCRAFT_TAKEOFF) { SetState(AIRCRAFT_FLYING); } goalPos = absPadPos; if (absPadPos.SqDistance2D(owner->pos) < (400.0f * 400.0f)) { padStatus = 1; } } else if (padStatus == 1) { // landing on pad const AircraftState landingState = GetLandingState(); if (aircraftState != landingState) SetState(landingState); goalPos = absPadPos; reservedLandingPos = absPadPos; wantedHeight = absPadPos.y - ground->GetHeightAboveWater(absPadPos.x, absPadPos.z); if ((owner->pos.SqDistance(absPadPos) < SQUARE_SIZE * SQUARE_SIZE) || aircraftState == AIRCRAFT_LANDED) { padStatus = 2; } } else { // taking off from pad if (aircraftState != AIRCRAFT_LANDED) { SetState(AIRCRAFT_LANDED); } owner->pos = absPadPos; owner->UpdateMidPos(); owner->AddBuildPower(airBase->unitDef->buildSpeed / GAME_SPEED, airBase); owner->currentFuel += (owner->unitDef->maxFuel / (GAME_SPEED * owner->unitDef->refuelTime)); owner->currentFuel = std::min(owner->unitDef->maxFuel, owner->currentFuel); if (owner->health >= owner->maxHealth - 1.0f && owner->currentFuel >= owner->unitDef->maxFuel) { // repaired and filled up, leave the pad UnreservePad(reservedPad); } } } return true; }