Files
EscapistsReintroduced/docs/prison-held-action-design.md
T

13 KiB
Raw Blame History

Proposed genuine held-F prison-lock proof

Design only; no held-F run or code change is established by this document. The next experiment is one real keyboard hold after independently accepted approach and alignment. It must not select an action, call an action method, change a door, move the player, alter input settings, or extend the original observation clock. A normal-input lock completion would establish this local route only, not multiplayer reliability or passage through the opened gate.

Native behavior that determines the proof

The installed scripts/Game/Interactions/SCR_InteractionHandlerComponent.c:67–92 listens to PerformAction DOWN/UP and sets its input latch. DoProcessInteraction at lines164–260 requires the selected action, current permission, and the previous selected action to agree. On the first eligible press it invokes native ChimeraCharacter.DoStartObjectAction; later frames advance GetActionProgress. The authored addons/core/Prefabs/ERR/PrisonDoor.et sets the lock duration to 4 seconds. The generated ScriptedUserAction.GetActionProgressScript normally adds timeSlice.

On completion, the handler calls the display's OnActionFinish(FINISHED), invokes native DoPerformObjectAction for a non-per-frame action, and immediately resets progress to zero and performing to false in the same frame. Thus a 100ms sampler need not ever observe progress equal to4. Neither zero progress nor disappearance of a progress binding alone proves success. Display completion is emitted before native action execution and is not an authoritative mission result.

If input, action, or permission becomes invalid while performing, the handler invokes DoCancelObjectAction, reports INTERRUPTED, and clears progress. A lost context also cancels the previous action and clears selection (OnPostFrame, lines795–819). The handler rechecks selectedAction.CanBePerformed(character) just before dispatch, because the filtered permission cache can be stale (line768). While performing it retains the last selected action; after completion selection and cached permission may change normally. Its end-of-frame input/previous-input bookkeeping prevents a completed action from simply restarting as another timed action without a fresh press. The proof must never send a second F-down to compensate for a dropped or interrupted first attempt.

The source exposes OnActionStart, OnActionCanceled, OnConfirmed, and OnRejected action callbacks; no separately named interactionPerformed event was found in the inspected installed interaction/generated action source. Do not fabricate such a callback marker from the local progress reset. The generated character action calls are native declarations, not proof of their internal timing or remote execution. The first design uses the existing raw progress/phase/door observations. Additional callback instrumentation, if later needed, would require its own narrowly gated, read-only design and unchanged superclass execution.

The successor ERR_UnlockPrisonAction.PerformAction first calls ERR_GameMode.UnlockPrison, whose server/current-roster/alive-conscious/faction/range/PRISON checks guard the transition to RADIO_SEARCH. Only after a successful transition does it call the exact owner's BaseDoorComponent.UseDoorAction. Gate control and physical state are distinct native getters. A wanted open state may precede actual physical motion; the generated API provides no fixed opening latency. A phase transition alone therefore does not establish a physically open or passable gate.

Explicit observation extension, not a new lifetime

Add a separately explicit held-action option requiring the already enabled input, gate, look, approach and alignment options and their identical nonce. Default observers and earlier proof variants retain their current behavior. Initial admission and gate binding must still occur in PRISON.

Boundary Required opt-in change
ERR_OrdinaryInputObserver.Valid Permit only the pinned run's monotonic PRISON(1) → RADIO_SEARCH(2) transition. Retain original mode/world/controller/body/roster-life/account, conscious on-foot state, menu and cleanup checks. No rebind, new start time, or admission.
ERR_OrdinaryLookObserver.Context The same narrowly gated phase transition; retain the exact original native player camera and current-camera checks. Never accept a replacement view to finish the proof.
ERR_OrdinaryGateObserver It already permits phases1 and2 after a strictly phase1 BindGate. Preserve all exact gate/manager/action/context/handler identities and gate-loss refusal. The held variant must additionally reject reversal to phase1 or any later phase.
Live snapshot adapter Add a held-specific consumer: the current approach adapter deliberately rejects pressed/performing/progress anywhere in its span. Do not weaken that adapter or the completed approach/alignment predicates. Preserve all intervening raw samples and their original receipt times.
Independent validator Validate approach/alignment only over their committed reference spans, then validate a separate held span and a bounded terminal phase2 span. Existing validate_gate_geometry deliberately requires phase1 and unchanged closed-door geometry; do not relax it globally.

The native QUEUED start, System.GetTickCount ordering, original 45-second / 450-sample limit and cancellation callbacks remain unchanged. Phase2 does not restart or prolong any observer. Phase2 at initial bind, phase reversal, another phase, world/restart/life/body/camera changes or a menu cause terminal refusal. A successful phase transition must not be mislabeled original-admission-lost solely because the current input/look observers still require PRISON.

Before completion retain the original closed-door/geometry bounds. After the accepted phase transition retain exact object identities and finite observations, but permit the same door's native control/state and attached context/forward geometry to change as it opens. Do not require a moving door's handle to remain at its closed position, and do not adopt a replacement context or gate. Keep the actor stationary inside the prison, so the separate physical-exit fallback cannot account for progress.

Admission, one hold, and fail-closed release

