#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 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 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 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 m_Origins = {}; protected ref array m_OriginalVehicles = {}; protected ref array 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 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 vehicles = {}, crew = {}; array groups = {}; array 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 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 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 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