Compare commits

...
1 Commits
Author SHA1 Message Date
Brues e881e18720 Fire PLAYER_STARTED_MOVING for both-mouse-button run
Holding both mouse buttons to run forward never fired
PLAYER_STARTED_MOVING. Ghidra trace of the input button handler
(FUN_00514840) shows that gesture drives the forward move directly at
the movement layer (FUN_005103e0) and explicitly clears the autorun
bit on the both-button press — so it sets none of the
INPUT_FLAGS_MOVING_ANY bits the mover-detection reads. (The Offsets.h
comment claiming the both-button combo sets autorun was wrong;
corrected.)

Detect it from the bit combo instead: both INPUT_FLAG_MOUSELOOK (RMB)
and INPUT_FLAG_FREE_LOOK (LMB) held means the engine is mouse-steering
the character forward. ORed into `moving`. Composes cleanly with the
TURNING/LOOKING latches (unchanged).
2026-06-22 12:51:30 -05:00
2 changed files with 25 additions and 8 deletions
+13 -7
View File
@@ -3379,13 +3379,19 @@ enum Offsets {
// Bits 4-7 — WASD movement-key state. Each `MoveForwardStart`
// / `StrafeLeftStart` / etc. pushes one of these as the bit
// mask into the engine's button-press handler. Bit `0x1000` is
// the autorun-active flag (set by `ToggleAutoRun` and the
// both-mouse-buttons combo). `INPUT_FLAGS_MOVING_ANY` is the
// engine's own "is the user currently inputting translational
// movement" mask, used to drive `PLAYER_STARTED_MOVING` —
// matches modern's "STOPPED fires on key release, even
// mid-air" semantics because no physics/airborne bit is
// involved.
// the autorun-active flag (set by `ToggleAutoRun`).
// `INPUT_FLAGS_MOVING_ANY` is the engine's own "is the user
// currently inputting translational movement via keys/autorun"
// mask, used to drive `PLAYER_STARTED_MOVING` — matches modern's
// "STOPPED fires on key release, even mid-air" semantics because
// no physics/airborne bit is involved.
//
// NOTE: the "hold both mouse buttons to run forward" gesture is
// NOT in this mask. The button handler (`FUN_00514840`) drives
// that forward move directly via `FUN_005103e0` and explicitly
// *clears* the autorun bit when both buttons go down. Detect it
// from `INPUT_FLAG_MOUSELOOK & INPUT_FLAG_FREE_LOOK` both held
// instead — see `Player::InputEvents`.
INPUT_FLAG_MOVE_FORWARD = 0x10,
INPUT_FLAG_MOVE_BACKWARD = 0x20,
INPUT_FLAG_STRAFE_LEFT = 0x40,
+12 -1
View File
@@ -111,10 +111,21 @@ void OnWorldTick() {
const uint32_t flags = *reinterpret_cast<const uint32_t *>(
ctrl + Offsets::OFF_UI_INPUT_FLAGS);
const bool moving = (flags & Offsets::INPUT_FLAGS_MOVING_ANY) != 0;
const bool freeLookHeld = (flags & Offsets::INPUT_FLAG_FREE_LOOK) != 0;
const bool mouselookHeld = (flags & Offsets::INPUT_FLAG_MOUSELOOK) != 0;
// MOVING — translational input. The WASD / autorun keys set the
// INPUT_FLAGS_MOVING_ANY bits directly. The "hold both mouse
// buttons to run forward" gesture does NOT: the engine drives that
// forward move at the movement layer (FUN_005103e0 from the button
// handler) and actually *clears* the autorun bit on the both-button
// press, so no MOVING_ANY bit is ever set. Detect it from the
// bit combo instead — both mouselook (RMB) and free-look (LMB)
// held means the engine is mouse-steering the character forward.
const bool mouseSteerMoving = mouselookHeld && freeLookHeld;
const bool moving =
(flags & Offsets::INPUT_FLAGS_MOVING_ANY) != 0 || mouseSteerMoving;
// TURNING — latched bit-AND-rotation signal:
// STARTED fires when mouselook bit is held AND the body yaw
// changes (the first actual drag after pressing RMB).