gate; supersedes CH round-1 item A)
The user's retail description matches the decomp exactly:
charge_jump @0x005281c0 has NO grounded check - it refuses only 0x49
(CanJump encumbrance) and 0x48 (fallen/crouch-family forward commands).
Pressing jump while airborne begins the powerbar and charges normally.
The 0x24 "You can't jump while in the air" comes exclusively from the
RELEASE path (ClientCombatSystem::DoJump @0x0056B110 ->
CMotionInterp::jump -> jump_is_allowed, whose airborne 0x24 our port
already carries test-pinned). A charge held through landing executes a
normal jump on the grounded release.
PlayerMovementController's input orchestration now mirrors
CommenceJump/DoJump:
- Press edge: ChargeJump() decides; a refused charge (0x48/0x49)
reports and never begins the bar (retail's jump_pending stays 0).
The invented airborne press-edge 0x24 report (CH user-gate round 1
item A - added when the press/release split was not yet known) is
deleted; CommenceJump's in-air fallback text is unreachable with a
faithful charge_jump.
- Hold: accumulates grounded OR airborne; leaving the ground mid-charge
no longer force-fires the jump.
- Release: fires jump(); an airborne release refuses 0x24 there.
Tests: the round-1 press-edge test is replaced by two release-semantics
tests (airborne release reports once; held-through-landing grounded
release jumps silently). Runtime 1,619, App 4,987/3, Core jump family
159.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>