fix(movement): remove unreferenced [0.25,3.0] clamp on local player's movSpd scale

CInstanceBase::SetMoveSpeed only guards moving_speed > 1100 -> 0; the local
player's set_server_speed() was additionally floor/ceil-clamping the scale to
an arbitrary [0.25, 3.0] band with no basis in the reference or in this
project's already-fixed remote-entity equivalent (EntityStore::motion_move_speed).
A heavy haste stack or slow debuff on the local player would silently diverge
from what everyone else sees. Removed the extra clamp; kept the moving_speed<=0
early-return guard against pre-spawn/malformed values.

audit: movement.keyboard.motion/server-speed-scale-clamp closed with reference
citation, regression test, and full related-suite pass; contract stays PARTIAL.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-09-22 16:31:17 +09:00
co-authored by Claude Sonnet 5
parent a4ac48db24
commit c5c183da37
6 changed files with 120 additions and 12 deletions
+17
View File
@@ -196,6 +196,23 @@ func _init() -> void:
pc._input(_key(KEY_A, false))
pc.stop()
# CInstanceBase::SetMoveSpeed(UINT uMovSpd) applies uMovSpd/100.0f with no
# lower/upper clamp besides the >1100 -> 0 (frozen) guard; a haste stack or a
# heavy slow debuff must scale local prediction exactly like it already
# scales remote actors in EntityStore::motion_move_speed.
pc.set_server_speed(10)
_ck(is_equal_approx(pc.server_speed_scale, 0.1),
"set_server_speed is unclamped below the old 0.25 floor")
pc.set_server_speed(500)
_ck(is_equal_approx(pc.server_speed_scale, 5.0),
"set_server_speed is unclamped above the old 3.0 ceiling")
pc.set_server_speed(1200)
_ck(is_equal_approx(pc.server_speed_scale, 0.0),
"set_server_speed freezes to 0 past the 1100 SetMoveSpeed guard")
pc.set_server_speed(100)
_ck(is_equal_approx(pc.server_speed_scale, 1.0),
"set_server_speed keeps the 100 baseline at scale 1.0")
player.free()
pc.free()
cam.free()
+7 -1
View File
@@ -274,7 +274,13 @@ func set_server_speed(moving_speed: int) -> void:
# pre-spawn zero values from freezing local prediction.
if moving_speed <= 0:
return
server_speed_scale = clampf(float(moving_speed) / 100.0, 0.25, 3.0)
# CInstanceBase::SetMoveSpeed(UINT uMovSpd): only guard is uMovSpd > 1100 ->
# 0 (frozen walk pose, no root-motion advance); otherwise uMovSpd/100.0f is
# applied unclamped. EntityStore::motion_move_speed already mirrors this for
# remote actors; there is no reference basis for an arbitrary [0.25, 3.0]
# band on the local player, so a big haste stack or heavy slow debuff must
# scale local prediction the same way it scales everyone else's remote view.
server_speed_scale = 0.0 if moving_speed > 1100 else float(moving_speed) / 100.0
func set_input_surfaces(cursor: Node, ui: Node = null, ground: Node = null,
cancel_fishing_cb := Callable(), ground_cancel_fishing_cb := Callable()) -> void: