Files
EscapistsReintroduced/docs/evidence/crash-start-2026-10-03/proposals/route/fix.patch
T
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

233 lines
36 KiB
Diff

--- a/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c
+++ b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c
@@ -29,6 +29,8 @@
return camps > 0 && seen.Count() == camps * 2;
}
+ protected bool m_ERRTestCrashStart;
+ protected bool m_ERRCrashEnteredPrison;
protected bool m_ERRTestCrashGeometry;
protected bool m_ERRTestPatrolHQ;
protected ref ERR_NativePatrolProbe m_ERRHQPatrolMovement;
@@ -115,7 +117,8 @@
if (SCR_Global.IsEditMode() || !Replication.IsServer() || !System.GetCLIParam("errSmoke", enabled) || enabled != "1") return;
string outcome;
m_ERRTestLostHelicopter = System.GetCLIParam("errSmokeOutcome", outcome) && outcome == "lost-helicopter";
- m_ERRTestEscapeRoute = outcome == "escape-route" || outcome == "normal-escape-route";
+ m_ERRTestCrashStart = outcome == "crash-start";
+ m_ERRTestEscapeRoute = outcome == "escape-route" || outcome == "normal-escape-route" || m_ERRTestCrashStart;
m_ERRTestRadioNetwork = outcome == "radio-network";
m_ERRTestHQResponse = outcome == "hq-response";
m_ERRTestHQAwareness = outcome == "hq-awareness";
@@ -323,6 +326,7 @@
}
protected void ERR_SmokePhase(ERR_Phase previous, ERR_Phase current)
{
+ if (m_ERRTestCrashStart && current == ERR_Phase.PRISON) m_ERRCrashEnteredPrison = true;
if (m_ERRSmokeDone || !ERR_MissionRules.Terminal(current)) return;
if (m_ERRTestCrashGeometry)
{
@@ -482,7 +486,7 @@
else if (!ERR_Check(current == ERR_Phase.VICTORY && m_ERRSmokeStep == 7, "scripted escape reaches victory after physical vehicle occupancy")) return;
m_ERRSmokeDone = true;
GetGame().GetCallqueue().Remove(ERR_SmokeTick);
- PrintFormat("ERR SMOKE COMPLETE: terminal=%1 lostHelicopterCase=%2 playerDeathCase=%3", current, m_ERRTestLostHelicopter, m_ERRTestPlayerDeath);
+ PrintFormat("ERR SMOKE COMPLETE: terminal=%1 lostHelicopterCase=%2 playerDeathCase=%3 crashStartCase=%4", current, m_ERRTestLostHelicopter, m_ERRTestPlayerDeath, m_ERRTestCrashStart);
GetGame().GetCallqueue().CallLater(ERR_EndScreenshot, 4000);
}
protected bool ERR_CheckRoster()
@@ -671,7 +675,9 @@
}
if (m_ERRSmokeStep == 0)
{
- if (m_SpawnPreload && Phase() == ERR_Phase.PRISON && !m_ERRSpawnPreloadUIObserved)
+ ERR_Phase initialPhase = ERR_Phase.PRISON;
+ if (m_ERRTestCrashStart) initialPhase = ERR_Phase.RADIO_SEARCH;
+ if (m_SpawnPreload && Phase() == initialPhase && !m_ERRSpawnPreloadUIObserved)
{
SCR_RespawnSystemComponent respawn = SCR_RespawnSystemComponent.GetInstance();
if (!ERR_Check(respawn && respawn.ERR_ProbePreparationVisible(this, false), "native spawn preload retains preparation text after server sites are ready")) return;
@@ -679,7 +685,7 @@
}
array<IEntity> players = {};
ERR_Actors.Players(players, true);
- if (players.Count() != 1 || Phase() != ERR_Phase.PRISON) return;
+ if (players.Count() != 1 || Phase() != initialPhase) return;
if (!ERR_Check(CanStartSpawnPreload() && m_ERRSpawnPreloadRequested && !m_SpawnPreload, "prisoner admitted only after enabled native spawn preload finishes")) return;
m_ERRSmokePlayer = players[0];
if (!ERR_CheckRoster() || !ERR_NativeContractsProbe.Run(this, m_ERRSmokePlayer) || !ERR_CheckCompanionCommands()) return;
@@ -898,32 +904,40 @@
PrintFormat("ERR NORMAL ROUTE: Southern transport ready at %1", clueSite.Transport.GetOrigin());
}
}
- ERR_UnlockPrisonAction lock;
- foreach (IEntity tracked : m_OwnedEntities)
- {
- if (tracked) lock = ERR_FindLock(tracked);
- if (lock) break;
- }
- if (!ERR_Check(lock != null, "authored gate exposes lock action")) return;
- if (!ERR_Check(ERR_PrisonAIState(false), "physical enemies stay inactive until prison lockpick")) return;
- ERR_MovePlayer(lock.GetOwner().GetOrigin() + "1 0 1");
- vector gateLow, gateHigh;
- lock.GetOwner().GetWorldBounds(gateLow, gateHigh);
- PrintFormat("ERR GEOMETRY: gate low=%1 high=%2", gateLow, gateHigh);
- IEntity wall = lock.GetOwner().GetParent().GetParent().GetChildren();
- while (wall)
- {
- vector wallLow, wallHigh;
- wall.GetWorldBounds(wallLow, wallHigh);
- PrintFormat("ERR GEOMETRY: child origin=%1 low=%2 high=%3", wall.GetOrigin(), wallLow, wallHigh);
- wall = wall.GetSibling();
- }
- GetGame().GetCallqueue().CallLater(ERR_PrisonScreenshot, 2000);
- if (!ERR_Check(lock.CanBePerformedScript(m_ERRSmokePlayer), "lock permits prisoner")) return;
- m_ERRGate = BaseDoorComponent.Cast(lock.GetOwner().FindComponent(BaseDoorComponent));
- lock.PerformAction(lock.GetOwner(), m_ERRSmokePlayer);
- if (!ERR_Check(Phase() == ERR_Phase.RADIO_SEARCH, "lock action advances mission")) return;
- if (!ERR_Check(ERR_PrisonAIState(true), "lockpick reactivates the existing physical enemies")) return;
+ if (m_ERRTestCrashStart)
+ {
+ if (!ERR_Check(!m_ERRCrashEnteredPrison && ERR_PrisonAIState(true), "crash start never enters prison and existing enemies are active")) return;
+ if (!ERR_NativeCrashStartProbe.Run(this, m_ERRSmokePlayer)) { m_ERRSmokeDone = true; GetGame().GetCallqueue().Remove(ERR_SmokeTick); return; }
+ }
+ else
+ {
+ ERR_UnlockPrisonAction lock;
+ foreach (IEntity tracked : m_OwnedEntities)
+ {
+ if (tracked) lock = ERR_FindLock(tracked);
+ if (lock) break;
+ }
+ if (!ERR_Check(lock != null, "authored gate exposes lock action")) return;
+ if (!ERR_Check(ERR_PrisonAIState(false), "physical enemies stay inactive until prison lockpick")) return;
+ ERR_MovePlayer(lock.GetOwner().GetOrigin() + "1 0 1");
+ vector gateLow, gateHigh;
+ lock.GetOwner().GetWorldBounds(gateLow, gateHigh);
+ PrintFormat("ERR GEOMETRY: gate low=%1 high=%2", gateLow, gateHigh);
+ IEntity wall = lock.GetOwner().GetParent().GetParent().GetChildren();
+ while (wall)
+ {
+ vector wallLow, wallHigh;
+ wall.GetWorldBounds(wallLow, wallHigh);
+ PrintFormat("ERR GEOMETRY: child origin=%1 low=%2 high=%3", wall.GetOrigin(), wallLow, wallHigh);
+ wall = wall.GetSibling();
+ }
+ GetGame().GetCallqueue().CallLater(ERR_PrisonScreenshot, 2000);
+ if (!ERR_Check(lock.CanBePerformedScript(m_ERRSmokePlayer), "lock permits prisoner")) return;
+ m_ERRGate = BaseDoorComponent.Cast(lock.GetOwner().FindComponent(BaseDoorComponent));
+ lock.PerformAction(lock.GetOwner(), m_ERRSmokePlayer);
+ if (!ERR_Check(Phase() == ERR_Phase.RADIO_SEARCH, "lock action advances mission")) return;
+ if (!ERR_Check(ERR_PrisonAIState(true), "lockpick reactivates the existing physical enemies")) return;
+ }
array<IEntity> cacheStock = {};
ERR_Inventory.Items(InventoryStorageManagerComponent.Cast(Sites().Find("everon-supply-1").Container.FindComponent(InventoryStorageManagerComponent)), cacheStock);
foreach (IEntity tracked : cacheStock)
@@ -937,7 +951,7 @@
}
else if (m_ERRSmokeStep == 1 || m_ERRSmokeStep == 2)
{
- if (m_ERRSmokeStep == 2 && !ERR_Check(m_ERRGate && m_ERRGate.IsOpen() && m_ERRGate.CanCharacterPass(0.6), "unlocked gate physically permits passage")) return;
+ if (m_ERRSmokeStep == 2 && !m_ERRTestCrashStart && !ERR_Check(m_ERRGate && m_ERRGate.IsOpen() && m_ERRGate.CanCharacterPass(0.6), "unlocked gate physically permits passage")) return;
ERR_MovePlayer(Sites().Find("everon-supply-1").Container.GetOrigin() + "0 0 2");
SCR_InventoryStorageManagerComponent inventory = SCR_InventoryStorageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(SCR_InventoryStorageManagerComponent));
InventoryStorageManagerComponent source = InventoryStorageManagerComponent.Cast(Sites().Find("everon-supply-1").Container.FindComponent(InventoryStorageManagerComponent));
--- a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c
+++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c
@@ -45,7 +45,9 @@
mode.Admin().Execute(mode, true, "settings", replies);
if (!Check(replies.Count() == ERR_Settings.Keys().Count(), "base settings listing available")) return false;
mode.Admin().Execute(mode, true, "status", replies);
- if (!Check(!replies.IsEmpty() && replies[0] == "Escape the prison", "base mission status available before companions")) return false;
+ string initialStatus = "Escape the prison";
+ if (mode.StartMode() == 1) initialStatus = "Locate the radio station";
+ if (!Check(!replies.IsEmpty() && replies[0] == initialStatus, "base mission status available before companions")) return false;
mode.Admin().Execute(mode, true, "mission radio set " + original.ToString(), replies);
if (!Check(mode.Settings().Get("radioDefenceSeconds") == original, "test setting restored")) return false;
return true;
--- /dev/null
+++ b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeCrashStartProbe.c
@@ -0,0 +1,52 @@
+#ifdef WORKBENCH
+// Read-only scene checks before the existing scripted escape route. No flight,
+// actor relocation, damage or inventory creation in this probe.
+class ERR_NativeCrashStartProbe
+{
+ protected static bool Check(bool condition, string message)
+ {
+ if (condition) { Print("ERR SMOKE PASS: crash start " + message); return true; }
+ Print("ERR SMOKE FAIL: crash start " + message, LogLevel.ERROR); return false;
+ }
+ static bool Run(ERR_GameMode mode, IEntity player)
+ {
+ if (!Check(mode && mode.StartMode() == 1 && mode.Phase() == ERR_Phase.RADIO_SEARCH, "frozen choice enters radio search directly")) return false;
+ ERR_PlayerLife life = mode.Players().CurrentActor(player);
+ CompartmentAccessComponent access = CompartmentAccessComponent.Cast(player.FindComponent(CompartmentAccessComponent));
+ if (!Check(life && life.UsedLife && access && !access.IsInCompartment() && ERR_Actors.CanFight(player), "ordinary canonical one-life survivor starts conscious on foot")) return false;
+ ERR_SiteRuntime site = mode.Sites().Find("everon-prison-1");
+ if (!Check(site && ERR_StartSetup.IsCrash(site.Definition) && site.Location && site.Location.GetOwner(), "single start slot owns a crash site")) return false;
+ IEntity root = site.Location.GetOwner();
+ if (!Check(mode.Sites().Owns(root) && root.FindComponent(RplComponent) && site.Definition.Label == "Crash site" && site.Definition.PlacementResolved && site.Definition.RandomClear, "generated replicated site has resolved terrain placement")) return false;
+ if (!Check(!site.Group && !site.Responders && !site.Definition.Guarded && site.Definition.Guards.IsEmpty() && site.Definition.ResponseCount == 0 && !site.PrisonPatrol && !root.GetChildren(), "start has no prison guards, gate or prison composition")) return false;
+ if (!Check(site.Props.Count() == 1 && site.Container && mode.Sites().Owns(site.Container), "one finite owned wreck and salvage bag")) return false;
+ IEntity wreck = site.Props[0];
+ if (!Check(wreck && mode.Sites().Owns(wreck) && wreck.GetPrefabData().GetPrefabName() == ERR_CrashSiteResources.WreckPrefab() && wreck.GetVObject() && wreck.FindComponent(RplComponent) && !wreck.GetChildren(), "exact replicated static wreck identity")) return false;
+ Physics physics = wreck.GetPhysics();
+ if (!Check(physics && !physics.IsDynamic(), "wreck remains static scenery")) return false;
+ vector low, high, expectedLow, expectedHigh;
+ wreck.GetBounds(low, high);
+ if (!ERR_CrashSiteResources.Bounds(expectedLow, expectedHigh)) return Check(false, "measured bounds available");
+ for (int axis = 0; axis < 3; axis++)
+ if (!Check(ERR_ForceRules.Finite(low[axis]) && ERR_ForceRules.Finite(high[axis]) && high[axis] > low[axis] && low[axis] >= expectedLow[axis] && high[axis] <= expectedHigh[axis], "placed model fits measured bounds axis " + axis.ToString())) return false;
+ vector offset, center; float halfSize, height;
+ if (!ERR_StartSetup.Geometry(offset, center, halfSize, height)) return false;
+ vector expectedPosition = ERR_Actors.Ground(site.Definition.Position + ERR_CampTerrain.Rotate(offset, site.Definition.Heading));
+ expectedPosition[1] = expectedPosition[1] + offset[1];
+ if (!Check(vector.Distance(wreck.GetOrigin(), expectedPosition) < 0.05 && low[0] + offset[0] >= 12, "measured placement keeps wreck outside every start slot")) return false;
+ InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(site.Container.FindComponent(InventoryStorageManagerComponent));
+ array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
+ if (!Check(inventory && items.Count() > 0 && items.Count() <= 128, "finite starting stock is present")) return false;
+ foreach (ERR_SiteStock stock : site.Definition.Stock)
+ {
+ int count;
+ foreach (IEntity item : items)
+ if (item && item.GetPrefabData() && item.GetPrefabData().GetPrefabName() == stock.Prefab) count++;
+ if (!Check(count == stock.Count, "original starting stock count " + stock.Prefab)) return false;
+ }
+ if (!Check(ERR_ObjectiveText.Description(mode).Contains("salvage"), "initial objective explains the salvage bag")) return false;
+ PrintFormat("ERR CRASH START: anchor=%1 wreck=%2 halfSize=%3 clearance=%4; on-foot static aftermath, no crash flight or multiplayer proof", site.Definition.Position, wreck.GetOrigin(), halfSize, height);
+ return true;
+ }
+}
+#endif
--- a/tools/headless_workbench.py
+++ b/tools/headless_workbench.py
@@ -14,7 +14,7 @@
p.add_argument('--external-addons', type=Path, help='Installed RHS/WCS/BMP source root; expose only audited closure in a separate Chat profile')
p.add_argument('--compat', type=Path, required=True, help='Disposable cloned Proton compatdata directory outside Steam')
p.add_argument('--profile', type=Path, required=True, help='Separate disposable successor Workbench profile')
-p.add_argument('--smoke', choices=['crash-geometry', 'normal-escape-route', 'escape-route', 'optional-site-skip', 'infantry-combat', 'medical-combat', 'hunter-faction', 'unconscious-camera', 'objective-map', 'town-garrisons', 'site-garrisons', 'radio-interaction', 'enemy-loadout', 'aggression', 'air-logistics', 'air-assault', 'air-recon', 'airfield-markers', 'opening-tools', 'mortar-station', 'generated-sites', 'hq-local-handoff', 'infantry-transfer', 'hq-body', 'convoy', 'supply-convoys', 'supply-travel', 'mounted-ammo', 'alarm-hearing', 'hq-memory', 'hq-awareness', 'aircraft-field', 'aircraft-route', 'native-end-active', 'native-end-preparing', 'aircraft-control', 'aircraft-cancel', 'aircraft-translate', 'map-ownership', 'mortar-refresh', 'mortar-salvo', 'mortar-courier', 'station-teardown', 'prison-breach', 'powered-flight', 'powered-translate', 'local-admission', 'mortar-expiry', 'mortar-transfer', 'mortar-fire', 'patrol-hq', 'victory', 'lost-helicopter', 'player-death', 'radio-network', 'hq-response', 'mortar-inventory', 'startup-failure', 'site-survey', 'cache-loss', 'extraction-capacity', 'early-helicopter-loss', 'extraction-startup-failure', 'extraction-boundary-failure', 'transport-loss', 'transport-survey', 'lifecycle', 'objective-ui', 'recovery', 'prisoner-kit', 'medical', 'casualty-load', 'casualty-direct', 'casualty-bench', 'casualty-remove', 'environment', 'environment-restart', 'patrols', 'radio-document-loss', 'radio-document-loss-partial', 'guard-cancel', 'casualty-service'], default='victory')
+p.add_argument('--smoke', choices=['crash-start', 'crash-geometry', 'normal-escape-route', 'escape-route', 'optional-site-skip', 'infantry-combat', 'medical-combat', 'hunter-faction', 'unconscious-camera', 'objective-map', 'town-garrisons', 'site-garrisons', 'radio-interaction', 'enemy-loadout', 'aggression', 'air-logistics', 'air-assault', 'air-recon', 'airfield-markers', 'opening-tools', 'mortar-station', 'generated-sites', 'hq-local-handoff', 'infantry-transfer', 'hq-body', 'convoy', 'supply-convoys', 'supply-travel', 'mounted-ammo', 'alarm-hearing', 'hq-memory', 'hq-awareness', 'aircraft-field', 'aircraft-route', 'native-end-active', 'native-end-preparing', 'aircraft-control', 'aircraft-cancel', 'aircraft-translate', 'map-ownership', 'mortar-refresh', 'mortar-salvo', 'mortar-courier', 'station-teardown', 'prison-breach', 'powered-flight', 'powered-translate', 'local-admission', 'mortar-expiry', 'mortar-transfer', 'mortar-fire', 'patrol-hq', 'victory', 'lost-helicopter', 'player-death', 'radio-network', 'hq-response', 'mortar-inventory', 'startup-failure', 'site-survey', 'cache-loss', 'extraction-capacity', 'early-helicopter-loss', 'extraction-startup-failure', 'extraction-boundary-failure', 'transport-loss', 'transport-survey', 'lifecycle', 'objective-ui', 'recovery', 'prisoner-kit', 'medical', 'casualty-load', 'casualty-direct', 'casualty-bench', 'casualty-remove', 'environment', 'environment-restart', 'patrols', 'radio-document-loss', 'radio-document-loss-partial', 'guard-cancel', 'casualty-service'], default='victory')
p.add_argument('--trace-random-radius', action='store_true', help='Workbench-only read-only zero-radius caller traces; one normal Chat round, capped at sixteen records')
p.add_argument('--maintenance-refuel', action='store_true', help='Opt-in normal-route check: original held Southern fuel can transfers finite fuel through its native UAZ action; one arranged tank depletion, no stock creation')
p.add_argument('--mounted-swap-eligibility', action='store_true', help='Read-only mounted-ammo variant: one exact finite cargo/mounted magazine CanSwap call; no transfer or radio proof')
@@ -35,6 +35,7 @@
p.add_argument('--timeout', type=int, default=360)
p.add_argument('--project', choices=['core', 'chat'], default='chat', help='Diagnostic fixture family (both load the combined mod)')
a = p.parse_args()
+if a.smoke == 'crash-start' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 240): p.error('crash-start requires Chat, one round and timeout at least 240 seconds')
if a.smoke == 'crash-geometry' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 180): p.error('crash-geometry requires Chat, one round and timeout at least180 seconds')
if a.trace_random_radius and (a.smoke != 'normal-escape-route' or a.project != 'chat' or a.rounds != 1 or a.timeout < 420): p.error('--trace-random-radius requires Chat normal-escape-route, one round and timeout at least 420 seconds')
if a.smoke == 'objective-map' and (a.project != 'core' or a.rounds != 1): p.error('objective-map requires --project core --rounds 1')
--- a/tools/check.py
+++ b/tools/check.py
@@ -88,7 +88,7 @@
assert set(mapped)==set(inventory['script_paths']), 'Original inventory has untracked or unknown entries'
print(f'PASS: {len(mapped)} original script entries tracked across {len(feature_ids)} unfinished responsibilities')
print(f'PASS: {len(ids)} isolated addons, acyclic dependencies, {len(resources)} unique resources, exact vanilla/authorized external references')
- for name in ['test_intercept_vehicle_footprint.py', 'test_bmp_intercept_geometry.py', 'test_native_random_radius_trace.py', 'test_native_random_radius_runner.py', 'test_native_supply_travel.py', 'test_native_supply_travel_hook.py', 'test_native_supply_travel_runner.py', 'test_native_mounted_intercept.py', 'test_hq_mounted_dispatch.py', 'test_hq_mounted_intercept.py', 'test_hq_mounted_intercept_pair.py', 'test_convoy_intercept_pair.py', 'test_native_maintenance_refuel.py', 'test_mine_intel.py', 'test_mine_intel_discovery_integration.py', 'test_infantry_combat.py', 'test_enemy_medicine.py', 'test_hunter_combat.py', 'test_hq_local_awareness.py', 'test_unconscious_controls.py', 'test_town_garrisons.py', 'test_field_sites.py', 'test_gameplay_session_regressions.py', 'test_gameplay_review_fixes.py', 'test_server_log_regressions.py', 'test_mortar_load_ack.py', 'test_hunter_profiles.py', 'test_hunter_lifecycle.py', 'test_hunter_capture.py', 'test_hunter_opening.py', 'test_enemy_awareness.py', 'test_intel_body_inspection.py', 'test_body_recovery_lifecycle.py', 'test_air_support_policy.py', 'test_air_logistics_orders.py', 'test_air_recon.py', 'test_scouts.py', 'test_mortar_station.py', 'test_random_settings.py', 'test_debug_ai.py', 'test_generated_sites.py', 'test_terrain_sites.py', 'test_terrain_adapter.py', 'test_terrain_airfields.py','test_terrain_takeover.py', 'test_terrain_presentation.py', 'test_terrain_selection.py', 'test_faction_selection.py', 'test_faction_menu.py', 'test_content_policy.py', 'test_hq_road_intercept.py', 'test_hq_delivered_task.py', 'test_hq_local_handoff.py', 'test_hq_local_handoff_intake.py', 'test_native_local_handoff_probe.py', 'test_infantry_resupply_waypoints.py', 'test_infantry_placement_settle.py', 'test_native_infantry_fixture_lifecycle.py', 'test_native_infantry_cargo.py', 'test_native_infantry_setup.py', 'test_infantry_ammo_access.py', 'test_infantry_resupply_planning.py', 'test_infantry_supply_pool.py', 'test_hq_multiconvoy_supply.py', 'test_enemy_gunner_skill.py', 'test_native_memory_deadlines.py', 'test_convoy_auto_settings.py', 'test_convoy_startup.py', 'test_failure_result_refresh.py', 'test_infantry_resupply_coordinator.py', 'test_infantry_mine_coordinator.py', 'test_infantry_mine_transfer.py', 'test_infantry_ammo_transfer.py', 'test_finite_magazine_reservation.py', 'test_mounted_ammo_transfer.py', 'test_mounted_ammo_pickup.py', 'test_mounted_resupply.py', 'test_mounted_supply_integration.py', 'test_hq_ammo_reporting.py', 'test_enemy_radio.py', 'test_native_maintenance_stock.py', 'test_packed_external_game.py', 'test_hq_radio_node.py', 'test_vehicle_maintenance_stock.py', 'test_optional_transport.py', 'test_vehicle_entry_diagnostics.py', 'test_vehicle_security_native_probe.py', 'test_vehicle_security.py', 'test_vehicle_alarm.py', 'test_vehicle_alarm_perception.py', 'test_native_convoy_mine_stock.py', 'test_native_mine_stock_runner.py', 'test_native_mounted_ammo_probe.py', 'test_native_mounted_swap_probe.py', 'test_native_mounted_courier_probe.py', 'test_native_alarm_hearing.py', 'test_native_convoy_cover_probe.py', 'test_enemy_optics.py', 'test_convoy_combat.py', 'test_ai_stinger_admin.py', 'test_hq_ammo_dispatch.py', 'test_hq_convoy_combat.py', 'test_hq_ammo_sampler.py', 'test_hq_mine_sampler.py', 'test_hq_mounted_ammo_sampler.py', 'test_hq_mounted_binding.py', 'test_hq_vehicle_seats.py', 'test_native_hq_body_probe.py', 'test_hq_delivered_casualties.py', 'test_external_profile_review.py', 'test_hq_uplink_fairness.py', 'test_actor_group.py', 'test_native_package_external.py', 'test_native_convoy_probe.py', 'test_convoy_placement.py', 'test_convoy_road_plan.py', 'test_hq_convoy_dispatch.py', 'test_convoy_admission.py', 'test_convoy_dispatch.py', 'test_convoy_lifecycle.py', 'test_convoy_survivors.py', 'test_convoy_budget.py','test_supply_convoys.py', 'test_supply_budget_admission.py', 'test_mounted_initial_stock.py', 'test_convoy_mine_stock.py', 'test_convoy_column.py', 'test_hq_body_observer.py', 'test_hq_status_sampler.py', 'test_hq_watch.py', 'test_hq_assignment_lifecycle.py', 'test_force_ledger.py', 'test_enemy_equipment.py', 'test_enemy_loadout.py', 'test_automatic_equipment.py', 'test_engineer_mine.py', 'test_engineer_mine_site.py', 'test_engineer_mine_hq.py', 'test_engineer_mine_posts.py', 'test_hq_doctrine.py', 'test_hq_coverage.py', 'test_hq_task_reservations.py', 'test_hq_pursuit.py', 'test_hq_memory.py', 'test_external_addons.py', 'test_admin_tick_delivery.py', 'test_project_schema.py', 'test_admin_session.py', 'test_admin_providers.py', 'test_admin_menu.py', 'test_server_item_catalog.py', 'test_item_preferences.py', 'test_journal_readability.py', 'test_admin_player_tools.py', 'test_intel_admin.py', 'test_intel_reroll.py', 'test_intel_discovery_feedback.py', 'test_hq_report_selection.py', 'test_casualty_feedback.py', 'test_initial_admission_exhaustion.py', 'test_prison_held_action_proof.py', 'test_prison_held_action_evidence.py', 'test_prison_held_input_adapter.py', 'test_prison_held_runner.py', 'test_prison_coarse_facing.py', 'test_aircraft_field_probe.py', 'test_aircraft_field_runner.py', 'test_aircraft_field_rules.py', 'test_aircraft_field_envelope.py', 'test_aircraft_field_flight.py', 'test_command_maintenance.py', 'test_aircraft_service.py', 'test_aircraft_service_cancel_runner.py', 'test_prison_action_selection_proof.py', 'test_prison_action_selection_evidence.py', 'test_ordinary_gate_choices.py', 'test_aircraft_control_bridge.py', 'test_prison_alignment_proof.py', 'test_prison_alignment_evidence.py', 'test_aircraft_route_demand.py', 'test_prison_approach_proof.py', 'test_prison_approach_evidence.py', 'test_ordinary_gate_evidence.py', 'test_ordinary_gate_observer.py', 'test_ordinary_look_observer.py', 'test_ordinary_look_evidence.py', 'test_relative_look_runner.py', 'test_radio_waiting_text.py', 'test_inventory_control_runner.py', 'test_inventory_layout.py', 'test_headless_input_proof.py', 'test_headless_input_exercise_runner.py', 'test_private_prefix_cleanup.py', 'test_runner_private_cleanup.py', 'test_ordinary_input_runner.py', 'test_ordinary_input_observer.py', 'test_aircraft_route_envelope.py', 'test_aircraft_route_policy.py', 'test_aircraft_route_probe.py', 'test_rough_intel_feedback.py', 'test_headless_display_probe.py', 'test_headless_display_runner.py', 'test_preparation_status.py', 'test_hint_delivery.py', 'test_native_end_lifecycle.py', 'test_native_end_runner.py', 'test_escape_result_wording.py', 'test_native_stats.py', 'test_aircraft_translation.py', 'test_spawn_retry_budget.py', 'test_spawn_preload_timeout.py', 'test_action_feedback.py', 'test_native_aircraft_control.py', 'test_aircraft_flight_policy.py', 'test_aircraft_flight_envelope.py', 'test_ordinary_screenshot.py', 'test_participant_selection.py', 'test_native_shared_map_ownership.py', 'test_shared_map_ownership.py', 'test_intel_registration.py', 'test_mortar_activity_completion.py', 'test_packed_chat_game.py', 'test_native_mortar_refresh.py', 'test_archive_packed.py', 'test_mortar_refresh.py', 'test_packed_core_game.py', 'test_pak_inventory.py', 'test_native_mortar_salvo.py', 'test_spectator_guidance.py', 'test_spectator_recovery.py', 'test_native_package.py', 'test_item_station_teardown.py', 'test_source_bundle.py', 'test_native_flight_footprint.py', 'test_native_flight_input_diagnostics.py', 'test_mortar_logistics.py', 'test_mortar_courier_storage.py','test_powered_flight_pad.py','test_prison_escape_policy.py','test_powered_flight_policy.py','test_flight_action_runner.py','test_native_local_admission_probe.py','test_mortar_report_ledger.py','test_dedicated_native.py','test_native_mortar_transfer.py','test_mortar_aim_renewal.py','test_dedicated_preflight.py','test_mortar_transactions.py','test_native_mortar_probe.py','test_diagnostic_no_splash.py','test_casualty_incapacitation.py','test_casualty_remove_probe.py','test_extraction_placement_policy.py','test_guard_cancellation_policy.py','test_casualty_ground_policy.py','test_casualty_reservation_death.py','test_casualty_loading_policy.py','test_initial_guard_policy.py','test_headless_game_runner.py','test_vanilla_game_control.py','test_archive_game_control.py','test_site_discovery_policy.py','test_faction_catalog_scope.py','test_mission_rules.py','test_admin_setting_policy.py', 'test_player_admission_policy.py','test_progression_identity.py','test_discovery_map_position.py','test_local_admission.py','test_prison_placement_policy.py', 'test_recovery_policy.py', 'test_player_medical.py','test_time_policy.py','test_environment_policy.py','test_view_distance.py','test_environment_restart_runner.py', 'test_inventory_enumeration_policy.py','test_radio_defence_policy.py','test_radio_feedback_policy.py','test_performance_comparison.py','test_release_check.py','test_settings_migration.py','hq_network_regression.py','helicopter_availability_regression.py','mortar_salvo_regression.py']:
+ for name in ['test_crash_start.py', 'test_start_settings.py', 'test_intercept_vehicle_footprint.py', 'test_bmp_intercept_geometry.py', 'test_native_random_radius_trace.py', 'test_native_random_radius_runner.py', 'test_native_supply_travel.py', 'test_native_supply_travel_hook.py', 'test_native_supply_travel_runner.py', 'test_native_mounted_intercept.py', 'test_hq_mounted_dispatch.py', 'test_hq_mounted_intercept.py', 'test_hq_mounted_intercept_pair.py', 'test_convoy_intercept_pair.py', 'test_native_maintenance_refuel.py', 'test_mine_intel.py', 'test_mine_intel_discovery_integration.py', 'test_infantry_combat.py', 'test_enemy_medicine.py', 'test_hunter_combat.py', 'test_hq_local_awareness.py', 'test_unconscious_controls.py', 'test_town_garrisons.py', 'test_field_sites.py', 'test_gameplay_session_regressions.py', 'test_gameplay_review_fixes.py', 'test_server_log_regressions.py', 'test_mortar_load_ack.py', 'test_hunter_profiles.py', 'test_hunter_lifecycle.py', 'test_hunter_capture.py', 'test_hunter_opening.py', 'test_enemy_awareness.py', 'test_intel_body_inspection.py', 'test_body_recovery_lifecycle.py', 'test_air_support_policy.py', 'test_air_logistics_orders.py', 'test_air_recon.py', 'test_scouts.py', 'test_mortar_station.py', 'test_random_settings.py', 'test_debug_ai.py', 'test_generated_sites.py', 'test_terrain_sites.py', 'test_terrain_adapter.py', 'test_terrain_airfields.py','test_terrain_takeover.py', 'test_terrain_presentation.py', 'test_terrain_selection.py', 'test_faction_selection.py', 'test_faction_menu.py', 'test_content_policy.py', 'test_hq_road_intercept.py', 'test_hq_delivered_task.py', 'test_hq_local_handoff.py', 'test_hq_local_handoff_intake.py', 'test_native_local_handoff_probe.py', 'test_infantry_resupply_waypoints.py', 'test_infantry_placement_settle.py', 'test_native_infantry_fixture_lifecycle.py', 'test_native_infantry_cargo.py', 'test_native_infantry_setup.py', 'test_infantry_ammo_access.py', 'test_infantry_resupply_planning.py', 'test_infantry_supply_pool.py', 'test_hq_multiconvoy_supply.py', 'test_enemy_gunner_skill.py', 'test_native_memory_deadlines.py', 'test_convoy_auto_settings.py', 'test_convoy_startup.py', 'test_failure_result_refresh.py', 'test_infantry_resupply_coordinator.py', 'test_infantry_mine_coordinator.py', 'test_infantry_mine_transfer.py', 'test_infantry_ammo_transfer.py', 'test_finite_magazine_reservation.py', 'test_mounted_ammo_transfer.py', 'test_mounted_ammo_pickup.py', 'test_mounted_resupply.py', 'test_mounted_supply_integration.py', 'test_hq_ammo_reporting.py', 'test_enemy_radio.py', 'test_native_maintenance_stock.py', 'test_packed_external_game.py', 'test_hq_radio_node.py', 'test_vehicle_maintenance_stock.py', 'test_optional_transport.py', 'test_vehicle_entry_diagnostics.py', 'test_vehicle_security_native_probe.py', 'test_vehicle_security.py', 'test_vehicle_alarm.py', 'test_vehicle_alarm_perception.py', 'test_native_convoy_mine_stock.py', 'test_native_mine_stock_runner.py', 'test_native_mounted_ammo_probe.py', 'test_native_mounted_swap_probe.py', 'test_native_mounted_courier_probe.py', 'test_native_alarm_hearing.py', 'test_native_convoy_cover_probe.py', 'test_enemy_optics.py', 'test_convoy_combat.py', 'test_ai_stinger_admin.py', 'test_hq_ammo_dispatch.py', 'test_hq_convoy_combat.py', 'test_hq_ammo_sampler.py', 'test_hq_mine_sampler.py', 'test_hq_mounted_ammo_sampler.py', 'test_hq_mounted_binding.py', 'test_hq_vehicle_seats.py', 'test_native_hq_body_probe.py', 'test_hq_delivered_casualties.py', 'test_external_profile_review.py', 'test_hq_uplink_fairness.py', 'test_actor_group.py', 'test_native_package_external.py', 'test_native_convoy_probe.py', 'test_convoy_placement.py', 'test_convoy_road_plan.py', 'test_hq_convoy_dispatch.py', 'test_convoy_admission.py', 'test_convoy_dispatch.py', 'test_convoy_lifecycle.py', 'test_convoy_survivors.py', 'test_convoy_budget.py','test_supply_convoys.py', 'test_supply_budget_admission.py', 'test_mounted_initial_stock.py', 'test_convoy_mine_stock.py', 'test_convoy_column.py', 'test_hq_body_observer.py', 'test_hq_status_sampler.py', 'test_hq_watch.py', 'test_hq_assignment_lifecycle.py', 'test_force_ledger.py', 'test_enemy_equipment.py', 'test_enemy_loadout.py', 'test_automatic_equipment.py', 'test_engineer_mine.py', 'test_engineer_mine_site.py', 'test_engineer_mine_hq.py', 'test_engineer_mine_posts.py', 'test_hq_doctrine.py', 'test_hq_coverage.py', 'test_hq_task_reservations.py', 'test_hq_pursuit.py', 'test_hq_memory.py', 'test_external_addons.py', 'test_admin_tick_delivery.py', 'test_project_schema.py', 'test_admin_session.py', 'test_admin_providers.py', 'test_admin_menu.py', 'test_server_item_catalog.py', 'test_item_preferences.py', 'test_journal_readability.py', 'test_admin_player_tools.py', 'test_intel_admin.py', 'test_intel_reroll.py', 'test_intel_discovery_feedback.py', 'test_hq_report_selection.py', 'test_casualty_feedback.py', 'test_initial_admission_exhaustion.py', 'test_prison_held_action_proof.py', 'test_prison_held_action_evidence.py', 'test_prison_held_input_adapter.py', 'test_prison_held_runner.py', 'test_prison_coarse_facing.py', 'test_aircraft_field_probe.py', 'test_aircraft_field_runner.py', 'test_aircraft_field_rules.py', 'test_aircraft_field_envelope.py', 'test_aircraft_field_flight.py', 'test_command_maintenance.py', 'test_aircraft_service.py', 'test_aircraft_service_cancel_runner.py', 'test_prison_action_selection_proof.py', 'test_prison_action_selection_evidence.py', 'test_ordinary_gate_choices.py', 'test_aircraft_control_bridge.py', 'test_prison_alignment_proof.py', 'test_prison_alignment_evidence.py', 'test_aircraft_route_demand.py', 'test_prison_approach_proof.py', 'test_prison_approach_evidence.py', 'test_ordinary_gate_evidence.py', 'test_ordinary_gate_observer.py', 'test_ordinary_look_observer.py', 'test_ordinary_look_evidence.py', 'test_relative_look_runner.py', 'test_radio_waiting_text.py', 'test_inventory_control_runner.py', 'test_inventory_layout.py', 'test_headless_input_proof.py', 'test_headless_input_exercise_runner.py', 'test_private_prefix_cleanup.py', 'test_runner_private_cleanup.py', 'test_ordinary_input_runner.py', 'test_ordinary_input_observer.py', 'test_aircraft_route_envelope.py', 'test_aircraft_route_policy.py', 'test_aircraft_route_probe.py', 'test_rough_intel_feedback.py', 'test_headless_display_probe.py', 'test_headless_display_runner.py', 'test_preparation_status.py', 'test_hint_delivery.py', 'test_native_end_lifecycle.py', 'test_native_end_runner.py', 'test_escape_result_wording.py', 'test_native_stats.py', 'test_aircraft_translation.py', 'test_spawn_retry_budget.py', 'test_spawn_preload_timeout.py', 'test_action_feedback.py', 'test_native_aircraft_control.py', 'test_aircraft_flight_policy.py', 'test_aircraft_flight_envelope.py', 'test_ordinary_screenshot.py', 'test_participant_selection.py', 'test_native_shared_map_ownership.py', 'test_shared_map_ownership.py', 'test_intel_registration.py', 'test_mortar_activity_completion.py', 'test_packed_chat_game.py', 'test_native_mortar_refresh.py', 'test_archive_packed.py', 'test_mortar_refresh.py', 'test_packed_core_game.py', 'test_pak_inventory.py', 'test_native_mortar_salvo.py', 'test_spectator_guidance.py', 'test_spectator_recovery.py', 'test_native_package.py', 'test_item_station_teardown.py', 'test_source_bundle.py', 'test_native_flight_footprint.py', 'test_native_flight_input_diagnostics.py', 'test_mortar_logistics.py', 'test_mortar_courier_storage.py','test_powered_flight_pad.py','test_prison_escape_policy.py','test_powered_flight_policy.py','test_flight_action_runner.py','test_native_local_admission_probe.py','test_mortar_report_ledger.py','test_dedicated_native.py','test_native_mortar_transfer.py','test_mortar_aim_renewal.py','test_dedicated_preflight.py','test_mortar_transactions.py','test_native_mortar_probe.py','test_diagnostic_no_splash.py','test_casualty_incapacitation.py','test_casualty_remove_probe.py','test_extraction_placement_policy.py','test_guard_cancellation_policy.py','test_casualty_ground_policy.py','test_casualty_reservation_death.py','test_casualty_loading_policy.py','test_initial_guard_policy.py','test_headless_game_runner.py','test_vanilla_game_control.py','test_archive_game_control.py','test_site_discovery_policy.py','test_faction_catalog_scope.py','test_mission_rules.py','test_admin_setting_policy.py', 'test_player_admission_policy.py','test_progression_identity.py','test_discovery_map_position.py','test_local_admission.py','test_prison_placement_policy.py', 'test_recovery_policy.py', 'test_player_medical.py','test_time_policy.py','test_environment_policy.py','test_view_distance.py','test_environment_restart_runner.py', 'test_inventory_enumeration_policy.py','test_radio_defence_policy.py','test_radio_feedback_policy.py','test_performance_comparison.py','test_release_check.py','test_settings_migration.py','hq_network_regression.py','helicopter_availability_regression.py','mortar_salvo_regression.py']:
subprocess.run([sys.executable,str(ROOT/'tests'/name)],check=True)
print('All repository checks passed. Native compilation and multiplayer tests are separate requirements.')
if __name__=='__main__':check()