Files
EscapistsReintroduced/docs/prison-input-proof-plan.md
jakub cab998fb64 Combine Workshop addon and fix prison startup
Merge owned systems into one addon while preserving resource identities. Gate player admission on the replicated prison scene, restore the original framed door, and hold enemy AI until escape. Correct scenario branding and author metadata, include publishing assets, and retain regression and native verification evidence.
2026-09-20 16:42:52 +02:00

6.4 KiB
Raw Permalink Blame History

Proposed normal-input prison escape proof

Implementation guidance only; this route and lock-picking input sequence have not been executed. Extend the existing explicitly enabled private-display experiment. Use actual mouse/keyboard input and read-only native observations. Do not teleport, set transforms/velocity, select actions through script, invoke action completion, shorten duration, change controls, or remove obstacles.

Source and starting evidence

The ordinary run game-2026-09-19-180423-inventory-ready/console.log.txt, line 490, records the original player at <6088.5,211.389,7158.5> with neutral inputs and zero velocity. Its nonce is a75280fda4494a0ca7b14a693cf310e9; this is historical starting-position evidence, never authorization for a later run.

ERR_SpawnPlacement.c, Prison, searches the four inner lattice positions first; its first candidate is prison centre minus 1.5 in X/Z. ERR_SpawnLogic.c, DoSpawn_S, constructs SCR_FreeSpawnData without angles. The installed vanilla scripts/Game/Respawn/RequestHandling/Implementation/FreeSpawn/SCR_FreeSpawnData.c:27 defaults angles to 0 0 0. Expected initial facing is +Z, but the experiment must read actual pose/view orientation before movement and refuse a different starting configuration rather than assume it.

EveronSites.conf places the prison at X/Z 6090/7160. Prison.et places the gate hinge at local 0,-0.1,-6, scale 1.5. PrisonDoor.et inherits the concrete vanilla metal gate's handle context offset 1.845,1.255,0, giving an expected world handle near (6092.7675, siteY+1.7825, 7154). This is approximately 6.20 m horizontally from the recorded spawn. Native UserActionContext.GetOrigin/GetRadius/GetTransformationWorld must confirm the actual evaluated geometry; do not assume how scale affects the configured radius of 2.

Minimal candidate route and inputs

  1. With inventory closed and the original player stationary, make a tiny bounded relative mouse movement. Require native CharacterTurnRight/CharacterTurnUp and measured view-direction change before enabling navigation. Mouse sensitivity and private XTest forwarding into native relative input are unproven; do not substitute an absolute cursor warp or camera write.
  2. Turn toward candidate interior approach point X/Z 6092/7155.5, roughly 4.61 m from the recorded spawn (initial horizontal heading approximately 131°). Use short W pulses, releasing and checking actual movement between them. Correct heading using small mouse movements. This point lies inside the authored walls and about 1.69 m horizontally from the expected handle.
  3. Stop and aim at the observed handle context. Require the selected action to be the gate's actual ERR_UnlockPrisonAction, named “Pick prison lock.” If disabled “Open” is selected, allow a bounded wheel step and reobserve selection; never call SetSelectedAction or override context collection.
  4. Hold F only while the exact lock/action/context/body remains valid. Require native progress through the authored four-second duration, then release F. Before any exit movement, observe PRISON → RADIO_SEARCH while the player remains inside, with the same intact gate moving open. This separates lock-picking proof from the alternate boundary-crossing progression path.
  5. After the gate is visibly/physically open, use heading-corrected W pulses through the candidate opening centre near 6091.5/7154 to 6091.5/7151. Observe continuous physical crossing south of 7152, then neutral input. Total proposed movement is about 9 m. This is a geometry-derived route, not a native clearance guarantee; collision/no progress must refuse the experiment.

Installed bindings are in Configs/System/chimeraInputCommon.conf: W → CharacterForward (255), relative mouse Y/X → CharacterTurnUp/Right (346/380), held F → PerformAction (2942), wheel ± → SelectAction in ActionMenuContext (8005). The separate CharacterAction F-down binding is not proof of a held interaction. Additional operations are therefore relative mouse, F, and possibly wheel; A/D are unnecessary if turning works.

Required observations and bounds

Keep the existing exact private-display/window/focus/process/prefix ownership guards before every event. Pin the new run's controller, account, body and gate. Abort on changed identity, death/unconsciousness, focus loss, gate destruction, unexpected phase/action/context, non-neutral prior input, blocked motion or exhausted budget. Do not alter guards or enemy balance to obtain a pass.

Read native BaseInteractionHandlerComponent.GetSelectedAction and ExtBaseInteractionHandlerComponent.GetCurrentContext/GetFilteredActions; confirm the original gate owns the lock, the context is in reach, native permission is true and GetActionDuration()==4. During F, record native PerformAction input and actual SCR_InteractionHandlerComponent.m_fCurrentProgress/m_bIsPerforming through a narrowly gated read-only accessor. action.GetActionProgress(0,0) does not return accumulated progress. The installed handler accumulates progress and invokes normal completion itself (scripts/Game/Interactions/SCR_InteractionHandlerComponent.c:164–239). Require multiple increasing native progress observations, original gate control-value change, phase transition, and subsequent neutral F/movement samples.

Retain existing short W/Tab safety limits. The current 1.5-second pending-key limit cannot accommodate the four-second lock: introduce an explicit F-only maximum of 5 seconds, conditional on fresh matching action observations, without extending any other key's lease. Use at most 250 ms per movement pulse, 12 m cumulative displacement and one attempt; budget at most 40 seconds after a fresh stationary READY, inside the observer's existing 45-second window. Reject insufficient remaining time. Release only while the original target remains proven; uncertain release must fail and trigger existing owned-session cleanup.

Capture approach/selected action, genuine progress and outside state. Preserve raw errors and all refused attempts. Even a pass qualifies one local normal-input prison exit only—not a full escape, remote multiplayer behavior, or performance improvement.