Integrate delivered HQ memory, finite physical convoy and RHS WCS dependencies

This commit is contained in:
2026-09-20 02:55:30 +02:00
parent e7b4141f69
commit a2aab17171
230 changed files with 37976 additions and 139 deletions
@@ -0,0 +1,344 @@
#ifdef WORKBENCH
// Failure diagnostics only. Every query is read-only and uses the production seed/volume rules.
class ERR_NativeConvoyRoadSurvey
{
void Run(vector seed)
{
if (!ERR_NativeConvoyProbe.Enabled()) return;
SCR_AIWorld world = SCR_AIWorld.Cast(GetGame().GetAIWorld());
if (!world || !world.GetRoadNetworkManager())
{
Print("ERR CONVOY SURVEY: native AI world or road-network manager unavailable"); return;
}
array<BaseRoad> roads = {};
vector low = seed + "-500 -1000 -500", high = seed + "500 1000 500";
world.GetRoadNetworkManager().GetRoadsInAABB(low, high, roads);
PrintFormat("ERR CONVOY SURVEY: seed=%1 AABB=%2..%3 candidates=%4; inspecting at most16, production cap128",
seed, low, high, roads.Count());
for (int r = 0; r < roads.Count() && r < 16; r++)
{
BaseRoad road = roads[r];
if (!road) { Print("ERR CONVOY SURVEY: null candidate"); continue; }
array<vector> points = {}; road.GetPoints(points);
float length, nearest = 1e20;
for (int i = 1; i < points.Count() && i <= 1024; i++)
{
vector delta = points[i] - points[i - 1]; delta[1] = 0;
float segment = delta.Length(); length += segment;
if (segment < 0.01) continue;
vector offset = seed - points[i - 1]; offset[1] = 0;
float fraction = Math.Clamp(vector.Dot(offset, delta) / (segment * segment), 0, 1);
nearest = Math.Min(nearest, vector.DistanceXZ(seed, vector.Lerp(points[i - 1], points[i], fraction)));
}
vector first, last;
if (!points.IsEmpty()) { first = points[0]; last = points[points.Count() - 1]; }
PrintFormat("ERR CONVOY SURVEY: road=%1 width=%2 points=%3 XZlength=%4 nearest=%5 first=%6 last=%7",
r, road.GetWidth(), points.Count(), length, nearest, first, last);
array<vector> positions, angles;
ERR_ForceRoute route;
float proximity;
bool polyline = ERR_ConvoyRoadPlan.FromPolyline(points, seed, positions, angles, route, proximity);
PrintFormat("ERR CONVOY SURVEY: road=%1 widthAllowed=%2 FromPolyline=%3 proximity=%4",
r, road.GetWidth() >= 4, polyline, proximity);
if (!polyline) continue;
for (int i = 0; i < positions.Count(); i++) positions[i] = ERR_Actors.Ground(positions[i]);
ERR_ConvoyPlacement placement = new ERR_ConvoyPlacement();
for (int i = 0; i < positions.Count() && i < 6; i++)
{
bool clear = placement.Clear(positions[i], angles[i][0]);
PrintFormat("ERR CONVOY SURVEY: road=%1 vehicle=%2 ground=%3 heading=%4 GroundClear=%5",
r, i, positions[i], angles[i][0], clear);
Print("ERR CONVOY SURVEY: " + placement.Diagnostic());
}
}
}
}
// Opt-in native fixture: production road survey, canonical HQ dispatch and native driving.
// The fixture does not create vehicles, seat crew, move entities or advance convoy service.
class ERR_NativeConvoyProbe
{
protected ERR_GameMode m_Mode;
protected ref ERR_ConvoyTask m_Task;
protected ref array<vector> m_Origins = {};
protected ref array<IEntity> m_OriginalVehicles = {};
protected ref array<IEntity> m_CargoBefore = {};
protected float m_Deadline;
protected float m_ReadyAt;
protected float m_NextLog;
protected float m_NextMovementDiagnostic;
protected int m_InitialLedger;
protected int m_Step;
protected bool m_Failed;
static bool Enabled()
{
string enabled, outcome;
return Replication.IsServer() && System.GetCLIParam("errSmoke", enabled) && enabled == "1"
&& System.GetCLIParam("errSmokeOutcome", outcome) && outcome == "convoy";
}
void ERR_NativeConvoyProbe(ERR_GameMode mode) { m_Mode = mode; }
protected bool Check(bool condition, string description)
{
if (condition) { Print("ERR SMOKE PASS: convoy " + description); return true; }
m_Failed = true; Print("ERR SMOKE FAIL: convoy " + description, LogLevel.ERROR); return false;
}
protected InventoryStorageManagerComponent TruckInventory()
{
if (!m_Task || m_Task.Vehicles.Count() != 6 || !m_Task.Vehicles[1].Entity) return null;
return InventoryStorageManagerComponent.Cast(m_Task.Vehicles[1].Entity.FindComponent(InventoryStorageManagerComponent));
}
protected void PopulationDiagnostic(ERR_ConvoyVehicle vehicle, array<AIAgent> agents, int expected)
{
PrintFormat("ERR CONVOY POPULATION: vehicle=%1 registered=%2 members=%3 seats=%4 agents=%5 expected=%6",
vehicle.Index, vehicle.Registered, vehicle.Members.Count(), vehicle.Seats.Count(), agents.Count(), expected);
if (vehicle.Index != 0) return;
for (int i = 0; i < agents.Count() && i < 19; i++)
{
AIAgent agent = agents[i];
IEntity controlled;
AIGroup parent;
if (agent) { controlled = agent.GetControlledEntity(); parent = agent.GetParentGroup(); }
string prefab = "none";
if (controlled && controlled.GetPrefabData()) prefab = controlled.GetPrefabData().GetPrefabName();
PrintFormat("ERR CONVOY POPULATION: returned agent=%1 controlled=%2 prefab=%3 parent=%4 expectedGroup=%5",
agent, controlled, prefab, parent, vehicle.Group);
}
for (int i = 0; i < vehicle.Members.Count() && i < 19; i++)
{
IEntity actor = vehicle.Members[i];
AIControlComponent control;
AIAgent agent;
AIGroup parent;
if (actor) control = AIControlComponent.Cast(actor.FindComponent(AIControlComponent));
if (control) agent = control.GetControlAIAgent();
if (agent) parent = agent.GetParentGroup();
PrintFormat("ERR CONVOY POPULATION: intended member=%1 actor=%2 controlAgent=%3 parent=%4 expectedGroup=%5",
i, actor, agent, parent, vehicle.Group);
}
}
protected string MovementAction(AIActionBase action)
{
if (!action) return "none";
SCR_AIActionBase scripted = SCR_AIActionBase.Cast(action);
string detail = action.ToString();
if (scripted) detail = scripted.GetActionDebugInfo();
if (detail.Length() > 200) detail = detail.Substring(0, 200);
return string.Format("%1 state=%2 suspended=%3", detail, action.GetActionState(), action.GetActionIsSuspended());
}
protected void MovementDiagnostic(float now)
{
if (!m_Task || now < m_NextMovementDiagnostic || m_Origins.Count() != 6) return;
m_NextMovementDiagnostic = now + 30000;
for (int i = 0; i < m_Task.Vehicles.Count() && i < 6; i++)
{
ERR_ConvoyVehicle unit = m_Task.Vehicles[i];
if (!unit || !unit.Entity || !unit.Group) { PrintFormat("ERR CONVOY MOTION: vehicle=%1 missing original identity", i); continue; }
AIWaypoint current = unit.Group.GetCurrentWaypoint();
vector target, nativeTarget;
float targetDistance = -1;
bool nativeWithin;
if (unit.Waypoint)
{
target = unit.Waypoint.GetOrigin();
targetDistance = vector.DistanceXZ(unit.Entity.GetOrigin(), target);
nativeWithin = unit.Waypoint.IsWithinCompletionRadius(unit.Group);
}
if (current) nativeTarget = current.GetOrigin();
PrintFormat("ERR CONVOY MOTION: vehicle=%1 travel=%2 pos=%3 routeIndex=%4 released=%5 arrived=%6 groupOrigin=%7",
i, vector.DistanceXZ(m_Origins[i], unit.Entity.GetOrigin()), unit.Entity.GetOrigin(), unit.RouteIndex,
unit.Released, unit.Arrived, unit.Group.GetOrigin());
PrintFormat("ERR CONVOY MOTION: vehicle=%1 ownWaypoint=%2 currentWaypoint=%3 same=%4 target=%5 distance=%6 nativeWithin=%7 nativeTarget=%8",
i, unit.Waypoint != null, current != null, current == unit.Waypoint, target, targetDistance, nativeWithin, nativeTarget);
SCR_AIGroupUtilityComponent groupUtility = unit.Group.GetGroupUtilityComponent();
string groupAction = "no group utility", driverBehavior = "no driver utility";
if (groupUtility) groupAction = MovementAction(groupUtility.GetCurrentAction());
AIControlComponent control;
if (unit.Driver) control = AIControlComponent.Cast(unit.Driver.FindComponent(AIControlComponent));
AIAgent driverAgent;
if (control) driverAgent = control.GetControlAIAgent();
SCR_AIUtilityComponent driverUtility;
if (driverAgent) driverUtility = SCR_AIUtilityComponent.Cast(driverAgent.FindComponent(SCR_AIUtilityComponent));
if (driverUtility) driverBehavior = MovementAction(driverUtility.GetCurrentBehavior());
PrintFormat("ERR CONVOY MOTION: vehicle=%1 groupAction=%2 driverBehavior=%3", i, groupAction, driverBehavior);
}
}
protected bool Population(ERR_HQ hq)
{
if (!Check(m_Task.Vehicles.Count() == 6, "six original vehicles remain tracked")) return false;
array<IEntity> vehicles = {}, crew = {};
array<SCR_AIGroup> groups = {};
array<BaseCompartmentSlot> slots = {};
for (int i = 0; i < 6; i++)
{
ERR_ConvoyVehicle vehicle = m_Task.Vehicles[i];
if (!Check(vehicle.Entity && vehicle.Entity == m_OriginalVehicles[i] && ERR_Actors.Alive(vehicle.Entity)
&& !vehicles.Contains(vehicle.Entity) && vehicle.Group && !groups.Contains(vehicle.Group),
"vehicle and group identity " + i.ToString())) return false;
vehicles.Insert(vehicle.Entity); groups.Insert(vehicle.Group);
int expected = ERR_ConvoyPool.CrewCount(i);
array<AIAgent> agents = {}; vehicle.Group.GetAgents(agents);
PopulationDiagnostic(vehicle, agents, expected);
if (!Check(vehicle.Registered && vehicle.Members.Count() == expected && vehicle.Seats.Count() == expected
&& agents.Count() == expected, "native group membership matches exact crew plan " + i.ToString())) return false;
ERR_ForceRecord record = m_Mode.Forces().FindGroup(vehicle.Group);
if (!Check(record && record.Kind == ERR_ForceKind.CONVOY && record.Physical && !record.Eliminated
&& record.Strength == expected && record.InitialStrength == expected
&& record.Id == m_Task.Receipt.Records[i], "Core ledger owns physical convoy group " + i.ToString())) return false;
for (int seatIndex = 0; seatIndex < expected; seatIndex++)
{
IEntity actor = vehicle.Members[seatIndex];
BaseCompartmentSlot seat = vehicle.Seats[seatIndex];
if (!Check(actor && ERR_Actors.CanFight(actor) && !crew.Contains(actor)
&& ERR_Actors.Group(actor) == vehicle.Group && seat && !slots.Contains(seat) && seat.GetOccupant() == actor
&& ERR_ConvoyRules.PartOf(CompartmentAccessComponent.GetVehicleIn(actor), vehicle.Entity),
"original crew occupies intended native compartment " + crew.Count().ToString())) return false;
crew.Insert(actor); slots.Insert(seat);
bool nativeMember;
foreach (AIAgent agent : agents) if (agent && agent.GetControlledEntity() == actor) nativeMember = true;
if (!Check(nativeMember, "seated actor is a real native group member")) return false;
}
if (!Check(vehicle.Driver == vehicle.Members[0]
&& vehicle.Seats[0].GetType() == ECompartmentType.PILOT, "actual driver seat " + i.ToString())) return false;
}
return Check(crew.Count() == 19 && hq.ConvoyPool().CommittedBodies() <= 60
&& m_Task.Receipt.OutstandingBodies == 0 && m_Task.Receipt.OutstandingGroups == 0,
"nineteen unique crew admitted once within shared sixty-body cap");
}
protected int Cargo(float now)
{
if (!m_Task.CargoIssued) return 0;
if (m_Task.Cargo.Count() != 56) { Check(false, "cargo request count differs from56"); return -1; }
int rifles, magazines;
foreach (ERR_ConvoyCargoCallback operation : m_Task.Cargo)
{
if (!operation || !operation.Finished)
{
if (now - m_ReadyAt > 60000) { Check(false, "cargo callback deadline"); return -1; }
return 0;
}
if (!operation.Succeeded) { Check(false, "native cargo insertion failed"); return -1; }
if (operation.Prefab == ERR_ConvoyResources.Rifle()) rifles++;
if (operation.Prefab == ERR_ConvoyResources.Magazine()) magazines++;
}
if (!Check(rifles == 8 && magazines == 48, "cargo requests are eight rifles and forty-eight magazines")) return -1;
InventoryStorageManagerComponent inventory = TruckInventory();
if (!Check(inventory != null, "real ammunition truck inventory exists")) return -1;
array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
rifles = 0; magazines = 0;
foreach (IEntity item : items)
{
if (!item || m_CargoBefore.Contains(item) || !item.GetPrefabData()) continue;
ResourceName prefab = item.GetPrefabData().GetPrefabName();
if (prefab == ERR_ConvoyResources.Rifle()) rifles++;
if (prefab == ERR_ConvoyResources.Magazine()) magazines++;
}
if (!Check(rifles == 8 && magazines >= 48,
"eight new physical rifles and at least forty-eight magazines found in truck")) return -1;
return 1;
}
static bool MovementComplete(float leaderMetres, float minimumMetres)
{
return ERR_ForceRules.Finite(leaderMetres) && ERR_ForceRules.Finite(minimumMetres)
&& leaderMetres >= 100 && minimumMetres >= 20;
}
int Tick(ERR_HQ hq, float now)
{
if (!Enabled() || !hq || !m_Mode || m_Mode != ERR_GameMode.Get() || m_Failed) return -1;
if (m_Deadline == 0) m_Deadline = now + 480000;
if (now >= m_Deadline) { Check(false, "native fixture deadline"); return -1; }
if (m_Step == 0)
{
// Existing finite support must finish ordinary readiness before measuring the ledger baseline.
array<ref ERR_MortarBattery> batteries = {}; hq.Mortars().Batteries(batteries);
foreach (ERR_MortarBattery battery : batteries)
{
if (!battery || battery.Stopped()) { Check(false, "baseline mortar readiness failed"); return -1; }
if (!battery.StartupActivated) return 0;
}
// Canonical authored supply-site seed; a missing suitable real road is a test failure.
ERR_SiteRuntime site = m_Mode.Sites().Find("everon-supply-1");
if (!Check(site && site.Definition, "authored supply-site road survey seed exists")) return -1;
vector seed = site.Definition.Position;
m_InitialLedger = m_Mode.Forces().Count();
Print("ERR CONVOY NATIVE: road survey seed=" + seed.ToString());
if (!hq.PrepareConvoy(seed))
{
ERR_NativeConvoyRoadSurvey survey = new ERR_NativeConvoyRoadSurvey(); survey.Run(seed);
Check(false, "production road survey refused seed; read-only diagnostics above"); return -1;
}
Check(true, "production road survey accepted six real road positions");
if (!Check(hq.StartConvoy(), "canonical HQ dispatch accepted once")) return -1;
m_Task = hq.ConvoyTask();
if (!Check(m_Task && m_Task.Receipt && m_Task.Receipt.Consumed && m_Task.Vehicles.Count() == 6,
"canonical receipt owns six attempted physical vehicles")) return -1;
foreach (ERR_ConvoyVehicle vehicle : m_Task.Vehicles)
{
if (!Check(vehicle.Entity != null, "original physical vehicle created")) return -1;
m_OriginalVehicles.Insert(vehicle.Entity); m_Origins.Insert(vehicle.Entity.GetOrigin());
}
ERR_Inventory.Items(TruckInventory(), m_CargoBefore);
if (!Check(!hq.StartConvoy() && hq.ConvoyTask() == m_Task && hq.Convoys().Count() == 1,
"duplicate canonical dispatch creates no second native task")) return -1;
if (!Check(!hq.ConvoyPool().Reserve("native-over-cap"), "second convoy reservation rejected by finite cap")) return -1;
m_Step = 1;
}
bool completed = m_Task && m_Task.Vehicles.Count() == 6;
if (m_Task) foreach (ERR_ConvoyVehicle candidate : m_Task.Vehicles)
if (!candidate.Arrived) completed = false;
if (!m_Task || (m_Task.Stopped && !completed))
{
string reason = "missing task";
if (m_Task) reason = m_Task.Reason;
Check(false, "production convoy stopped before proof: " + reason); return -1;
}
if (m_Step == 1)
{
if (!m_Task.Ready) return 0;
m_ReadyAt = now;
if (!Population(hq)) return -1;
ERR_ConvoyPlacement occupied = new ERR_ConvoyPlacement();
Vehicle lead = m_Task.Vehicles[0].Entity;
bool empty = occupied.Clear(ERR_Actors.Ground(lead.GetOrigin()), lead.GetAngles()[0]);
float fraction = occupied.LastTraceFraction();
Print("ERR CONVOY NATIVE: existing lead vehicle blocker control; " + occupied.Diagnostic());
if (!Check(!empty && ERR_ForceRules.Finite(fraction) && fraction >= 0 && fraction < 1
&& occupied.Diagnostic().IndexOf("native filled volume collision") >= 0,
"native filled volume detects the actual lead vehicle as a positive blocker")) return -1;
if (!Check(m_Mode.Forces().Count() == m_InitialLedger + 6,
"exactly six new Core records after native readiness")) return -1;
m_Step = 2;
}
if (m_Step == 2)
{
int cargo = Cargo(now);
if (cargo <= 0) return cargo;
m_Step = 3;
}
float minimum = 1000000;
for (int i = 0; i < 6; i++)
{
ERR_ConvoyVehicle vehicle = m_Task.Vehicles[i];
if (!vehicle.Entity || (vehicle.Released && !vehicle.Arrived)) { Check(false, "vehicle released before road movement proof"); return -1; }
minimum = Math.Min(minimum, vector.DistanceXZ(m_Origins[i], vehicle.Entity.GetOrigin()));
}
float leader = vector.DistanceXZ(m_Origins[0], m_Task.Vehicles[0].Entity.GetOrigin());
if (now >= m_NextLog)
{
m_NextLog = now + 10000;
PrintFormat("ERR CONVOY NATIVE: leader travel=%1m minimum vehicle travel=%2m; age=%3s",
leader, minimum, (now - m_ReadyAt) / 1000);
}
MovementDiagnostic(now);
if (!MovementComplete(leader, minimum)) return 0;
if (!Check(m_Task.Route && m_Task.Route.Count() >= 2 && !m_Task.Route.Looped(),
"driving uses finite road-polyline route")) return -1;
if (!Population(hq)) return -1;
if (!Check(!hq.StartConvoy() && hq.Convoys().Count() == 1 && hq.ConvoyTask() == m_Task
&& m_Mode.Forces().Count() == m_InitialLedger + 6 && m_Task.Cargo.Count() == 56,
"later repeated dispatch preserves exact task, force and cargo counts")) return -1;
Check(true, "all six native vehicles drove at least 20m and leader at least 100m without fixture movement");
return 1;
}
}
#endif
@@ -0,0 +1,291 @@
#ifdef WORKBENCH
// Explicit fixture payloads, physical radio delivery, production HQ intake.
// This does not certify visual detection or an actual ground sweep completing.
modded class ERR_HQ
{
int ERR_MemoryFixtureRegisteredForces()
{
if (!ERR_NativeHQMemoryProbe.Enabled() || !m_Mode || !m_Mode.Forces()) return -1;
int registered;
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.ReservedForSupport || !unit.Group) continue;
ERR_ForceRecord record = m_Mode.Forces().FindGroup(unit.Group);
if (!record || record.Group != unit.Group || !record.Physical || record.Eliminated) return -1;
registered++;
}
if (m_Mode.Forces().Count() < registered) return -1;
return registered;
}
protected bool ERR_MemoryFixtureHealthy(ERR_HQRoute route)
{
if (!route || route.Nodes.IsEmpty()) return false;
for (int i = 0; i < route.Nodes.Count(); i++)
if (!route.Nodes[i] || !route.Nodes[i].Valid(i == route.Nodes.Count() - 1)) return false;
return true;
}
ERR_HQRoute ERR_MemoryFixtureQueue(ERR_HQReport report)
{
if (!ERR_NativeHQMemoryProbe.Enabled()) return null;
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.ReservedForSupport || !unit.Radio || unit.Uplink || unit.PendingReport || unit.PendingSweep) continue;
if (unit.PendingSupplyStatus || unit.PendingStatus) continue;
ERR_HQRoute route = m_Network.Route(unit.Radio);
if (!ERR_MemoryFixtureHealthy(route)) continue;
report.Source = unit.Group;
route.MessageId = report.MessageId;
route.Payload = "FIXTURE synthetic observed position; " + report.Description(report.ObservedAt);
unit.PendingReport = report.Snapshot(); unit.Uplink = route;
return route;
}
return null;
}
ERR_HQRoute ERR_MemoryFixtureSweep(ERR_HQSearchReport report)
{
if (!ERR_NativeHQMemoryProbe.Enabled()) return null;
foreach (ERR_HQUnit unit : m_Units)
{
if (unit.ReservedForSupport || !unit.Radio || unit.Uplink || unit.PendingReport || unit.PendingSweep) continue;
if (unit.PendingSupplyStatus || unit.PendingStatus) continue;
ERR_HQRoute route = m_Network.Route(unit.Radio);
if (!ERR_MemoryFixtureHealthy(route)) continue;
report.SourceId = unit.Id;
route.MessageId = report.MessageId;
route.Payload = "FIXTURE synthetic completed sweep; real uplink required";
unit.PendingSweep = report; unit.Uplink = route;
return route;
}
return null;
}
void ERR_MemoryFixtureReplaySweep(ERR_HQSearchReport report, float now)
{
if (ERR_NativeHQMemoryProbe.Enabled()) AcceptSweep(report, now);
}
override void Stop()
{
super.Stop();
if (!ERR_NativeHQMemoryProbe.Enabled()) return;
if (m_Memory.Count() != 0)
Print("ERR SMOKE FAIL: HQ memory stop retained beliefs", LogLevel.ERROR);
else Print("ERR SMOKE PASS: HQ memory actual command stop clears all belief history");
}
}
class ERR_NativeHQMemoryProbe
{
protected ERR_GameMode m_Mode;
protected ref ERR_HQRoute m_Route;
protected ref ERR_HQReport m_Report;
protected ref ERR_HQSearchReport m_Sweep;
protected int m_Step;
protected int m_BeliefId;
protected int m_Revision;
protected float m_FirstObserved;
protected float m_SecondObserved;
protected vector m_FirstPosition;
protected float m_Deadline;
protected bool m_Failed;
protected bool m_ValueChecked;
protected int m_RouteRetries;
static bool Enabled()
{
string enabled, outcome;
return Replication.IsServer() && System.GetCLIParam("errSmoke", enabled) && enabled == "1"
&& System.GetCLIParam("errSmokeOutcome", outcome) && outcome == "hq-memory";
}
void ERR_NativeHQMemoryProbe(ERR_GameMode mode) { m_Mode = mode; }
protected bool Check(bool condition, string description)
{
if (condition) { Print("ERR SMOKE PASS: HQ memory " + description); return true; }
m_Failed = true; Print("ERR SMOKE FAIL: HQ memory " + description, LogLevel.ERROR); return false;
}
protected float Unaged(ERR_HQBelief belief)
{
if (!belief) return -1;
float decay = ERR_HQMemoryRules.Confidence((belief.EvaluatedAt - belief.ObservedAt) / 1000);
if (decay <= 0) return -1;
return belief.Confidence / decay;
}
protected ERR_HQReport Payload(ERR_HQ hq, float now, vector position)
{
ERR_HQReport report = new ERR_HQReport();
report.MessageId = hq.Journal().Message(); report.Target = m_Mode;
report.ObservedAt = now; report.Position = position; report.TravelMode = "on foot";
return report;
}
protected bool LocalPolicies()
{
ERR_ForceLedger ledger = new ERR_ForceLedger();
ERR_ForceRecord force = ledger.Register("memory-value-fixture", ERR_ForceKind.PATROL, "100 0 100", 6);
if (!Check(force && ledger.Count() == 1 && !force.Group && !force.Physical,
"detached native Core ledger registers one arithmetic fixture without spawning")) return false;
if (!Check(ledger.Eliminate(force.Id, 1000), "detached native ledger records elimination")) return false;
ERR_ForceRecord duplicate = ledger.Register("memory-value-fixture", ERR_ForceKind.PATROL, "100 0 100", 6);
if (!Check(duplicate == force && ledger.Count() == 1 && force.Strength == 0 && force.Eliminated
&& !force.Group && !force.Physical, "eliminated source re-registration cannot restore strength or spawn"))
return false;
ERR_HQMemory memory = new ERR_HQMemory();
ERR_HQReport first = new ERR_HQReport();
first.Target = m_Mode; first.MessageId = 1; first.ObservedAt = 0;
first.Position = "100 7 100"; first.TravelMode = "on foot";
if (!Check(memory.Ingest(first, 0), "injected value fixture begins with a detached report")) return false;
first.Position = "999 7 999";
ERR_HQBelief belief = memory.Get(m_Mode);
if (!Check(belief && belief.Position == "100 7 100", "stored snapshot ignores later input mutation")) return false;
ERR_HQReport next = first.Snapshot();
next.MessageId = 2; next.ObservedAt = 10000; next.Position = "160 7 100";
if (!Check(memory.Ingest(next, 12000), "newer delivered-value fixture advances trajectory")) return false;
belief = memory.Get(m_Mode);
if (!Check(belief.HasVelocity && Math.AbsFloat(belief.Speed - 6) < 0.01,
"native vector arithmetic infers six metres per second from snapshots")) return false;
memory.Tick(610000); belief = memory.Get(m_Mode);
if (!Check(belief && Math.AbsFloat(belief.Confidence - 0.5) < 0.001 && belief.Radius > 700,
"ten-minute value-clock advance retains a weaker wider belief")) return false;
if (!Check(belief.PredictionSeconds == 30 && vector.DistanceXZ(belief.Position, belief.PredictedPosition) <= 300,
"old trajectory prediction remains capped in time and distance")) return false;
int id = belief.BeliefId;
if (!Check(memory.NegativeSearch(id, belief.BeliefRevision, 610000)
&& !memory.NegativeSearch(id, belief.BeliefRevision, 610000), "negative revision is idempotent")) return false;
memory.Clear();
if (!Check(memory.Count() == 0 && !memory.GetById(id), "clear removes detached value history")) return false;
return true;
}
protected bool RemoveRadios(IEntity carrier)
{
InventoryStorageManagerComponent inventory;
if (carrier)
inventory = InventoryStorageManagerComponent.Cast(carrier.FindComponent(InventoryStorageManagerComponent));
if (!inventory) return false;
array<IEntity> items = {}; inventory.GetItems(items);
int removed;
foreach (IEntity item : items)
{
if (!item || !item.FindComponent(BaseRadioComponent)) continue;
SCR_EntityHelper.DeleteEntityAndChildren(item); removed++;
}
return removed > 0;
}
int Tick(ERR_HQ hq, float now)
{
if (!Enabled() || !hq || !m_Mode || m_Failed) return -1;
if (m_Deadline == 0) m_Deadline = now + 120000;
if (now > m_Deadline) { Check(false, "fixture deadline"); return -1; }
if (m_Step == 0)
{
if (!hq.ERR_ProbeSquadsReady()) return 0;
if (!m_ValueChecked)
{
if (!Check(hq.ERR_MemoryFixtureRegisteredForces() == 6,
"actual six site groups are registered once in the Core force ledger")) return -1;
if (!LocalPolicies()) return -1;
m_ValueChecked = true;
}
m_FirstPosition = m_Mode.PrisonPosition() + "300 0 300";
m_Report = Payload(hq, now, m_FirstPosition);
m_Route = hq.ERR_MemoryFixtureQueue(m_Report);
if (!m_Route) return 0;
if (!Check(!hq.Memory().Get(m_Mode) && m_Route.Advance(now, hq.Journal()) == 0,
"queued synthetic sighting has no belief while actual transmitter starts")) return -1;
if (!Check(RemoveRadios(m_Route.Nodes[0].Carrier), "fixture removes actual transmitting equipment mid-uplink"))
return -1;
m_Step = 1; return 0;
}
if (m_Step == 1)
{
if (hq.Memory().Get(m_Mode))
{ Check(false, "interrupted uplink created a belief"); return -1; }
if (!m_Route.Failed) return 0;
Print("ERR SMOKE PASS: HQ memory physical uplink loss prevents production Accept");
m_Step = 2;
}
// A real carrier can fail after selection. Retry with a fresh immutable payload;
// a fixture may not hang waiting for a message that production correctly dropped.
if (m_Route && m_Route.Failed && m_Step >= 3)
{
m_RouteRetries++;
if (m_RouteRetries > 5) { Check(false, "positive-route retry bound"); return -1; }
if (m_Step == 3) m_Step = 2;
else if (m_Step == 5) m_Step = 4;
else if (m_Step == 7) m_Step = 6;
else if (m_Step == 9) m_Step = 8;
else if (m_Step == 10) m_Step = 9;
m_Route = null;
}
if (m_Step == 2 || m_Step == 4 || m_Step == 8)
{
if (m_Step == 4 && now - m_FirstObserved < 4000) return 0;
vector position = m_FirstPosition;
if (m_Step >= 4) position += "24 0 0";
m_Report = Payload(hq, now, position);
m_Route = hq.ERR_MemoryFixtureQueue(m_Report);
if (!m_Route) return 0;
if (m_Step == 2) m_FirstObserved = now;
if (m_Step == 4) m_SecondObserved = now;
m_Step++; return 0;
}
ERR_HQBelief current = hq.Memory().Get(m_Mode);
if (m_Step == 3)
{
if (!current || current.MessageId != m_Report.MessageId) return 0;
if (!Check(current.Position == m_Report.Position && current.SampleCount == 1,
"actual uplink delivery reaches production intake exactly once")) return -1;
m_BeliefId = current.BeliefId; m_Step = 4; return 0;
}
if (m_Step == 5)
{
if (!current || current.MessageId != m_Report.MessageId) return 0;
if (!Check(current.BeliefId == m_BeliefId && current.SampleCount == 2 && current.HasVelocity,
"second physical delivery extends one stable credible trajectory")) return -1;
m_Revision = current.BeliefRevision;
m_Step = 6;
}
if (m_Step == 6)
{
m_Sweep = new ERR_HQSearchReport();
m_Sweep.MessageId = hq.Journal().Message(); m_Sweep.BeliefId = m_BeliefId;
m_Sweep.BeliefRevision = m_Revision; m_Sweep.ObservedAt = now; m_Sweep.Position = current.Position;
m_Sweep.SweepCompleted = true;
m_Route = hq.ERR_MemoryFixtureSweep(m_Sweep);
if (!m_Route) return 0;
if (!Check(Unaged(hq.Memory().GetById(m_BeliefId)) > 0.99,
"synthetic completed sweep is not knowledge before radio delivery")) return -1;
m_Step = 7; return 0;
}
if (m_Step == 7)
{
if (!current || Unaged(current) > 0.99) return 0;
if (!Check(Math.AbsFloat(Unaged(current) - 0.65) < 0.001 && current.BeliefRevision == m_Revision
&& current.ObservedAt == m_SecondObserved && current.SampleCount == 2,
"delivered negative sweep lowers confidence without inventing a sighting")) return -1;
hq.ERR_MemoryFixtureReplaySweep(m_Sweep, now);
if (!Check(Math.AbsFloat(Unaged(hq.Memory().Get(m_Mode)) - 0.65) < 0.001,
"replayed completed-sweep payload cannot multiply confidence loss")) return -1;
m_Step = 8; return 0;
}
if (m_Step == 9)
{
if (!current || current.MessageId != m_Report.MessageId) return 0;
if (!Check(current.BeliefRevision > m_Revision && Unaged(current) > 0.99,
"fresh delivered sighting supersedes prior negative evidence")) return -1;
ERR_HQSearchReport stale = new ERR_HQSearchReport();
stale.MessageId = hq.Journal().Message(); stale.BeliefId = m_BeliefId;
stale.BeliefRevision = m_Revision; stale.ObservedAt = now; stale.Position = m_FirstPosition;
stale.SweepCompleted = true;
m_Route = hq.ERR_MemoryFixtureSweep(stale);
if (!m_Route) return 0;
m_Step = 10; return 0;
}
if (m_Step == 10)
{
if (m_Route.Failed) { Check(false, "old-revision fixture sweep route failed"); return -1; }
if (m_Route.Cursor < m_Route.Nodes.Count() || m_Route.Sending) return 0;
if (!Check(current && current.BeliefRevision > m_Revision && Unaged(current) > 0.99,
"delivered old-revision sweep cannot weaken a newer sighting")) return -1;
return 1;
}
return 0;
}
}
#endif
+47 -1
View File
@@ -16,6 +16,10 @@ modded class ERR_GameMode
protected bool m_ERRTestPlayerDeath;
protected bool m_ERRTestRadioNetwork;
protected bool m_ERRTestHQResponse;
protected bool m_ERRTestHQMemory;
protected bool m_ERRTestConvoy;
protected ref ERR_NativeConvoyProbe m_ERRConvoyProbe;
protected ref ERR_NativeHQMemoryProbe m_ERRHQMemoryProbe;
protected bool m_ERRTestMortar;
protected bool m_ERRTestMortarFire;
protected bool m_ERRTestMapOwnership;
@@ -54,6 +58,8 @@ modded class ERR_GameMode
m_ERRTestLostHelicopter = System.GetCLIParam("errSmokeOutcome", outcome) && outcome == "lost-helicopter";
m_ERRTestRadioNetwork = outcome == "radio-network";
m_ERRTestHQResponse = outcome == "hq-response";
m_ERRTestHQMemory = outcome == "hq-memory";
m_ERRTestConvoy = outcome == "convoy";
m_ERRTestMortar = outcome == "mortar-inventory";
m_ERRTestMapOwnership = outcome == "map-ownership";
m_ERRTestAircraftField = outcome == "aircraft-field";
@@ -66,8 +72,10 @@ modded class ERR_GameMode
m_ERRTestMortarSalvo = outcome == "mortar-salvo" || outcome == "mortar-refresh";
m_ERRTestMortarTransfer = outcome == "mortar-transfer";
m_ERRTestPatrolHQ = outcome == "patrol-hq";
m_ERRTestPlayerDeath = outcome == "player-death" || m_ERRTestRadioNetwork || m_ERRTestHQResponse || m_ERRTestMortar;
m_ERRTestPlayerDeath = outcome == "player-death" || m_ERRTestRadioNetwork || m_ERRTestHQResponse || m_ERRTestMortar || m_ERRTestHQMemory || m_ERRTestConvoy;
m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 150000;
if (m_ERRTestConvoy) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 540000;
if (m_ERRTestHQMemory) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 240000;
if (m_ERRTestAircraftControl || m_ERRTestAircraftRoute || m_ERRTestAircraftField) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 330000;
if (m_ERRTestMortarCourier) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 450000;
if (m_ERRTestMortarTransfer) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 330000;
@@ -499,6 +507,20 @@ modded class ERR_GameMode
m_ERRSmokeStep = 110;
return;
}
if (m_ERRTestConvoy)
{
DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
m_ERRConvoyProbe = new ERR_NativeConvoyProbe(this);
m_ERRSmokeStep = 106;
return;
}
if (m_ERRTestHQMemory)
{
DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false);
m_ERRHQMemoryProbe = new ERR_NativeHQMemoryProbe(this);
m_ERRSmokeStep = 105;
return;
}
if (m_ERRTestRadioNetwork)
{
m_ERRRadioProbe = new ERR_NativeRadioProbe();
@@ -672,6 +694,30 @@ modded class ERR_GameMode
damage.Kill(Instigator.CreateInstigator(m_ERRSmokePlayer));
m_ERRSmokeWait = now + 4000;
}
else if (m_ERRSmokeStep == 106)
{
int result = m_ERRConvoyProbe.Tick(ERR_HQ.Cast(Command()), now);
if (result == 0) return;
if (!ERR_Check(result == 1, "native six-vehicle convoy readiness, cargo and road movement")) return;
m_ERRSmokeStep = 9;
SCR_CharacterDamageManagerComponent damage;
damage = SCR_CharacterDamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(SCR_CharacterDamageManagerComponent));
damage.EnableDamageHandling(true);
damage.Kill(Instigator.CreateInstigator(m_ERRSmokePlayer));
m_ERRSmokeWait = now + 4000;
}
else if (m_ERRSmokeStep == 105)
{
int result = m_ERRHQMemoryProbe.Tick(ERR_HQ.Cast(Command()), now);
if (result == 0) return;
if (!ERR_Check(result == 1, "native HQ memory delivery and search lineage")) return;
m_ERRSmokeStep = 9;
SCR_CharacterDamageManagerComponent damage;
damage = SCR_CharacterDamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(SCR_CharacterDamageManagerComponent));
damage.EnableDamageHandling(true);
damage.Kill(Instigator.CreateInstigator(m_ERRSmokePlayer));
m_ERRSmokeWait = now + 4000;
}
else if (m_ERRSmokeStep == 100)
{
int result = m_ERRRadioProbe.Tick(ERR_HQ.Cast(Command()), now);