docs(R3-W0): ambiguity pins A1-A10 — all textually resolved, adversarially verified

Workflow-produced pin pass over the R3 decomp extraction (3 independent
raw re-readers + adversarial refuters on the two load-bearing pins +
synthesis). No pin was refuted; none blocks on cdb.

Headlines:
- A1: motion_allows_jump 0x005279e0 is a BLOCKLIST (0 = pass, 0x48 =
  blocked) — the BN extraction's whitelist annotation was inverted
  (corrected in-place in §3a + §10). Retail blocks FALLEN 0x40000008
  and PASSES Falling 0x40000015; ACE mis-transcribed the exact-id term
  as Falling (one-off slip — ACE's own charge gates use Fallen).
  Definitive literal-uint blocklist table recorded.
- A3: the raw-vs-interpreted dual-dispatch gate is IsThePlayer (vtable
  slot +0x14, bound via the ACCWeenieObject vftable dump @0x007e3ea0),
  NOT ACE's IsCreature — in all four functions. Anti-artifact proof:
  HitGround/LeaveGround nearby call the +0x2c IsCreature slot, so BN
  distinguishes the slots locally. Copying ACE's gate would send
  remotes down apply_raw_movement against an empty raw state.
- A4: MovementParameters absolute-mask table pinned from acclient.h's
  own bitfield struct; retail ctor default 0x1EE0F has can_charge
  CLEAR (ACE sets it true) and walk_run_threshold 15.0 (ACE 1.0).
- A5/A6: both jump-velocity epsilons are 0.000199999995f (acdream's
  0.001 must change); get_leave_ground_velocity's fallback matrix is
  GLOBAL→LOCAL (index-pattern match against Frame::globaltolocalvec).
- A10: definitive error-code table from an exhaustive return-site
  sweep, incl. a second 0x24 site (DoInterpretedMotion action-class
  contact block) absent from the plan row.
- Adjacent: move_to_interpreted_state's apply_current_movement arg2 is
  a garbled allowJump = (motion_allows_jump(old fwd) == 0) — polarity
  trap for W-commits.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-02 21:24:46 +02:00
parent a6235a36f5
commit cd0289bea2
2 changed files with 309 additions and 25 deletions

View file

@ -402,17 +402,22 @@ that interpreted/remote commands skip.
005279e0 }
```
Cleaned: returns `0x48` (nonzero = "jump is currently allowed given this in-flight
motion id") for a specific whitelist of motion-id ranges, else `0` (disallowed):
- `arg2 in [0x1000006f, 0x10000078]` (movement/locomotion range 1) — allowed.
- `arg2 in [0x10000128, 0x10000131]` — allowed.
- `arg2 == 0x40000008` — allowed.
- `arg2 == 0x40000016` through `0x40000018` inclusive — allowed (falls through the
`else if` since neither branch rejects it; note `< 0x40000016` is the else-if guard,
so `0x40000016..0x40000018` skip both inner branches and hit `return 0x48` directly).
- `arg2 in [0x4000001e, 0x40000039]` — allowed.
- `arg2 in [0x41000012, 0x41000014]` — allowed (jump-charge stance ids).
- everything else outside `(0x40000018, 0x41000014]` range or the whitelisted holes → `0`.
Cleaned **[polarity corrected per W0-pins A1 — the original note here was inverted]**:
returns `0x48` = jump BLOCKED ("YouCantJumpFromThisPosition"-class error code) for a
specific **blocklist** of motion-id ranges, else `0` = jump allowed (pass). Callers
treat nonzero as the error (`jump_is_allowed` @305541: `if (eax_7 != 0) return eax_7;`;
`jump` 0x00528780 executes only when the chain returns 0). Blocked set:
- `arg2 in [0x1000006f, 0x10000078]` (MagicPowerUp01..MagicPowerUp10) — BLOCKED.
- `arg2 in [0x10000128, 0x10000131]` (TripleThrustLow..MagicPowerUp07Purple) — BLOCKED.
- `arg2 == 0x40000008` (**Fallen** — NOT Falling; ACE mis-transcribed this as Falling) — BLOCKED.
- `arg2 == 0x40000016` through `0x40000018` inclusive (Reload/Unload/Pickup) — BLOCKED
(falls through the `else if` since neither branch passes it; note `< 0x40000016` is
the else-if guard, so `0x40000016..0x40000018` skip both inner branches and hit
`return 0x48` directly).
- `arg2 in [0x4000001e, 0x40000039]` (AimLevel..MagicPray) — BLOCKED.
- `arg2 in [0x41000012, 0x41000014]` (Crouch/Sitting/Sleeping) — BLOCKED.
- everything else → `0` (pass), including **Falling `0x40000015`**, Ready `0x41000003`,
Dead `0x40000011`, and all ids > `0x41000014` (turns etc.).
This is the "can retail let you jump given the motion currently applying" check — used
by `StopCompletely`, `DoInterpretedMotion`, `move_to_interpreted_state` to compute the
@ -435,12 +440,12 @@ by `StopCompletely`, `DoInterpretedMotion`, `move_to_interpreted_state` to compu
00527a50 }
```
Cleaned: `0x49` if the weenie's `CanJump(jump_extent)` virtual rejects the current
charge amount (e.g. stamina/burden gate). Otherwise: allowed (`0x48`) only if the
**current interpreted forward_command** is either exactly `0x40000008` OR strictly
inside `(0x41000011, 0x41000014]` (i.e. already mid-jump-charge motion ids
`0x41000012..0x41000014`); anything else → `0` (not allowed to *start* charging a jump
from this forward-motion state).
Cleaned **[polarity corrected per W0-pins A1]**: `0x49` if the weenie's
`CanJump(jump_extent)` virtual rejects the current charge amount (e.g. stamina/burden
gate). `0x48` = charge BLOCKED if the **current interpreted forward_command** is either
exactly `0x40000008` (Fallen — prone) OR strictly inside `(0x41000011, 0x41000014]`
(Crouch/Sitting/Sleeping `0x41000012..0x41000014`); anything else → `0` = charge
allowed (pass).
### 3c. `CMotionInterp::get_jump_v_z``00527aa0` @ line 304953
@ -561,10 +566,10 @@ Cleaned flow: compute the leave-ground (jump) launch velocity vector.
005281c0 }
```
Cleaned: `0x49` if `CanJump` virtual rejects the current charge. `0x48` ("already
charging") if `forward_command` is already `0x40000008` or in `[0x41000012,0x41000014]`
(no-op re-entry guard — mirrors `jump_charge_is_allowed`'s allowed set but this
function is the "you're already there" early-out, not the gate). Otherwise:
Cleaned **[polarity corrected per W0-pins A1]**: `0x49` if `CanJump` virtual rejects
the current charge. `0x48` = charge BLOCKED if `forward_command` is `0x40000008`
(Fallen) or in `[0x41000012,0x41000014]` (Crouch/Sitting/Sleeping) — the same blocked
set as `jump_charge_is_allowed`'s gate. Otherwise:
`standing_longjump = 1` **iff** the physics object is currently grounded
(`transient_state` bits `0x1` AND `0x2` both set — matches `CPhysicsObj::on_ground`,
§3g) AND the mover is perfectly idle (`forward_command == 0x41000003 /*none*/`,
@ -901,8 +906,8 @@ forward/sidestep/turn commands to "none" (`forward_command = 0x41000003`,
`forward_speed = 1.0`, `sidestep_command = turn_command = 0`), call
`CPhysicsObj::StopCompletely_Internal` (the actual physics-level full stop — outside
CMotionInterp), then unconditionally enqueue a `MotionNode{0, 0x41000003, eax_2}` onto
`pending_motions` (this is the ONLY caller that passes the **precomputed** jump-allowed
flag as the queued node's `jump_error_code`, rather than recomputing after applying the
`pending_motions` (this is the ONLY caller that passes the **precomputed** jump-error
code (0 = allowed) as the queued node's `jump_error_code`, rather than recomputing after applying the
new motion — note the semantic quirk: `eax_2` was computed from the OLD
`forward_command` value, before the overwrite two lines later). If the physics object
has no cell (detached / not in world), also strip link animations. Always returns `0`
@ -1680,8 +1685,10 @@ only as confirmation that `set_hold_run`'s two callers exist and roughly where.
bit `0x400` set — `jump_is_allowed`), `0x3f`/`0x40`/`0x41`/`0x42` (combat-stance
jump-charge rejections, `DoMotion`), `0x45` (action queue depth ≥ 6, `DoMotion`),
`0x47` (bad `MovementStruct.type`, OR `IsFullyConstrained`, OR
`JumpStaminaCost` failure), `0x48` ("jump currently allowed" success sentinel from
`motion_allows_jump`/`jump_charge_is_allowed`/`charge_jump`'s early-out), `0x49`
`JumpStaminaCost` failure), `0x48` (jump BLOCKED by the current motion/position —
the blocklist reject from `motion_allows_jump`/`jump_charge_is_allowed`/
`charge_jump`; **NOT a success sentinel** — 0 is the success/pass value across the
whole jump-gate family, per W0-pins A1), `0x49`
(`CanJump` virtual rejected the charge — stamina/burden gate).
- `0.000199999995f` (~0.0002) — the epsilon used throughout for "is this velocity
component effectively zero" (`get_jump_v_z`, `get_leave_ground_velocity` x3).