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
@@ -22,12 +22,50 @@ class ERR_AircraftFieldEnvelope : ERR_AircraftFlightEnvelope
if (columns < 1 || rows < 1 || columns >= MAX_TERRAIN_NODES || rows >= MAX_TERRAIN_NODES) return false;
return (columns + 1) * (rows + 1) <= MAX_TERRAIN_NODES;
}
#ifdef WORKBENCH
// At most the first refusal of each exact survey call is logged. No query,
// predicate, retry or resource allocation is added to the qualification.
protected static bool SurveyDiagnostics()
{
string enabled, outcome;
return System.GetCLIParam("errSmoke", enabled) && enabled == "1" && System.GetCLIParam("errSmokeOutcome", outcome) && outcome == "aircraft-field";
}
protected static void SurveyTraceFailure(string stage, float fraction, TraceBox trace)
{
if (!SurveyDiagnostics()) return;
IEntity hit = trace.TraceEnt;
string kind = "none", resource = "";
if (hit)
{
kind = hit.Type().ToString();
if (hit.GetPrefabData()) resource = hit.GetPrefabData().GetPrefabName();
}
if (hit)
{
vector lower, upper; hit.GetWorldBounds(lower, upper);
PrintFormat("ERR AIRCRAFT FIELD SURVEY HIT BOUNDS: lower=%1 upper=%2", lower, upper);
}
PrintFormat("ERR AIRCRAFT FIELD SURVEY REFUSED: stage=%1 fraction=%2 entity=%3 class=%4 prefab=%5 start=%6 end=%7", stage, fraction, hit, kind, resource, trace.Start, trace.End);
}
#endif
static bool Survey(vector start, vector end, array<IEntity> excluded = null)
{
if (!GetGame() || !GetGame().GetWorld() || !FinitePoint(start) || !FinitePoint(end)) return false;
if (!GetGame() || !GetGame().GetWorld() || !FinitePoint(start) || !FinitePoint(end))
{
#ifdef WORKBENCH
if (SurveyDiagnostics()) PrintFormat("ERR AIRCRAFT FIELD SURVEY REFUSED: stage=context-or-finite-points start=%1 end=%2", start, end);
#endif
return false;
}
float distance = vector.DistanceXZ(start, end);
int columns = TerrainColumns(distance), rows = 40;
if (!TerrainBudget(columns, rows) || !(start[1] >= 2) || !(Math.AbsFloat(end[1] - start[1]) <= 0.3)) return false;
if (!TerrainBudget(columns, rows) || !(start[1] >= 2) || !(Math.AbsFloat(end[1] - start[1]) <= 0.3))
{
#ifdef WORKBENCH
if (SurveyDiagnostics()) PrintFormat("ERR AIRCRAFT FIELD SURVEY REFUSED: stage=budget-or-endpoints start=%1 end=%2 distance=%3 columns=%4 rows=%5 startHeight=%6 endHeight=%7 delta=%8", start, end, distance, columns, rows, start[1], end[1], Math.AbsFloat(end[1] - start[1]));
#endif
return false;
}
vector along = end - start; along[1] = 0; along = along * (1 / distance);
vector across = Vector(-along[2], 0, along[0]);
float span = distance + 80;
@@ -38,7 +76,14 @@ class ERR_AircraftFieldEnvelope : ERR_AircraftFlightEnvelope
for (int z = 0; z <= rows; z++)
{
vector sample = start + along * (-40 + span * x / columns) + across * (-40 + 80 * z / rows);
if (!(Math.AbsFloat(SCR_TerrainHelper.GetTerrainY(sample) - start[1]) <= 0.3)) return false;
float terrain = SCR_TerrainHelper.GetTerrainY(sample);
if (!(Math.AbsFloat(terrain - start[1]) <= 0.3))
{
#ifdef WORKBENCH
if (SurveyDiagnostics()) PrintFormat("ERR AIRCRAFT FIELD SURVEY REFUSED: stage=terrain x=%1 z=%2 columns=%3 rows=%4 sample=%5 terrainHeight=%6 startHeight=%7 delta=%8", x, z, columns, rows, sample, terrain, start[1], Math.AbsFloat(terrain - start[1]));
#endif
return false;
}
}
vector lower, upper;
for (int axis = 0; axis < 3; axis++)
@@ -55,11 +100,22 @@ class ERR_AircraftFieldEnvelope : ERR_AircraftFlightEnvelope
corridor.Start = centre + "0 3 0"; corridor.End = centre + "0 60 0";
corridor.Mins = Vector(-half[0], -1, -half[2]); corridor.Maxs = Vector(half[0], 1, half[2]);
corridor.Flags = TraceFlags.ENTS | TraceFlags.WORLD; corridor.ExcludeArray = excluded;
if (!(GetGame().GetWorld().TraceMove(corridor, null) >= 1)) return false;
float corridorFraction = GetGame().GetWorld().TraceMove(corridor, null);
if (!(corridorFraction >= 1))
{
#ifdef WORKBENCH
SurveyTraceFailure("corridor", corridorFraction, corridor);
#endif
return false;
}
TraceBox low = new TraceBox(); low.Start = centre + "0 0.5 0"; low.End = centre + "0 3 0";
low.Mins = Vector(-half[0], -0.2, -half[2]); low.Maxs = Vector(half[0], 0.2, half[2]);
low.Flags = TraceFlags.ENTS; low.ExcludeArray = excluded;
return GetGame().GetWorld().TraceMove(low, null) >= 1;
float lowFraction = GetGame().GetWorld().TraceMove(low, null);
#ifdef WORKBENCH
if (!(lowFraction >= 1)) SurveyTraceFailure("low-objects", lowFraction, low);
#endif
return lowFraction >= 1;
}
static ERR_AircraftFieldEnvelope QualifyField(ERR_GameMode mode, Vehicle aircraft, IEntity pilot, vector destination)
{