Before sending anything, independently accept the completed approach and alignment from the same raw session. Require two consecutive fresh observations, separated by at least100ms, selecting the exact pinned lock and context with cached permission and progressBound=true, duration4, performing=false, progress=0 and pressed=0. Require the same stopped body within0.05m, neutral movement/turn input, unchanged closed gate, no menu, and the current private mapped/focused owned window. No mouse, wheel, movement, Tab or other keys are available during this stage.

Compute remaining time conservatively from both the immutable original native QUEUED lifetime and its frozen host-clock correspondence, including existing receipt-age allowance. Require at least6 seconds left immediately before F-down, after ownership/idle checks. Do not use the requested sleep duration or a newly read sample receipt to renew the deadline. If insufficient, record held-action-not-started: insufficient-original-budget; send no F.

The supervisor may grant a 5-second F-only held-key lease, beginning when that exact press is marked uncertain before the native XTest request. The existing W/other-key 1.5-second lease and all private display/socket/PID/focus/window checks remain unchanged. Unknown keys or malformed lease requests cannot obtain the longer bound. The overall original45-second deadline can only shorten the F lease. Reserve time for the guarded key-up and confirmed keymap roundtrip; start release before the hard deadline, never after a blind five-second sleep. Slow simulation or delayed delivery may make completion impossible within this budget; that is a failed attempt, not a reason to increase it.

Send one F-down. Observe bound native performing/progress samples from the exact lock, with positive advancing progress and native pressed acknowledgement. Before native completion, lost permission/selection/context, a progress reset after demonstrated progress, body movement, stale samples, focus/identity loss or any deadline is a failure. Polling must retain intermediate samples rather than accepting only the latest state. Allow the normal completion-frame progress reset when it is linked to the first phase1→2 result; do not require an exactly4.0 sample or four seconds of host sleep as a substitute for native action progress.

Release F promptly on observed completion or any failure. The intended trace contains one down and one up. The existing finally path must still attempt a paired release for an uncertain press on the same freshly proven connection; an extra recorded key-up is allowed only as release recovery, never another down or action retry. Verify idle via bounded native keymap roundtrip and native pressed=0 when the observer remains valid. If authority is lost, do not redirect input or force focus: mark release uncertain, terminate only the owned wrapped child through the existing supervisor, and let parent containment cleanup run. Retain the primary failure and separate release/supervision errors.

A complete proof requires genuine bound progress, one monotonic mission transition, the original door's nonzero control response and separately observed physical state change, stable original actor, and confirmed key release before the original expiry. After transition it may be normal for the selected action, cached permission and progress binding to disappear. Observe the door only for the time still available; no fixed native opening time is assumed. If physical motion is not observed, distinguish unlock observed; gate-motion unverified from a complete result. Do not infer passable width, send W through the gate, or report the full escape loop.

Record all actual press/release timestamps, uncertain attempts, first/last and progress/transition/door/release sample references, immutable deadlines, raw nonce/session/inode bindings and helper/source hashes. An independent validator must resolve references against raw native records and reject early reset, phase reversal, extra press, missing native input, unbound progress, unrelated door changes, stale evidence and uncertain release. Helper completion flags alone cannot qualify the run.

Available time from the real approach

In ordinary session logs_2026-09-19_19-17-50, nonce 1e85ace87d88491dbf311c2512e50edb, QUEUED was native real30028ms and the accepted approach ended at sample286, real62393ms. The unchanged expiry is75028ms: 12.635 seconds remained at that sample. The helper's approach took27.417 seconds after its own stage start, used nine W pairs and stopped with selected/context/cached permission allfalse. The actual final camera was <6092.38,212.922,7155.72>; the handle remained <6092.77,213.226,7154>. Proximity is not evidence that F can start.

An alignment stage allowed up to8 seconds can consume too much of those12.635 seconds: even without other overhead its maximum leaves4.635 seconds, below the6-second admission minimum. A held attempt is therefore conditional on actual alignment completion and fresh remaining-time checks, not guaranteed by the configured maxima. Upcoming alignment timing/selection was unknown when this design was prepared. No increase to45 seconds, reset at alignment, shortened action duration, synthetic completion or relaxed settling is proposed to obtain a pass.

Networking conclusion

The installed generated UserAction/ScriptedUserAction.c defaults HasLocalEffectOnlyScript() tofalse and CanBroadcastScript() totrue. Its CheckOnServerFirstScript() documentation explicitly says false does not mean actions are unverified on the server. BaseUserAction documents native action-data transmission. The successor lock overrides none of those defaults and deliberately guards its mutation on the server. This source review does not establish a networking defect in PerformAction. Native door replication/action dispatch details and genuine remote-client behavior still require their own evidence; changing broadcast flags merely to make this local input proof pass is unjustified.

Primary evidence: installed extracted scripts/Game/Interactions/SCR_InteractionHandlerComponent.c, Interactions/Display/SCR_ActionMenuInteractionDisplay.c, generated/UserAction/{BaseUserAction,ScriptedUserAction}.c, generated/Character/ChimeraCharacter.c, generated/Components/BaseDoorComponent.c; successor ERR_Actions.c, ERR_GameMode.c, the three ordinary observers, ordinary_gate_evidence.py, and the preserved19:17:50 console/input-proof artifacts. This audit sent no input, opened no display connection, and changed no executable source.