Finish airborne extraction after 30 seconds and hold rescue aircraft; record Workshop 0.0.134
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -8,6 +8,16 @@ class ERR_RescueRules
|
||||
if (since < 0 || now < since) return now;
|
||||
return since;
|
||||
}
|
||||
static float AirborneSince(bool airborne, float since, float now)
|
||||
{
|
||||
if (!airborne || now < 0) return -1;
|
||||
if (since < 0 || now < since) return now;
|
||||
return since;
|
||||
}
|
||||
static bool FlightComplete(float since, float now)
|
||||
{
|
||||
return since >= 0 && now >= since && now - since >= 30000;
|
||||
}
|
||||
static bool CanDepart(float since, float now)
|
||||
{
|
||||
return since >= 0 && now >= since && now - since >= 8000;
|
||||
@@ -234,6 +244,7 @@ class ERR_ExtractionService
|
||||
protected bool m_Stopped;
|
||||
protected vector m_Center;
|
||||
protected float m_Radius;
|
||||
protected float m_AirborneSince = -1;
|
||||
protected ERR_ExtractionState m_State;
|
||||
protected ref set<UUID> m_Escapees = new set<UUID>();
|
||||
protected int m_ParticipantCount;
|
||||
@@ -328,8 +339,12 @@ class ERR_ExtractionService
|
||||
if (m_State != ERR_ExtractionState.WAITING || !m_Assigned) return;
|
||||
if (!FleetAlive()) { Resolve(ERR_ExtractionState.LOST); return; }
|
||||
if (m_Stage != 5 || phase != ERR_Phase.EXTRACTION) return;
|
||||
bool airborne = !m_Transports.IsEmpty();
|
||||
foreach (ERR_RescueFlightComponent departing : m_Transports)
|
||||
if (vector.DistanceXZ(departing.Aircraft().GetOrigin(), m_Pickup) < 1000 || vector.DistanceXZ(departing.Aircraft().GetOrigin(), m_Center) <= m_Radius) return;
|
||||
if (!departing || !departing.AirborneAfterPickup()) airborne = false;
|
||||
float now = GetGame().GetWorld().GetWorldTime();
|
||||
m_AirborneSince = ERR_RescueRules.AirborneSince(airborne, m_AirborneSince, now);
|
||||
if (!ERR_RescueRules.FlightComplete(m_AirborneSince, now)) return;
|
||||
array<ref ERR_PlayerLife> lives = {};
|
||||
m_Roster.Participants(lives);
|
||||
foreach (ERR_PlayerLife life : lives)
|
||||
@@ -359,6 +374,13 @@ class ERR_ExtractionService
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
// Capture the final aircraft state before terminal cleanup releases autopilots
|
||||
// and removes the AI groups. Keep the same occupied airframes until reload.
|
||||
if (m_State == ERR_ExtractionState.ESCAPED)
|
||||
{
|
||||
foreach (ERR_RescueFlightComponent safeTransport : m_Transports) if (safeTransport) safeTransport.HoldForResults();
|
||||
foreach (ERR_RescueFlightComponent safeEscort : m_Escorts) if (safeEscort && !safeEscort.Lost()) safeEscort.HoldForResults();
|
||||
}
|
||||
m_Stopped = true; m_RadioPending = ""; m_PreviousSignals.Clear();
|
||||
foreach (ERR_RescueFlightComponent transport : m_Transports) if (transport) transport.Release(false);
|
||||
foreach (ERR_RescueFlightComponent escort : m_Escorts) if (escort) escort.Release(false);
|
||||
|
||||
@@ -56,7 +56,7 @@ modded class ERR_GameMode
|
||||
float now = GetWorld().GetWorldTime();
|
||||
if (Phase() == ERR_Phase.VICTORY)
|
||||
{
|
||||
ERR_RescueCheck(Extraction().EscapedCount() == 1, "native flight carried the original prisoner across the escape boundary");
|
||||
ERR_RescueCheck(Extraction().EscapedCount() == 1, "native flight carried the original prisoner through thirty seconds of airborne evacuation");
|
||||
Print("ERR RESCUE COMPLETE"); GetGame().GetCallqueue().Remove(ERR_RescueProbeTick); return;
|
||||
}
|
||||
if (!PreparationError().IsEmpty() || Phase() == ERR_Phase.DEFEAT) { ERR_RescueCheck(false, "mission failed: " + PreparationError()); return; }
|
||||
|
||||
@@ -18,6 +18,47 @@ class ERR_RescueFlightComponentClass : ERR_ReconFlightComponentClass {}
|
||||
class ERR_RescueFlightComponent : ERR_ReconFlightComponent
|
||||
{
|
||||
protected bool m_Escort, m_Departing, m_LandingConfirmed;
|
||||
[RplProp(onRplName: "ApplyResultsHold")] protected bool m_ResultsHeld;
|
||||
// Contact plus real clearance excludes boarding, engine spin-up, and the
|
||||
// controller's ten-second grounded takeoff hold. Every transport must lift.
|
||||
bool AirborneAfterPickup()
|
||||
{
|
||||
if (!m_Departing || m_Lost || !m_Aircraft) return false;
|
||||
VehicleHelicopterSimulation sim = VehicleHelicopterSimulation.Cast(m_Aircraft.FindComponent(VehicleHelicopterSimulation));
|
||||
if (!sim || sim.HasAnyGroundContact()) return false;
|
||||
float ground = SCR_TerrainHelper.GetTerrainY(m_Aircraft.GetOrigin(), GetGame().GetWorld(), noUnderwater: true);
|
||||
return m_Aircraft.GetOrigin()[1] - ground >= 3;
|
||||
}
|
||||
void HoldForResults()
|
||||
{
|
||||
if (!Replication.IsServer() || m_Lost || !ERR_Actors.Alive(GetOwner()) || m_ResultsHeld) return;
|
||||
m_ResultsHeld = true;
|
||||
ApplyResultsHold();
|
||||
Replication.BumpMe();
|
||||
}
|
||||
protected void ApplyResultsHold()
|
||||
{
|
||||
if (!m_ResultsHeld || !GetOwner()) return;
|
||||
Physics physics = GetOwner().GetPhysics();
|
||||
if (physics)
|
||||
{
|
||||
physics.SetVelocity(vector.Zero);
|
||||
physics.SetAngularVelocity(vector.Zero);
|
||||
physics.ChangeSimulationState(SimulationState.COLLISION);
|
||||
}
|
||||
if (Replication.IsServer())
|
||||
{
|
||||
DamageManagerComponent damage = DamageManagerComponent.Cast(GetOwner().FindComponent(DamageManagerComponent));
|
||||
if (damage) damage.EnableDamageHandling(false);
|
||||
}
|
||||
}
|
||||
override void Release(bool captured)
|
||||
{
|
||||
// Terminal presentation keeps the engines/rotors; physics is already held.
|
||||
// Ordinary lost/captured/aborted flights retain their original cleanup.
|
||||
super.Release(captured || m_ResultsHeld);
|
||||
}
|
||||
|
||||
protected float m_BoardingReadySince = -1;
|
||||
protected vector m_Pickup;
|
||||
protected float m_RescueDeadline, m_NextThreat;
|
||||
@@ -168,6 +209,7 @@ class ERR_RescueFlightComponent : ERR_ReconFlightComponent
|
||||
}
|
||||
override void EOnSimulate(IEntity owner, float timeSlice)
|
||||
{
|
||||
if (m_ResultsHeld) { ApplyResultsHold(); return; }
|
||||
// Initial airborne crew allocation has a fixed 45-second deadline.
|
||||
if (Replication.IsServer() && m_Initialized && m_Phase == ERR_ReconPhase.CREW)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user