Improve base guidance and qualify bounded aircraft route and hidden test lifecycle
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
// Experimental direct leg only; the original point envelope is unchanged.
|
||||
class ERR_AircraftRouteRules
|
||||
{
|
||||
static bool Length(float distance) { return distance >= 18 && distance <= 20.05; }
|
||||
static vector Nearest(vector start, vector end, vector point)
|
||||
{
|
||||
vector leg = end - start; leg[1] = 0;
|
||||
vector offset = point - start; offset[1] = 0;
|
||||
float squared = vector.Dot(leg, leg);
|
||||
if (!(squared > 0)) return start;
|
||||
return start + leg * Math.Clamp(vector.Dot(offset, leg) / squared, 0, 1);
|
||||
}
|
||||
static bool Contains(vector start, vector end, vector point, float upright)
|
||||
{
|
||||
if (!Length(vector.DistanceXZ(start, end))) return false;
|
||||
float height = point[1] - start[1];
|
||||
return height >= -3 && height <= 18 && upright >= 0.85 && vector.DistanceXZ(point, Nearest(start, end, point)) < 8;
|
||||
}
|
||||
static bool Held(bool contact, float height, float speed, float vertical, float upright, float horizontal, float error)
|
||||
{
|
||||
return !contact && ERR_AircraftFlightRules.Hover(height, speed, vertical, upright) && horizontal >= 0 && horizontal < 0.25 && error >= 0 && error <= 0.75;
|
||||
}
|
||||
}
|
||||
|
||||
// Inherits the exact single-claim identity/clock guard, not caller-supplied validity.
|
||||
class ERR_AircraftRouteEnvelope : ERR_AircraftFlightEnvelope
|
||||
{
|
||||
protected vector m_Destination;
|
||||
vector Destination() { return m_Destination; }
|
||||
bool Contains(vector position, float upright) { return ERR_AircraftRouteRules.Contains(m_Home, m_Destination, position, upright); }
|
||||
// This deliberately qualifies a larger enclosing rectangle, not just endpoints.
|
||||
// Whole-model/rotor radius+8m deviation+1m margin already fits the 40m half-width.
|
||||
static bool Survey(vector start, vector end, array<IEntity> excluded = null)
|
||||
{
|
||||
if (!GetGame() || !GetGame().GetWorld() || !ERR_AircraftRouteRules.Length(vector.DistanceXZ(start, end))) return false;
|
||||
vector lower, upper;
|
||||
for (int axis = 0; axis < 3; axis++)
|
||||
{
|
||||
lower[axis] = Math.Min(start[axis], end[axis]);
|
||||
upper[axis] = Math.Max(start[axis], end[axis]);
|
||||
}
|
||||
// Near-level bare-ground route. Grid covers both pads and every possible
|
||||
// corridor landing centre plus the native gear footprint, at <=2m spacing.
|
||||
float spanX = upper[0] - lower[0] + 44, spanZ = upper[2] - lower[2] + 44;
|
||||
int columns = Math.Ceil(spanX / 2), rows = Math.Ceil(spanZ / 2);
|
||||
if (columns > 34 || rows > 34) return false;
|
||||
for (int x = 0; x <= columns; x++)
|
||||
for (int z = 0; z <= rows; z++)
|
||||
{
|
||||
vector sample = Vector(lower[0] - 22 + spanX * x / columns, 0, lower[2] - 22 + spanZ * z / rows);
|
||||
if (!(Math.AbsFloat(SCR_TerrainHelper.GetTerrainY(sample) - start[1]) <= 0.3)) return false;
|
||||
}
|
||||
vector centre = (lower + upper) * 0.5; centre[1] = start[1];
|
||||
vector half = (upper - lower) * 0.5; half[0] = half[0] + 40; half[2] = half[2] + 40;
|
||||
TraceBox corridor = new TraceBox();
|
||||
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;
|
||||
// Separate low object sweep makes intermediate emergency landing ground as
|
||||
// conservative as both endpoints; WORLD is above because the ground is wanted.
|
||||
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;
|
||||
}
|
||||
static ERR_AircraftRouteEnvelope QualifyRoute(ERR_GameMode mode, Vehicle aircraft, IEntity pilot, vector destination)
|
||||
{
|
||||
// Existing native qualification supplies health, seat, complete rotor/model
|
||||
// footprint, near-ground and exact original-airframe checks; no bypass.
|
||||
ERR_AircraftFlightEnvelope point = ERR_AircraftFlightEnvelope.Qualify(mode, aircraft, pilot);
|
||||
if (!point) return null;
|
||||
vector start = ERR_Actors.Ground(point.Home());
|
||||
vector end = ERR_Actors.Ground(destination);
|
||||
if (!ERR_AircraftRouteRules.Length(vector.DistanceXZ(start, end)) || !(end[1] >= 2) || !(Math.AbsFloat(end[1] - start[1]) <= 0.3)) return null;
|
||||
array<IEntity> excluded = {};
|
||||
if (!Hierarchy(aircraft, excluded) || !Hierarchy(pilot, excluded)) return null;
|
||||
if (!ClearColumn(aircraft, pilot, end) || !Survey(start, end, excluded)) return null;
|
||||
ERR_AircraftRouteEnvelope record = new ERR_AircraftRouteEnvelope();
|
||||
record.m_Mode = mode; record.m_Aircraft = aircraft; record.m_Pilot = pilot;
|
||||
record.m_Home = point.Home(); record.m_Radius = point.Radius();
|
||||
record.m_Destination = end; record.m_Destination[1] = record.m_Home[1];
|
||||
record.m_QualifiedAt = GetGame().GetWorld().GetWorldTime();
|
||||
return record;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user