Files
EscapistsReintroduced/docs/ai-equipment-migration.md
T

8.1 KiB

Enemy skill and finite startup equipment migration

Adapted from independently authored, user-authorized AI code. Original files remain read-only; no original Escapists helpers, protected-derived EAI_GroupLookup, patched prefabs or asset bytes are imported.

Owned source SHA-256 Reused behavior
escapists-ai/Scripts/Game/EscapistsAI/EAI_SniperOptics.c 96a302da44fdb9207c12cc1c9c93aad38eb510cb0cf9befd800f60a2945b08e8 Preserve mounted magnified optics, randomized native-compatible attachment fitting, five startup checks and no replacement after removal
escapists-ai/Scripts/Game/EscapistsAI/EAI_StingerEquipment.c b8ce09f2d3ed61e58beadc1f158daed6eceb17b08243f7979b46d8c27e917695 One startup selection, native weapon-proxy insertion, five checks, no replacement after firing/dropping/looting
escapists-ai/Scripts/Game/EscapistsAI/EAI_AIResponseSystem.c b3e1263e986837744a70fbaedaa6e57afae7f2981a21211d3a2066e2c63ac84d First combat-component section's Expert skill clamp and native reset handling only; no convoy spawning, original faction/group hooks or other sections imported
escapists-ai/Scripts/Game/EscapistsAI/EAI_AIConfig.c 8c320d3163d443b43e50547734702484c8ad51f2cffe88cf6dfd33aaf339ec01 stingerChanceOneIn, default 15 and valid range 0..10000

The successor HQ owns ERR_EnemyEquipment. Registration supplies exact physical groups; two seconds after group registration, at most five scans discover initialized members. Entries retain exact actor/group identity, with 128 group and 2048 actor limits. Per-actor inventory submission is finite. Accepted pending operations are never repeated; unresolved completion at the fifth check ends processing permanently for that actor. Explicit failure may retry before the fifth check. A success callback ends issuance even if the item was dropped before it could be observed. A late callback after Stop cannot restart this service, although native accepted insertion itself is not cancellable through this API.

The exact allowed launcher is {3DF204EEE0534EF2}Prefabs/Weapons/Launchers/FIM92_Stinger/Launcher_FIM92_Stinger.et, owned by WCS Armaments. The successor requests insertion into PURPOSE_WEAPON_PROXY, preserving native slot constraints and other equipment. It creates no loose ammunition or replenishment; actual prefab loadout and operational AI firing need native validation.

Expert minimum binds only after initialization to an eligible, living, nonplayer member of a registered military enemy group in the active successor mission. Native SetAISkill and ResetAISkill enforce that scoped floor; higher skills are preserved. No perception/target knowledge is changed. Unregistration or Stop clears the binding and restores the skill captured at first binding. Convoy-gunner Cylon specialization is not implemented here because no production convoy-gunner registration exists yet.

Settings migrate through the existing additive-default reader and import helper. Existing valid ten-key/six-key files preserve their values and obtain 15 for missing stingerChanceOneIn; explicitly present malformed values remain invalid. /esc hq stinger show|set N changes only actors that have not rolled yet: 0 disables, 1 selects every eligible actor, 2..10000 selects one in N. The existing ten native menu fields are preserved; this extra key is available through text commands. Unsupported convoy/simulation/start keys are still reported as deferred by the importer, never exposed as working settings.

tests/test_enemy_equipment.py executes actual eligibility, callback, insertion, scoped skill and coordinator bodies against native API doubles. It covers pending nonduplication, success after item removal, finite rejected/failed requests, timeout quarantine, capture, absence, wrong mode/faction/player/client/editor, native resets, higher skills, restoration, delayed group membership, registration dedupe, terminal stop and bounded scans. These are policy regressions, not native inventory or multiplayer proof. Expanded external runtime qualification remains separate.

Magnified optics

ERR_EnemyOptics belongs to each existing equipment entry's exact actor/group and uses the same three-second startup cadence independently of Stinger completion. Its first eligible physical weapon roster is retained, with at most eight weapons; later replacement rifles are never equipped. Rifle, sniper-rifle and machine-gun types qualify. Existing magnified optics are detected through the three native optics components on weapon children, attached sights and attachment slots. Inspection is bounded to 128 visited entities, four child levels and 16 attachment/storage slots; incomplete inspection refuses a grant. Occupied mounts remain occupied, including nonmagnified sights.

The seven original candidate path/GUID pairs were independently checked against installed resource databases: vanilla PSO-1, ART II and 4x20; RHS PSO-1M2, 1P21, M8541 and 1P78. Their exact catalog entries belong in vanilla-resources.json and external-addons.json; no new dependency or external asset bytes are introduced. Candidates are drawn without replacement, and native CanInsertResourceInStorage must accept the same concrete free slot passed to TrySpawnPrefabToStorage. This does not override mounting compatibility or guarantee that every rifle accepts a scope.

At most one native submission per original rifle per check is allowed. Explicit failure permits another candidate/slot before the fifth check; that final check only observes. An accepted unknown operation is never repeated, including after its deadline or Stop. A successful callback is terminal even if the optic is removed before physical observation. Ownership loss terminates processing, and Stop retains callback/tombstone state; the native API cannot cancel an insertion already accepted. No loose optics, replenishment, new actors or independent timer is added.

tests/test_enemy_optics.py executes the actual service with native API doubles: all three scope component kinds, nested adapters, occupied/compatible mounts, original-rifle transfer, actor ownership loss, success/failure ordering, accepted-operation quarantine, late callbacks, bounded checks and malformed hierarchy limits. tests/test_enemy_equipment.py additionally verifies real entry Stop propagation, exact actor/group binding, optics cadence after Stinger completion, unregistration and ownership-loss teardown. These are policy proofs. Native compilation and physical attachment validation are pending for this optics change; they do not follow from earlier Stinger or convoy evidence.

Native startup observation (2026-09-20, 05:09:06 run)

The archived full-addon native run compiled the optics service and executed it on ordinary mission/convoy equipment. Its rereintroduced-hq.log contains 59 terminal OPTICS records: six physical magnified optic preserved/confirmed and 53 startup deadlines without a confirmed compatible optic. The six confirmations occurred at world time 13.7 seconds. No explicit native optic insertion completed or unresolved-insertion quarantine record was emitted.

This demonstrates normal startup execution and detection of physical magnified optics, not successful new attachment insertion. The physical-presence check runs before the callback check and uses the same event for preexisting and newly fitted scopes; the journal does not record actor/rifle identity or whether a request preceded confirmation. The 53 deadlines likewise do not distinguish an incompatible mount from other unconfirmed startup outcomes. The preservation path performs no insertion when a scope is already observed; a separate before/after observation of the same rifle would be required to qualify a new native insertion. No additional fixture or resource manipulation was performed for this checkpoint.

The final full-addon checkpoint compiles all current optics, vehicle and diagnostic classes and completes 56 HQ-memory assertions with zero script/runtime failures. Four installed external localization errors remain. This does not add new optic-insertion or multiplayer evidence.