Repository navigation
[WONTFIX?] Blend the player upper body by speed like classic NEOTOKYO - #2240
Draft
sunzenshen wants to merge 2 commits into
Draft
sunzenshen wants to merge 2 commits into
sunzenshen wants to merge 2 commits into
Conversation
neo plays the walk upper body at full weight from the first 0.5 u/s of movement, so a player who drifts, peeks or eases to a stop bobs the torso at the 0.73 s walk loop instead of the 2 s idle breathing, with a 0.2 s crossfade at each start and stop. Classic NEOTOKYO, like the 2006 SDK player anim state it is built on, always plays the idle upper body and blends the walk, sprint or crouch walk upper body over it at 2D speed / 100, 250 or 85 u/s. Do the same with a second pair of aim layers and its own sequence transitioner.
A player who stops in one frame (a wall, or releasing walk) dropped the walk torso from near full weight to zero at once, a visible snap that the old 0.2 s crossfade between the torso sequences used to hide. Classic NT snaps here too; fade the last moving pose out over the same 0.2 s instead. A normal friction stop is slower than the fade, so the speed blend is unchanged there.
Contributor
Author
sunzenshen
marked this pull request as ready for review
October 15, 2026 05:26
This was referenced Oct 15, 2026
sunzenshen
marked this pull request as draft
October 15, 2026 07:01
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Description
Case 2: tiny movements swap the torso to the walk pose.
Review page: exported review page (Dropbox) · live review page (opening it lets you request access with your email or Claude account).
A player who moves slowly (drifting, peeking, easing to a stop) bobs their torso at the full walk rate in neo, where classic NEOTOKYO keeps the idle breathing torso and only brings the walk in as speed rises. This PR blends the upper body by speed the way classic does.
In neo the upper-body aim layer plays the sequence of the current main activity at full weight, so from the first 0.5 u/s of movement the torso switches to
Walk_Upper_<weapon>(a 0.73 s loop) instead ofIdle_Upper_<weapon>(2 s), with a 0.2 s crossfade at every start and stop. Classic NEOTOKYO's player anim state is the 2006 SDK template (CBasePlayerAnimStatewithCSDKPlayerAnimState's top speeds): it always plays the idle upper body and blends the walk, sprint or crouch walk upper body over it at a weight of 2D speed / top speed, with top speeds of 100 u/s walking, 250 sprinting and 85 crouched (ANIM_TOPSPEED_*insdk_playeranimstate.cpp, and the same three constants in classic'sclient.dll). A walker at 30 u/s shows 70 % idle torso; a sprinter at about 205 u/s keeps 18 % idle.The change, in
CMultiPlayerAnimState(shared, NEO block only):UpdateAimSequenceLayersnow honors itsbForceIdleargument, so the existing aim pair (GESTURE_SLOT_AIM/AIM2) always plays the idle or crouch idle upper body, as its one caller already asks for.GESTURE_SLOT_AIM_MOVE/AIM_MOVE2, with its own sequence transitioner, plays the walk, run or crouch walk upper body atmin(speed2D / top speed, 1)while walking, sprinting or crouch walking; the idle pair takes the rest of the weight.Leg animation, the main activity choice and the idle torso of a standing player are unchanged. Players are animated client-side (layers are not networked); the server runs the same shared code for its hitbox layers, so both stay in step.
How to test
thirdperson, then tap a movement key briefly or walk slowly: the torso keeps the slow idle motion and the walk bob grows with speed, instead of switching to the full walk bob at once.Results
Logged per frame with a temporary client-side logger of the player's anim layers (not part of this PR), on the same scripted session in both games:
nt_rise_ctg, Assault with ZR68C, listen server, thirdperson in neo; stand, walk, peek, run, short taps, sprint, crouch walk. Classic NEOTOKYO logged withcl_showanimstate(AnimStateClient.log). neo: Release client builds of master (f426c22) and this PR. "walk torso" = share of upper-body weight on the walk/run/crouch walk sequences; "off model" = mean distance of that share from the 2006 SDK blendmin(speed2D / top speed, 1).Bin means depend on how the frames spread inside each bin, so the "off model" column is the per-frame comparison: classic follows the SDK blend exactly, this PR follows it within 0.02 (the 0.5-10 bin holds the fade-out frames after abrupt stops), master does not. Frames at 0.5-50 u/s with the torso at least 0.9 walk: classic 0 of 126, master 35 of 52, this PR 0 of 182. Largest one-frame change of the walk torso share while slowing down: classic 0.96 (abrupt stops), master 0.08, this PR 0.22 (at about 30 fps).
Risk
Two more animation overlays per player on client and server (11 of the engine's 15). Gesture slot indices after the aim slots shift by two; nothing addresses them by number.
How this was compared
The code came first: NT;RE's player animation code was read against the 2006 Source base class that classic NEOTOKYO is built on (still in this tree as
shared/base_playeranimstate.cpp); classic'sclient.dllwas read only for class names, console settings and constants. Then both games logged every frame (classic's built-incl_showanimstate_log, an equivalent harness log in NT;RE) on the same map and spot, with the same class, weapon and scripted keys, and the same scripts read both logs. The clips only illustrate; the numbers above come from the logs.