Prepare independent successor playtest with spawn recovery and casualty feedback

This commit is contained in:
2026-09-19 22:12:52 +02:00
parent 61e165ef5b
commit 6cf989a060
266 changed files with 134064 additions and 154 deletions
@@ -18,7 +18,7 @@ modded class ERR_AircraftFieldFlight
bool alreadyFrozen = m_FieldStopFrozen;
bool result = super.BeginFieldBrake(now);
ERR_NativeAircraftFieldProbe probe = ERR_NativeAircraftFieldProbe.Current();
if (result && !alreadyFrozen && probe && m_Aircraft && m_Simulation) probe.BrakeBegan(this, now, m_Aircraft.GetOrigin(), m_Simulation.GetVelocity());
if (result && !alreadyFrozen && probe && m_Aircraft && m_Simulation) probe.BrakeBegan(this, now, m_Aircraft.GetOrigin(), m_Simulation.GetVelocity(), m_Simulation.HasAnyGroundContact());
return result;
}
protected override void CheckTranslation(float now, vector position, float height, float speed, float upright)
@@ -26,7 +26,7 @@ modded class ERR_AircraftFieldFlight
int oldPhase = m_FieldPhase;
super.CheckTranslation(now, position, height, speed, upright);
ERR_NativeAircraftFieldProbe probe = ERR_NativeAircraftFieldProbe.Current();
if (oldPhase == 2 && m_FieldPhase == 3 && probe && m_Aircraft && m_Simulation) probe.BrakeStopped(this, now, m_Aircraft.GetOrigin(), m_Simulation.GetVelocity());
if (oldPhase == 2 && m_FieldPhase == 3 && probe && m_Aircraft && m_Simulation) probe.BrakeStopped(this, now, m_Aircraft.GetOrigin(), m_Simulation.GetVelocity(), m_Simulation.HasAnyGroundContact());
}
}
@@ -65,9 +65,9 @@ class ERR_NativeAircraftFieldRules
{
return phase == 1 && !contact && alongSpeed >= 1 && horizontal >= 1 && horizontal <= 2.5;
}
static bool Braking(float reserve, float sampledTravel, float displacement, float lowSince, float now, float horizontal)
static bool Braking(float reserve, float sampledTravel, float displacement, float lowSince, float now, float horizontal, bool contactObserved)
{
return reserve >= 3 && reserve <= 26.334 && sampledTravel >= 0 && sampledTravel <= reserve && displacement >= 0 && displacement <= reserve && horizontal >= 0 && horizontal < 0.25 && lowSince >= 0 && now - lowSince >= 2000;
return !contactObserved && reserve >= 3 && reserve <= 26.334 && sampledTravel >= 0 && sampledTravel <= reserve && displacement >= 0 && displacement <= reserve && horizontal >= 0 && horizontal < 0.25 && lowSince >= 0 && now - lowSince >= 2000;
}
static bool Terminal(bool cancellation, int state, int stops, bool arrived, bool cruiseHeld, bool endpointHeld, bool braking, float displacement, float targetError)
{
@@ -123,6 +123,7 @@ class ERR_NativeAircraftFieldProbe
protected bool m_BrakeObserved;
protected bool m_BrakeStopped;
protected bool m_BrakePassed;
protected bool m_BrakeContactObserved;
protected string m_ObservationFailure;
protected vector m_BrakeOrigin;
protected vector m_BrakeLandingPoint;
@@ -140,6 +141,7 @@ class ERR_NativeAircraftFieldProbe
protected int m_HelicopterHooks;
protected bool m_LastEngine;
protected bool m_AllocationRequested;
protected bool m_TerrainAudited;
protected bool m_PilotRequested;
protected bool m_Stopped;
protected bool m_Complete;
@@ -196,14 +198,49 @@ class ERR_NativeAircraftFieldProbe
if (m_Stopped || !m_Flight || controller != m_Controller) return;
// Observation only: super-chain order cannot cause a second control write.
m_HelicopterHooks++;
ObserveBrakingContact(!m_Simulation || m_Simulation.HasAnyGroundContact());
}
static bool TerrainAuditEnabled()
{
string audit, cancellation;
return Enabled() && System.GetCLIParam("errSmokeFieldTerrainAudit", audit) && audit == "1" && !(System.GetCLIParam("errSmokeFieldServiceCancel", cancellation) && cancellation == "1");
}
protected void AuditTerrain()
{
if (m_TerrainAudited || !TerrainAuditEnabled() || m_Stopped || m_AllocationRequested || m_Aircraft || m_Group || m_Pilot || !GetGame() || !GetGame().GetWorld()) return;
m_TerrainAudited = true;
// Read-only fixed coarse grid for offline corridor authorship. No selected
// candidate, fallback, traces, entity allocation or qualification is produced.
Print("ERR AIRCRAFT FIELD TERRAIN AUDIT BEGIN: minX=4750 maxX=5150 minZ=11600 maxZ=12000 spacing=10 columns=41 rows=41 nodes=1681");
for (int x = 0; x <= 40; x++)
{
for (int z = 0; z <= 40; z++)
{
vector point = "0 0 0";
point[0] = 4750 + x * 10; point[2] = 11600 + z * 10;
float terrain = SCR_TerrainHelper.GetTerrainY(point);
int index = x * 41 + z;
if (!(Math.AbsFloat(terrain) <= 1000000))
{
PrintFormat("ERR AIRCRAFT FIELD TERRAIN AUDIT ABORT: index=%1 x=%2 z=%3 nonfiniteOrInvalidHeight=%4", index, point[0], point[2], terrain);
return;
}
PrintFormat("ERR AIRCRAFT FIELD TERRAIN AUDIT POINT: index=%1 x=%2 z=%3 height=%4", index, point[0], point[2], terrain);
}
}
Print("ERR AIRCRAFT FIELD TERRAIN AUDIT END: nodes=1681; original survey refusal unchanged; no candidate qualified");
}
protected bool FindPad(out vector result)
{
// This exact airport start was observed in the twenty-metre fixture. The
// longer corridor still requires its own complete survey; there is no search.
vector candidate = ERR_Actors.Ground("4850.953 0 11787.412");
vector destination = ERR_Actors.Ground(candidate + "100 0 0");
if (!ERR_AircraftFieldEnvelope.Survey(candidate, destination)) return false;
// Authored from terrain, warehouse and tree evidence: one south-shifted northbound candidate.
// Coarse data grants no clearance; the complete survey below is mandatory.
vector candidate = ERR_Actors.Ground("4890 0 11730");
vector destination = ERR_Actors.Ground(candidate + "0 0 100");
if (!ERR_AircraftFieldEnvelope.Survey(candidate, destination))
{
AuditTerrain();
return false;
}
PrintFormat("ERR AIRCRAFT FIELD FIXTURE CORRIDOR: singleStart=%1 destination=%2; fixed100m complete survey passed", candidate, destination);
result = candidate; m_Destination = destination; return true;
}
@@ -259,27 +296,35 @@ class ERR_NativeAircraftFieldProbe
PrintFormat("ERR AIRCRAFT FIELD MOTION: now=%1 state=%2 phase=%3 position=%4 velocity=%5 refVelocity=%6 integral=%7 observedLocalInput=%8 fuel=%9", now, m_Flight.State(), m_Flight.FieldPhase(), position, velocity, m_Flight.ReferenceVelocity(), m_Flight.IntegralDemand(), m_Flight.ERR_NativeFieldInputDemand(), m_Fuel.GetTotalFuel());
PrintFormat("ERR AIRCRAFT FIELD LEASE: token=%1 originalDeadline=%2 stageDeadline=%3 actions=%4 helicopter=%5 contact=%6 engine=%7 targetError=%8", m_Flight.OrderToken(), m_ControlDeadline, m_Flight.ERR_NativeFieldStageDeadline(), m_Flight.ERR_NativeFieldActionUpdates(), m_Flight.ERR_NativeFieldHelicopterUpdates(), m_Simulation.HasAnyGroundContact(), m_Controller.IsEngineOn(), vector.DistanceXZ(position, m_Flight.LandingPoint()));
}
void BrakeBegan(ERR_AircraftFieldFlight flight, float now, vector position, vector velocity)
void ObserveBrakingContact(bool contact)
{
if (m_Stopped || !m_BrakeObserved || m_BrakeStopped || !contact) return;
m_BrakeContactObserved = true;
m_ObservationFailure = "native ground contact cannot qualify airborne braking";
}
void BrakeBegan(ERR_AircraftFieldFlight flight, float now, vector position, vector velocity, bool contact)
{
if (m_Stopped || flight != m_Flight) return;
if (m_BrakeObserved) { m_ObservationFailure = "production brake event occurs exactly once"; return; }
m_BrakeObserved = true; m_BrakeAt = now;
ObserveBrakingContact(contact);
m_BrakeOrigin = position; m_BrakePrevious = position;
m_BrakeReserve = ERR_AircraftFieldRules.BrakingReserve(ERR_AircraftFieldRules.HorizontalSpeed(velocity));
m_BrakeStageDeadline = flight.ERR_NativeFieldStageDeadline(); m_BrakeLandingPoint = flight.LandingPoint();
PrintFormat("ERR AIRCRAFT FIELD BRAKE OBSERVED: now=%1 position=%2 velocity=%3 declaredHypothesisReserve=%4 stageDeadline=%5 originalDeadline=%6", now, position, velocity, m_BrakeReserve, m_BrakeStageDeadline, m_ControlDeadline);
}
void BrakeStopped(ERR_AircraftFieldFlight flight, float now, vector position, vector velocity)
void BrakeStopped(ERR_AircraftFieldFlight flight, float now, vector position, vector velocity, bool contact)
{
if (m_Stopped || flight != m_Flight) return;
if (!m_BrakeObserved || m_BrakeStopped) { m_ObservationFailure = "one actual low-speed braking transition after original brake event"; return; }
ObserveBrakingContact(contact);
m_BrakeStopped = true;
m_BrakeSampledTravel += vector.DistanceXZ(position, m_BrakePrevious);
m_BrakePrevious = position;
float displacement = vector.DistanceXZ(position, m_BrakeOrigin);
m_BrakePassed = ERR_NativeAircraftFieldRules.Braking(m_BrakeReserve, m_BrakeSampledTravel, displacement, m_BrakeLowSince, now, ERR_AircraftFieldRules.HorizontalSpeed(velocity));
PrintFormat("ERR AIRCRAFT FIELD STOP OBSERVED: now=%1 position=%2 sampledTravel=%3 displacement=%4 declaredReserve=%5 lowSince=%6 passed=%7", now, position, m_BrakeSampledTravel, displacement, m_BrakeReserve, m_BrakeLowSince, m_BrakePassed);
if (!m_BrakePassed) m_ObservationFailure = "observed braking exceeded declared reserve or lacked independent two-second low-speed observations";
m_BrakePassed = ERR_NativeAircraftFieldRules.Braking(m_BrakeReserve, m_BrakeSampledTravel, displacement, m_BrakeLowSince, now, ERR_AircraftFieldRules.HorizontalSpeed(velocity), m_BrakeContactObserved);
PrintFormat("ERR AIRCRAFT FIELD STOP OBSERVED: now=%1 position=%2 sampledTravel=%3 displacement=%4 declaredReserve=%5 lowSince=%6 passed=%7 contactObserved=%8", now, position, m_BrakeSampledTravel, displacement, m_BrakeReserve, m_BrakeLowSince, m_BrakePassed, m_BrakeContactObserved);
if (!m_BrakePassed && !m_BrakeContactObserved) m_ObservationFailure = "observed braking exceeded declared reserve or lacked independent two-second low-speed observations";
}
int Tick(float now)
{
@@ -356,6 +401,7 @@ class ERR_NativeAircraftFieldProbe
if (!StopRetainedField(now)) return -1;
if (m_BrakeObserved && !m_BrakeStopped)
{
ObserveBrakingContact(contact);
m_BrakeSampledTravel += vector.DistanceXZ(position, m_BrakePrevious); m_BrakePrevious = position;
if (!(horizontal < 0.25)) m_BrakeLowSince = -1;
else if (m_BrakeLowSince < 0) m_BrakeLowSince = now;