Capture current mission, AI, map and administration development

Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
This commit is contained in:
2026-10-13 22:52:53 +02:00
parent a951a96edc
commit 6a667d8deb
8104 changed files with 2124945 additions and 2061 deletions
@@ -0,0 +1,350 @@
--- /dev/null
+++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeInventoryHitZoneProbe.c
@@ -0,0 +1,166 @@
+#ifdef WORKBENCH
+// Read-only fixture access to native UI identities. No replacement widgets.
+modded class SCR_InventoryMenuUI
+{
+ bool ERR_HitZoneProbeReady(IEntity actor)
+ {
+ return ERR_NativeInventoryHitZoneProbe.Enabled() && m_Player == actor && m_pStorageListUI
+ && m_pStorageListUI.GetStorage() && m_PlayerRenderAttributes && m_wAttachmentPointsContainer;
+ }
+ bool ERR_HitZoneProbePoints(out array<ref SCR_InventoryHitZonePointContainerUI> points)
+ {
+ points.Clear();
+ if (!ERR_NativeInventoryHitZoneProbe.Enabled() || m_aHitZonePoints.Count() != 7) return false;
+ foreach (SCR_InventoryHitZonePointContainerUI point : m_aHitZonePoints) points.Insert(point);
+ return true;
+ }
+}
+
+modded class SCR_InventoryHitZonePointContainerUI
+{
+ protected SCR_HitZone m_ERRProbeBlood;
+ protected int m_ERRProbeUpdates;
+ protected bool m_ERRProbeFalseRefresh;
+ protected override void UpdateHitZoneState(SCR_HitZone hz, bool updateAttachmentStorage = true)
+ {
+ super.UpdateHitZoneState(hz, updateAttachmentStorage);
+ if (m_ERRProbeBlood && hz == m_ERRProbeBlood)
+ {
+ m_ERRProbeUpdates++;
+ if (!updateAttachmentStorage) m_ERRProbeFalseRefresh = true;
+ }
+ }
+ bool ERR_HitZoneProbeWatch(ERR_GameMode mode, SCR_HitZone blood)
+ {
+ if (!ERR_NativeInventoryHitZoneProbe.Enabled() || !mode || mode != m_ERRHitZoneMode
+ || !blood || !m_ERRHitZoneSources.Contains(blood)) return false;
+ m_ERRProbeBlood = blood; m_ERRProbeUpdates = 0; m_ERRProbeFalseRefresh = false;
+ return true;
+ }
+ bool ERR_HitZoneProbeOnce() { return m_ERRProbeUpdates == 1 && !m_ERRProbeFalseRefresh; }
+ bool ERR_HitZoneProbeDetached() { return !m_ERRHitZoneMode && m_ERRHitZoneSources.IsEmpty(); }
+ void ERR_HitZoneProbeStop() { m_ERRProbeBlood = null; }
+}
+
+// Emits one real one-argument damage-state notification without changing health.
+// It proves callback/native UI integration, not a natural injury or manual UI use.
+class ERR_NativeInventoryHitZoneProbe
+{
+ protected ERR_GameMode m_Mode;
+ protected SCR_PlayerController m_Controller;
+ protected IEntity m_Actor;
+ protected SCR_InventoryStorageManagerComponent m_Inventory;
+ protected SCR_CharacterBloodHitZone m_Blood;
+ protected SCR_InventoryMenuUI m_Menu;
+ protected ref array<ref SCR_InventoryHitZonePointContainerUI> m_Points = {};
+ protected int m_Deadline;
+ protected int m_Stage;
+ protected int m_Result;
+ protected bool m_Stopped;
+ protected bool m_CloseRequested;
+ protected float m_Health;
+ static bool Enabled()
+ {
+ string enabled, outcome;
+ return Replication.IsServer() && System.GetCLIParam("errBaseSmoke", enabled) && enabled == "1"
+ && System.GetCLIParam("errSmokeOutcome", outcome) && outcome == "inventory-hitzone";
+ }
+ void ERR_NativeInventoryHitZoneProbe(ERR_GameMode mode, IEntity actor)
+ {
+ m_Mode = mode; m_Actor = actor; m_Deadline = System.GetTickCount() + 30000;
+ m_Controller = SCR_PlayerController.Cast(GetGame().GetPlayerController());
+ }
+ protected bool Check(bool condition, string detail)
+ {
+ if (condition) { Print("ERR SMOKE PASS: inventory hitzone " + detail); return true; }
+ Print("ERR SMOKE FAIL: inventory hitzone " + detail, LogLevel.ERROR);
+ m_Result = -1; Stop(); return false;
+ }
+ protected bool Context()
+ {
+ return Enabled() && m_Mode && m_Mode == ERR_GameMode.Get() && m_Mode.Active()
+ && m_Controller && m_Controller == GetGame().GetPlayerController() && m_Controller.GetControlledEntity() == m_Actor
+ && m_Mode.Players() && m_Mode.Players().CurrentActor(m_Actor) && ERR_Actors.CanFight(m_Actor);
+ }
+ protected bool OwnsMenu()
+ {
+ return m_Menu && GetGame().GetMenuManager().FindMenuByPreset(ChimeraMenuPreset.Inventory20Menu) == m_Menu;
+ }
+ protected bool UnchangedHealth() { return m_Blood && m_Blood.GetHealth() == m_Health; }
+ int Tick(float now)
+ {
+ if (m_Result != 0) return m_Result;
+ if (m_Stopped) return -1;
+ if (!Context()) { Check(false, "original conscious local round body changed"); return -1; }
+ if (System.GetTickCount() >= m_Deadline) { Check(false, "fixed 30-second UI/callback deadline"); return -1; }
+ if (m_Stage == 0)
+ {
+ if (!Check(!GetGame().GetMenuManager().GetTopMenu(), "no existing menu adopted")) return -1;
+ m_Inventory = SCR_InventoryStorageManagerComponent.Cast(m_Actor.FindComponent(SCR_InventoryStorageManagerComponent));
+ SCR_CharacterDamageManagerComponent damage = SCR_CharacterDamageManagerComponent.Cast(m_Actor.FindComponent(SCR_CharacterDamageManagerComponent));
+ if (damage) m_Blood = damage.GetBloodHitZone();
+ if (!Check(m_Inventory && m_Blood, "original native inventory and blood event source present")) return -1;
+ m_Health = m_Blood.GetHealth();
+ m_Inventory.OpenInventory();
+ m_Menu = SCR_InventoryMenuUI.Cast(GetGame().GetMenuManager().FindMenuByPreset(ChimeraMenuPreset.Inventory20Menu));
+ if (!Check(OwnsMenu(), "ordinary native inventory opens without input automation")) return -1;
+ m_Stage = 1; return 0;
+ }
+ if (m_Stage == 1)
+ {
+ if (!Check(OwnsMenu() && UnchangedHealth(), "owned inventory and original blood health retained")) return -1;
+ if (!m_Menu.ERR_HitZoneProbeReady(m_Actor)) return 0;
+ m_Menu.InspectItem(null); // Native character inspection creates its normal seven containers over several frames.
+ m_Stage = 2; return 0;
+ }
+ if (m_Stage == 2)
+ {
+ if (!Check(OwnsMenu() && UnchangedHealth(), "native inspection retains original menu and health")) return -1;
+ if (!m_Menu.ERR_HitZoneProbePoints(m_Points)) return 0;
+ array<SCR_InventoryHitZonePointContainerUI> seen = {};
+ foreach (SCR_InventoryHitZonePointContainerUI point : m_Points)
+ {
+ if (!Check(point && !seen.Contains(point) && point.ERR_HitZoneProbeWatch(m_Mode, m_Blood), "unique native point retains original blood subscription")) return -1;
+ seen.Insert(point);
+ }
+ if (!Check(UnchangedHealth() && m_Blood.GetOnDamageStateChanged(false), "original blood event and health retained before notification")) return -1;
+ m_Blood.GetOnDamageStateChanged(false).Invoke(m_Blood);
+ foreach (SCR_InventoryHitZonePointContainerUI updated : m_Points)
+ if (!Check(updated.ERR_HitZoneProbeOnce(), "one-argument event reached native updater once with explicit true")) return -1;
+ if (!Check(UnchangedHealth() && OwnsMenu(), "notification changes no blood health or menu ownership")) return -1;
+ bool closeAccepted = GetGame().GetMenuManager().CloseMenu(m_Menu);
+ m_CloseRequested = closeAccepted;
+ if (!Check(closeAccepted, "exact owned inventory close request accepted")) return -1;
+ m_Stage = 3; return 0;
+ }
+ if (m_Stage == 3)
+ {
+ MenuBase current = GetGame().GetMenuManager().FindMenuByPreset(ChimeraMenuPreset.Inventory20Menu);
+ if (current == m_Menu && m_Menu) return 0;
+ if (!Check(!current, "native inventory closes without adopting a replacement")) return -1;
+ foreach (SCR_InventoryHitZonePointContainerUI detached : m_Points)
+ if (!Check(detached && detached.ERR_HitZoneProbeDetached(), "native detach cleared original point subscriptions")) return -1;
+ if (!Check(UnchangedHealth() && m_Blood.GetOnDamageStateChanged(false), "original blood event and health retained before notification")) return -1;
+ m_Blood.GetOnDamageStateChanged(false).Invoke(m_Blood);
+ foreach (SCR_InventoryHitZonePointContainerUI oldPoint : m_Points)
+ if (!Check(oldPoint.ERR_HitZoneProbeOnce(), "closed original point receives no late native update")) return -1;
+ if (!Check(UnchangedHealth(), "blood health unchanged through complete callback proof")) return -1;
+ m_Menu = null; m_Result = 1; Stop(); return 1;
+ }
+ Check(false, "unexpected fixture stage"); return -1;
+ }
+ void Stop()
+ {
+ if (m_Stopped) return;
+ m_Stopped = true;
+ foreach (SCR_InventoryHitZonePointContainerUI point : m_Points) if (point) point.ERR_HitZoneProbeStop();
+ m_Points.Clear();
+ if (GetGame() && GetGame().GetMenuManager() && !m_CloseRequested && OwnsMenu())
+ {
+ m_CloseRequested = true;
+ GetGame().GetMenuManager().CloseMenu(m_Menu);
+ }
+ m_Menu = null; m_Blood = null; m_Inventory = null;
+ }
+}
+#endif
--- a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c
+++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c
@@ -20,6 +20,7 @@
protected ref ERR_NativeLocalAdmissionProbe m_ERRLocalAdmissionProbe;
protected ref ERR_NativePoweredFlightProbe m_ERRPoweredFlightProbe;
protected ref ERR_NativePrisonBreachProbe m_ERRPrisonBreachProbe;
+ protected ref ERR_NativeInventoryHitZoneProbe m_ERRInventoryHitZoneProbe;
protected ref ERR_NativeItemStationTeardownProbe m_ERRItemStationTeardownProbe;
protected ref ERR_NativeObjectiveLossProbe m_ERRObjectiveLossProbe;
protected ref ERR_NativeMedicalProbe m_ERRBaseMedicalProbe;
@@ -100,6 +101,7 @@
if (m_ERRLocalAdmissionProbe) m_ERRLocalAdmissionProbe.Stop();
if (m_ERRPoweredFlightProbe) m_ERRPoweredFlightProbe.Stop();
if (m_ERRPrisonBreachProbe) m_ERRPrisonBreachProbe.Stop();
+ if (m_ERRInventoryHitZoneProbe) m_ERRInventoryHitZoneProbe.Stop();
if (m_ERRItemStationTeardownProbe) m_ERRItemStationTeardownProbe.Stop();
if (m_ERRCasualtyServiceProbe) m_ERRCasualtyServiceProbe.Stop();
if (m_ERRObjectiveLossProbe) m_ERRObjectiveLossProbe.Stop();
@@ -172,6 +174,13 @@
{
if (!ERR_MissionRules.Terminal(current)) return;
GetGame().GetCallqueue().Remove(ERR_BaseTick);
+ if (m_ERRExtractionCase == "inventory-hitzone")
+ {
+ if (!ERR_BaseCheck(current == ERR_Phase.DEFEAT && m_ERRBaseStep == 2102, "native inventory callback fixture finished before explicit reset")) return;
+ ERR_StopHealthProbes();
+ Print("ERR SMOKE COMPLETE: real one-argument blood event reaches native inventory updater and detached points stay silent; synthetic notification, no injury/manual UI/multiplayer proof");
+ return;
+ }
if (m_ERRExtractionCase == "station-teardown")
{
if (!ERR_BaseCheck(current == ERR_Phase.DEFEAT && m_ERRBaseStep == 2002, "native station teardown fixture finished before explicit reset")) return;
@@ -336,6 +345,13 @@
Print("ERR SMOKE COMPLETE: expected startup-failure");
return;
}
+ if (m_ERRBaseStep == 2100)
+ {
+ int result = m_ERRInventoryHitZoneProbe.Tick(now);
+ if (result < 0) { ERR_BaseCheck(false, "native inventory hitzone callback fixture"); return; }
+ if (result == 1) { m_ERRBaseStep = 2102; Transition(ERR_Phase.DEFEAT); }
+ return;
+ }
if (m_ERRBaseStep == 2000)
{
int result = m_ERRItemStationTeardownProbe.Tick(now);
@@ -509,6 +525,12 @@
{
if (!ERR_NativeDiscoveryMapProbe.Run()) { GetGame().GetCallqueue().Remove(ERR_BaseTick); return; }
m_ERRDiscoveryMapChecked = true;
+ }
+ if (m_ERRExtractionCase == "inventory-hitzone")
+ {
+ m_ERRInventoryHitZoneProbe = new ERR_NativeInventoryHitZoneProbe(this, m_ERRBasePlayer);
+ m_ERRBaseStep = 2100;
+ return;
}
if (m_ERRExtractionCase == "station-teardown")
{
--- 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-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('--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', 'inventory-hitzone', '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')
@@ -36,6 +36,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 == 'inventory-hitzone' and (a.project != 'core' or a.rounds != 1 or a.timeout < 240): p.error('inventory-hitzone requires --project core --rounds 1 and timeout at least 240 seconds')
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')
@@ -153,10 +154,10 @@
if a.recon_takeover_only: command += ['-errReconTakeoverOnly', '1']
if a.body_recovery_only: command += ['-errBodyRecoveryOnly', '1']
if a.project == 'core':
- if a.smoke not in {'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', 'native-end-active', 'native-end-preparing', 'station-teardown', 'prison-breach', 'powered-flight', 'powered-translate', 'local-admission', 'victory', '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'}: p.error('Unsupported Core-only fixture')
+ if a.smoke not in {'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', 'native-end-active', 'native-end-preparing', 'station-teardown', 'inventory-hitzone', 'prison-breach', 'powered-flight', 'powered-translate', 'local-admission', 'victory', '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'}: p.error('Unsupported Core-only fixture')
command[command.index('-plugin=ERR_ValidateWorldPlugin')] = '-plugin=ERR_ValidateBaseWorldPlugin'
command[command.index('-errSmoke')] = '-errBaseSmoke'
-if a.smoke in {'station-teardown', 'prison-breach', 'powered-flight', 'powered-translate', 'local-admission', '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'} and a.project != 'core': p.error('This fixture requires --project core')
+if a.smoke in {'station-teardown', 'inventory-hitzone', 'prison-breach', 'powered-flight', 'powered-translate', 'local-admission', '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'} and a.project != 'core': p.error('This fixture requires --project core')
if a.smoke in {'startup-failure', 'site-survey', 'transport-survey', 'extraction-startup-failure', 'extraction-boundary-failure'} and (a.project != 'core' or a.rounds != 1): p.error('This diagnostic requires --project core --rounds 1')
env = os.environ.copy()
env.update(STEAM_COMPAT_DATA_PATH=str(compat), STEAM_COMPAT_CLIENT_INSTALL_PATH=str(steam), WINEPREFIX=str(compat/'pfx'))
--- /dev/null
+++ b/tests/test_native_inventory_hitzone.py
@@ -0,0 +1,87 @@
+"""Actual probe state machine/counters; menu, actor and invoker boundaries doubled."""
+import ast,os,re
+from pathlib import Path
+from types import SimpleNamespace
+from policy_harness import ROOT,body,run
+BASE=Path(os.environ.get('ERR_INVENTORY_PROBE_ROOT',ROOT))
+p=Path(os.environ.get('ERR_NATIVE_INVENTORY_SOURCE',BASE/'addons/core/Scripts/Game/ERR/00_Core/ERR_NativeInventoryHitZoneProbe.c'))
+s=p.read_text()
+assert s.startswith('#ifdef WORKBENCH') and s.rstrip().endswith('#endif')
+for forbidden in ['SetHealth(', 'FullHeal(', 'ForceUnconsciousness(', 'SetOrigin(', 'CreateWidgets(', 'InputManager', 'ERR_ClearHitZoneCallbacks(']: assert forbidden not in s
+assert 'super.UpdateHitZoneState(hz, updateAttachmentStorage);' in s
+assert 'm_Menu.InspectItem(null);' in s and 'm_Deadline = System.GetTickCount() + 30000' in s
+assert 'out array<ref SCR_InventoryHitZonePointContainerUI> points' in s
+
+def cpp(s):
+ for a,b in [('protected override ',''),('protected ',''),('override ',''),('super.UpdateHitZoneState','Native::UpdateHitZoneState'),('ERR_NativeInventoryHitZoneProbe','Probe'),('SCR_InventoryHitZonePointContainerUI','Point'),('SCR_CharacterDamageManagerComponent','Damage'),('SCR_InventoryStorageManagerComponent','Inventory'),('SCR_CharacterBloodHitZone','Zone'),('SCR_HitZone','Zone'),('ERR_GameMode','Mode'),('SCR_PlayerController','Controller'),('SCR_InventoryMenuUI','Menu'),('MenuBase','Menu'),('IEntity','Actor*'),('string ','string '),('null','nullptr'),('foreach (','for ('),('ref ',''),('array<Point> seen = {};','Array<Point*> seen;')]:s=s.replace(a,b)
+ for name in ['mode','damage','point','updated','detached','oldPoint']:
+ s=re.sub(r'\b'+name+r'\.',name+'->',s)
+ for name in ['m_Mode','m_Controller','m_Actor','m_Inventory','m_Blood','m_Menu']:s=s.replace(name+'.',name+'->')
+ for cls in ['Probe','Mode','Controller','Damage','Inventory','Menu','System','Replication','ERR_Actors','ChimeraMenuPreset']:s=s.replace(cls+'.',cls+'::')
+ for cls,var in [('Mode','mode'),('Zone','hz'),('Zone','blood'),('Point','point'),('Point','updated'),('Point','detached'),('Point','oldPoint'),('Menu','current'),('Damage','damage')]:s=s.replace(cls+' '+var,cls+'* '+var)
+ s=s.replace('GetGame().','GetGame()->').replace('GetMenuManager().','GetMenuManager()->').replace('Players().','Players()->').replace('GetOnDamageStateChanged(false).','GetOnDamageStateChanged(false)->')
+ s=s.replace('FindComponent(Inventory)','FindComponent(1)').replace('FindComponent(Damage)','FindComponent(2)')
+ s=s.replace('Print("ERR SMOKE FAIL: inventory hitzone " + detail, LogLevel.ERROR);','Print("ERR SMOKE FAIL: inventory hitzone " + detail);')
+ return s
+point='\n'.join(cpp(body(p,sig)) for sig in ['protected override void UpdateHitZoneState(','bool ERR_HitZoneProbeWatch(','bool ERR_HitZoneProbeOnce(','bool ERR_HitZoneProbeDetached(','void ERR_HitZoneProbeStop('])
+probe='\n'.join(cpp(body(p,sig)) for sig in ['void ERR_NativeInventoryHitZoneProbe(','protected bool Check(','protected bool Context(','protected bool OwnsMenu(','protected bool UnchangedHealth(','int Tick(','void Stop('])
+probe=probe.replace('void Probe(', 'Probe(')
+run(r'''
+#include <cassert>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <functional>
+using string=std::string;template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;void Clear(){this->clear();}void Insert(T x){this->push_back(x);}bool Contains(T x){return std::find(this->begin(),this->end(),x)!=this->end();}bool IsEmpty(){return this->empty();}};
+struct Actor;struct Mode;struct Point;struct Menu;struct Probe{static bool Enabled(){return enabled;}static inline bool enabled=true;};
+namespace System{int now=0;int GetTickCount(){return now;}}
+namespace ChimeraMenuPreset{int Inventory20Menu=1;}
+void Print(string){}
+struct Event{std::function<void()>fire;int calls=0;void Invoke(void*){calls++;if(fire)fire();}};
+struct Zone{float health=100;Event event;float GetHealth(){return health;}Event*GetOnDamageStateChanged(bool create){assert(!create);return &event;}};
+struct Damage{Zone*blood;Zone*GetBloodHitZone(){return blood;}static Damage*Cast(void*p){return static_cast<Damage*>(p);}};
+struct Inventory{int opens=0;std::function<void()>opening;void OpenInventory(){opens++;if(opening)opening();}static Inventory*Cast(void*p){return static_cast<Inventory*>(p);}};
+struct Actor{Inventory*inventory;Damage*damage;bool fit=true;void*FindComponent(int n){return n==1?static_cast<void*>(inventory):static_cast<void*>(damage);}};
+namespace ERR_Actors{bool CanFight(Actor*a){return a&&a->fit;}}
+struct Controller{Actor*actor;Actor*GetControlledEntity(){return actor;}static Controller*Cast(Controller*p){return p;}};
+struct Roster{Actor*actor;bool CurrentActor(Actor*a){return a==actor;}};
+struct Mode{static inline Mode*current=nullptr;Roster roster;bool active=true;static Mode*Get(){return current;}bool Active(){return active;}Roster*Players(){return &roster;}};
+struct Native{int updates=0;void UpdateHitZoneState(Zone*,bool){updates++;}};
+struct Point:Native{Zone*m_ERRProbeBlood=nullptr;int m_ERRProbeUpdates=0;bool m_ERRProbeFalseRefresh=false;Mode*m_ERRHitZoneMode=nullptr;Array<Zone*>m_ERRHitZoneSources;
+POINT
+};
+struct Menu{Array<Point*>points;Actor*actor=nullptr;bool ready=true;int inspect=0;bool ERR_HitZoneProbeReady(Actor*a){return ready&&actor==a;}void InspectItem(void*){inspect++;}bool ERR_HitZoneProbePoints(Array<Point*>&out){out=points;return points.size()==7;}static Menu*Cast(Menu*m){return m;}};
+struct Manager{Menu*current=nullptr;bool foreignTop=false,accept=true;int closes=0;void*GetTopMenu(){return foreignTop||current?this:nullptr;}Menu*FindMenuByPreset(int){return current;}bool CloseMenu(Menu*m){assert(m==current);closes++;return accept;}};
+struct Game{Controller*controller;Manager manager;Controller*GetPlayerController(){return controller;}Manager*GetMenuManager(){return &manager;}};Game*game=nullptr;Game*GetGame(){return game;}
+struct Actual:Probe{Mode*m_Mode;Controller*m_Controller;Actor*m_Actor;Inventory*m_Inventory=nullptr;Zone*m_Blood=nullptr;Menu*m_Menu=nullptr;Array<Point*>m_Points;int m_Deadline=0,m_Stage=0,m_Result=0;bool m_Stopped=false,m_CloseRequested=false;float m_Health=0;
+PROBE
+};
+struct Fixture{Zone blood;Damage damage{&blood};Inventory inventory;Actor actor{&inventory,&damage};Controller controller{&actor};Mode mode;Game world{&controller,{}};Menu menu;Point points[7];Fixture(){System::now=0;Probe::enabled=true;game=&world;Mode::current=&mode;mode.roster.actor=&actor;menu.actor=&actor;inventory.opening=[&](){world.manager.current=&menu;};for(auto&p:points){p.m_ERRHitZoneMode=&mode;p.m_ERRHitZoneSources.Insert(&blood);menu.points.Insert(&p);}blood.event.fire=[&](){for(auto&p:points)if(!p.m_ERRHitZoneSources.IsEmpty())p.UpdateHitZoneState(&blood,true);};}
+ void Close(){world.manager.current=nullptr;for(auto&p:points){p.m_ERRHitZoneMode=nullptr;p.m_ERRHitZoneSources.Clear();}}
+};
+int main(){
+ {Fixture f;Actual p(&f.mode,&f.actor);assert(p.Tick(0)==0&&f.inventory.opens==1);assert(p.Tick(0)==0&&f.menu.inspect==1);assert(p.Tick(0)==0&&f.blood.event.calls==1&&f.world.manager.closes==1);assert(p.Tick(0)==0&&f.world.manager.closes==1);f.Close();assert(p.Tick(0)==1&&f.blood.event.calls==2&&f.blood.health==100);assert(p.Tick(0)==1);for(auto&x:f.points)assert(x.updates==1);}
+ {Fixture f;Actual p(&f.mode,&f.actor);f.world.manager.foreignTop=true;assert(p.Tick(0)==-1&&f.inventory.opens==0&&f.world.manager.closes==0);}
+ {Fixture f;Actual p(&f.mode,&f.actor);p.Tick(0);f.menu.ready=false;assert(p.Tick(0)==0&&f.menu.inspect==0);System::now=30000;assert(p.Tick(0)==-1&&f.world.manager.closes==1);}
+ {Fixture f;Actual p(&f.mode,&f.actor);p.Tick(0);p.Tick(0);f.menu.points.pop_back();assert(p.Tick(0)==0&&f.blood.event.calls==0);p.Stop();assert(f.world.manager.closes==1);}
+ {Fixture f;Actual p(&f.mode,&f.actor);p.Tick(0);p.Tick(0);f.menu.points[6]=f.menu.points[0];assert(p.Tick(0)==-1&&f.blood.event.calls==0);}
+ {Fixture f;Actual p(&f.mode,&f.actor);p.Tick(0);p.Tick(0);f.blood.event.fire=[&](){for(auto&x:f.points)x.UpdateHitZoneState(&f.blood,false);};assert(p.Tick(0)==-1);}
+ {Fixture f;Actual p(&f.mode,&f.actor);p.Tick(0);p.Tick(0);p.Tick(0);f.world.manager.current=nullptr;assert(p.Tick(0)==-1);}// missing real detach
+ {Fixture f;Actual p(&f.mode,&f.actor);p.Tick(0);p.Tick(0);p.Tick(0);f.Close();f.blood.event.fire=[&](){f.points[0].UpdateHitZoneState(&f.blood,true);};assert(p.Tick(0)==-1);}// late retained callback
+ {Fixture f;Actual p(&f.mode,&f.actor);p.Tick(0);p.Tick(0);f.world.manager.accept=false;assert(p.Tick(0)==-1&&f.world.manager.closes==2);}
+ {Fixture f;Actual p(&f.mode,&f.actor);p.Tick(0);f.blood.health=99;assert(p.Tick(0)==-1);}
+ {Fixture f;Actual p(&f.mode,&f.actor);p.Tick(0);Menu foreign;f.world.manager.current=&foreign;assert(p.Tick(0)==-1&&f.world.manager.closes==0);}
+ {Fixture f;Actual p(&f.mode,&f.actor);p.Tick(0);Controller replacement{&f.actor};f.world.controller=&replacement;assert(p.Tick(0)==-1);}
+ {Fixture f;Actual p(&f.mode,&f.actor);Probe::enabled=false;assert(p.Tick(0)==-1&&f.inventory.opens==0);}
+}
+'''.replace('POINT',point).replace('PROBE',probe.replace('Probe(', 'Actual(')))
+base=(BASE/'addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c').read_text()
+assert 'm_ERRInventoryHitZoneProbe.Tick(now)' in base and 'm_ERRInventoryHitZoneProbe.Stop()' in base
+assert 'current == ERR_Phase.DEFEAT && m_ERRBaseStep == 2102' in base
+assert 'if (result == 1) { m_ERRBaseStep = 2102; Transition(ERR_Phase.DEFEAT); }' in base
+runner=(BASE/'tools/headless_workbench.py').read_text();tree=ast.parse(runner)
+node=next(n for n in tree.body if isinstance(n,ast.If) and "a.smoke == 'inventory-hitzone'" in ast.unparse(n.test))
+for project,rounds,timeout,bad in [('core',1,240,False),('chat',1,240,True),('core',2,240,True),('core',1,239,True)]:
+ assert eval(compile(ast.Expression(node.test),'<selector>','eval'),{'a':SimpleNamespace(smoke='inventory-hitzone',project=project,rounds=rounds,timeout=timeout)})==bad
+assert runner.count("'inventory-hitzone'")>=3
+print('PASS: actual native-probe lifecycle/counters with doubled boundaries; fixed deadline, exact seven sources, true forwarding, async close, no late updates and selector wiring')
@@ -0,0 +1 @@
PASS: actual native-probe lifecycle/counters with doubled boundaries; fixed deadline, exact seven sources, true forwarding, async close, no late updates and selector wiring
@@ -0,0 +1,42 @@
{
"complete": true,
"source_review_approved": true,
"blockers": [],
"files": {
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeInventoryHitZoneProbe.c": "604eacdc66cd52bc8a0115862ee7884a8b0f83bdb50609397de671eacd476543",
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c": "d4318ac4f8567afde4cb9f9546f6022ca74e5cabd689355ee75d19f2cde25060",
"tools/headless_workbench.py": "7ffa38822cee1df4248ea027234823a51c2535a8ce74a9e1a9e7756ee1a72d09",
"tests/test_native_inventory_hitzone.py": "bb67f3e2002661331b1f170955989df5bf30a60b48a294ff979bb6db335ca819"
},
"green_log_sha256": "84c104970b68d9355726cf72b63ac726bf1e4ad6285c4ed66114519264125731",
"scope": "Read-only source/test/log review; no reviewer compiler, native or live writes.",
"api": "SCR_InventoryMenuUI native fields, InspectItem(null), seven-point incremental InitHitZones; SCR_InventoryStorageManagerComponent.OpenInventory; damage.GetBloodHitZone and one-argument invoker; original protected updater override all match inspected installed SDK. CloseMenu(MenuBase) returns bool in exact installed GameLib generated MenuManager.c line32, independently read and hashed from core/data.pak.",
"identity_and_proof": "Current mode, local controller, roster actor and consciousness checked each Tick. Opens only with no existing top menu; pins exact Inventory20Menu; seven unique original subscribed handlers held strongly. Instruments native updater after super and counts exact blood calls with explicit true. First real invoker notification must update each once, blood health unchanged. Exact menu closed; retained handlers must show actual adapter detach cleanup, and second notification must leave counters unchanged. No fixture direct clear of subscriptions.",
"timing_and_cleanup": "30-second construction deadline never resets; one-way Stop closes only still-owned menu and never a replacement. NativeBaseSmoke routes only exact selector, stops probe on failure/terminal and completes only after result1 followed by explicit DEFEAT at step2102. Existing outer210-second cap and runnerCore/one-round/240-second minimum remain.",
"test_review": "Actual probe and counter methods execute against explicit native/menu/actor/invoker doubles; tests retain false refresh, duplicate points, changed health/controller/menu, missing detach and late update rejection, asynchronous close and deadline. Menu readiness/getter and SDK invoker semantics still native validation targets.",
"limits": [
"No native compilation or real rendered UI/callback result yet.",
"Synthetic Invoke(m_Blood) verifies dispatch wiring without injury; no natural damage, manual input or multiplayer claim.",
"Inherited native health updater runs by design; health equality assertion concerns original blood health, not every possible native UI side effect."
],
"approved": true,
"manifest_sha256": "54d993dc6516f6b962633386693f50d5610568ea62337a88b6f601420e60bacc",
"patch_sha256": "d5b18a1716fa31fae10e51db703441ed660467c2abc7ee825ae19f3ea7a5495d",
"logs": {
"green.log": "84c104970b68d9355726cf72b63ac726bf1e4ad6285c4ed66114519264125731",
"late-update-mutation-red.log": "a89f6b30fb52ca00aa7e156a493c2af981461474aa3095382005469b5868f10d"
},
"menu_api": {
"archive": "/home/jakub/.local/share/Steam/steamapps/common/Arma Reforger/addons/core/data.pak",
"resource": "scripts/GameLib/generated/Menu/MenuManager.c",
"sha256": "88bd64762866406a8b8283f82f1f34deef1925244b3148ac88edb7d8d72c664e",
"signatures": {
"18": "proto external MenuBase FindMenuByPreset(ScriptMenuPresetEnum preset);",
"22": "proto external MenuBase GetTopMenu();",
"32": "proto external bool CloseMenu(MenuBase menu);"
},
"method": "Read exact installed PAK entry with parse_tree, decompressed and hashed in memory; no asset copied."
},
"final_cleanup_delta": "Primary CloseMenu accepted flag is set from the actual returned bool. If it refuses, Check fails and one-way Stop can make exactly one further request for the still-exact owned menu; no retries thereafter, no replacement menu touched. Focused persistent-refusal control asserts result -1 and exactly two total requests. Persistent native refusal stays failure, not completed cleanup.",
"mutation": "Late-update count-check omission compiled then runtime-failed the negative control; retained log hashed. Reviewer did not rerun."
}
@@ -0,0 +1,19 @@
check: /tmp/err-policy-182mkgob/check.cpp:156: int main(): Assertion `p.Tick(0)==-1' failed.
Traceback (most recent call last):
File "/tmp/erri-inventory-native-proposal/tests/test_native_inventory_hitzone.py", line 29, in <module>
run(r'''
~~~^^^^^
#include <cassert>
^^^^^^^^^^^^^^^^^^
...<45 lines>...
}
^
'''.replace('POINT',point).replace('PROBE',probe.replace('Probe(', 'Actual(')))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 14, in run
subprocess.run([str(p/'check')],check=True)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 578, in run
raise CalledProcessError(retcode, process.args,
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['/tmp/err-policy-182mkgob/check']' died with <Signals.SIGABRT: 6>.
@@ -0,0 +1,11 @@
{
"archive": "/home/jakub/.local/share/Steam/steamapps/common/Arma Reforger/addons/core/data.pak",
"resource": "scripts/GameLib/generated/Menu/MenuManager.c",
"sha256": "88bd64762866406a8b8283f82f1f34deef1925244b3148ac88edb7d8d72c664e",
"signatures": {
"18": "proto external MenuBase FindMenuByPreset(ScriptMenuPresetEnum preset);",
"22": "proto external MenuBase GetTopMenu();",
"32": "proto external bool CloseMenu(MenuBase menu);"
},
"method": "Read exact installed PAK entry with parse_tree, decompressed and hashed in memory; no asset copied."
}
@@ -0,0 +1,15 @@
{
"scope": "Single WORKBENCH-only Core inventory-hitzone diagnostic; fixed30s after initial admission, ordinary menu+InspectItem,7original containers, real one-argument blood invoker, native updater once/true, unchangedhealth, asynchronous exact-ownedmenu close and no lateupdates.",
"focused_test": "Actual probe Context/Tick/Stop/counters with doubled native UI/event boundaries green; omission of late-update count check compiles then runtime-fails negative control.",
"test_registration_needed": "tests/test_native_inventory_hitzone.py",
"native_execution": false,
"native_compilation": false,
"rendered_ui_qualified": false,
"limits": [
"No natural injury/treatment/manualinput/MP/FPS proof.",
"If primary CloseMenu refuses, Stop makes one bounded cleanup request for the same owned menu; persistent native refusal stays a failure and session cleanup remains runner-owned.",
"Invoker notification is deliberately synthetic; no health/damage methods invoked."
],
"runner": "--project core --smoke inventory-hitzone --rounds 1 --timeout 240 (existing disposable hidden/muted profile requirements retained)",
"no_production_adapter_or_mounted_source_edits": true
}
@@ -0,0 +1,29 @@
{
"files": {
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeInventoryHitZoneProbe.c": {
"baseline_sha256": null,
"proposal_sha256": "604eacdc66cd52bc8a0115862ee7884a8b0f83bdb50609397de671eacd476543",
"index_sha256": null
},
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c": {
"baseline_sha256": "e811e985048e07365569acde6b5f045d57e9bbf13927f85b74e6e347fd2ef571",
"proposal_sha256": "d4318ac4f8567afde4cb9f9546f6022ca74e5cabd689355ee75d19f2cde25060",
"index_sha256": "ec319b070bd915d0326b9be1fd3fbc7aabc58956982a2ec69eb24d023a651815"
},
"tools/headless_workbench.py": {
"baseline_sha256": "b0bbb87597fe5f116e8b4fd1d60d52983935d438d3e82b972c675991fddcc971",
"proposal_sha256": "7ffa38822cee1df4248ea027234823a51c2535a8ce74a9e1a9e7756ee1a72d09",
"index_sha256": "b82da94e227a45c87b8ad74cac55d1b48dfaed55b82a66fe867ca4f0e5d22190"
},
"tests/test_native_inventory_hitzone.py": {
"baseline_sha256": null,
"proposal_sha256": "bb67f3e2002661331b1f170955989df5bf30a60b48a294ff979bb6db335ca819",
"index_sha256": null
}
},
"patch_sha256": "d5b18a1716fa31fae10e51db703441ed660467c2abc7ee825ae19f3ea7a5495d",
"logs": {
"green.log": "84c104970b68d9355726cf72b63ac726bf1e4ad6285c4ed66114519264125731",
"late-update-mutation-red.log": "a89f6b30fb52ca00aa7e156a493c2af981461474aa3095382005469b5868f10d"
}
}