Repository navigation
Finish reloads at the last reload click - #2245
Merged
AdamTadeusz merged 2 commits intoOct 26, 2026
Merged
Conversation
This was referenced Oct 16, 2026
sunzenshen
marked this pull request as ready for review
October 16, 2026 07:16
Contributor
Author
|
Demos: reload-click-switch-jitte.mp4reload-click-switch-mpn.mp4reload-click-switch-pz.mp4reload-click-switch-zr68s.mp4 |
AdamTadeusz
approved these changes
Oct 22, 2026
A reload credited the magazine only when the whole reload animation ended, 0.2 to 0.7 s after the last click of the reload sound. Switching weapons in that window dropped the reload, though the gun sounded done. Each gun script now names its ReloadReadyTime: the last loud click of its reload sound, rounded up to the animation frame. Where the charging handle is home later (Jitte, SRM, MPN, AA13, PZ), the script comment names that time as the alternative value. The reload completes there and the rest of the animation plays on. Guns without the key (Supa7) keep the animation length.
Keep the end of the reload animation as the time the gun can fire again, as before this branch, and only load the magazine early: the owner stays busy until the animation ends, and the weapon loads the magazine from ItemBusyFrame once the reload's ready time has passed. A switch after the last click keeps the ammo; firing, aiming and the sprint lower still wait for the animation to end. The script key is now ReloadReadyBeforeEnd, the time from the last reload click to the end of the reload animation, and the ready time is that much before the end of the reload sequence actually played, clamped to the reload start. The ready time is networked and predicted so the client loads the magazine on the same frame.
sunzenshen
force-pushed
the
reload-ready-at-cue
branch
from
October 26, 2026 03:32
69d69c9 to
41c9dca
Compare
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
Adds a script field that defines when a weapon's reload state is done sooner than the end of the animation file. The time a player is able to return fire should be the same as before.
A reload loads the magazine only when the whole reload animation has finished, 0.17-0.67 s after the last click of
the reload sound. A player who switches weapons in that gap, for example to the knife after hearing the click, loses
the reload: the magazine is still low when they switch back. Players count shots and listen for the click, so the
click should mean the magazine is in.
With this PR the magazine loads at the gun's last reload click. Nothing else about the reload changes: the animation
plays to its end, and the gun can fire again, aim down sights or lower for a sprint only when the animation ends,
as before. Only a weapon switch in that last stretch behaves differently: it keeps the loaded magazine.
Each gun's weapon script names the click as
ReloadReadyBeforeEnd, next toCycleTime: how long before the end ofthe reload animation the last click comes. The code subtracts it from the length of the reload sequence it started,
so the value follows the animation if the animation changes. The click is the start of the last loud click in the
reload
.wav(the last onset within 12 dB of the file's peak), read from the classic sound files (NT;RE ships thesame files), rounded to the 30 fps animation frame. On the Jitte, SRM, MPN, AA13 and PZ the charging handle is back
in place a little after the click (frames from the classic viewmodels); the script comment names that offset as the
alternative value.
Code, all in
CNEOBaseCombatWeapon:Reload(): afterDefaultReloadstarts the reload (owner and weapon next attack at the animation end, as onmaster), it stores the ready time: the animation end minus
ReloadReadyBeforeEnd, never before the reload start.ItemBusyFrame(), which runs while the owner waits for the reload animation to end: once the ready time haspassed, it calls
FinishReload().FinishReload(): returns at once if this reload's magazine is already loaded, so the usualCheckReloadat theanimation end does not load a second magazine.
A gun without the key loads at the animation end, as before; the Supa7 keeps its own per-shell reload.
An animation event at the same frame would carry the value as well, but the reload sequences have no events and
the viewmodels are the classic files, so every gun's viewmodel would need recompiling.
Times in seconds from reload start; offsets in seconds before the animation ends.
Balance: firing is unchanged: the first shot after a reload comes at the end of the reload animation, as on
master (measured below). Aiming down sights and the sprint lower still wait for the end of the animation. The only
change is that the magazine survives a weapon switch made after the last click. Classic NEOTOKYO does not keep it
either: on the ZR68S it loads the magazine at 2.70 s and loses the reload when switching at 2.47 s (the Tachi also
loads at its animation length; the other guns were not measured in classic).
Changed after the first review: the script value is now an offset before the end of the reload animation instead of
an absolute time, and the time the gun can fire again stays at the end of the animation; only the magazine loads at
the click.
How to test
the magazine is full. Switching before the click still cancels the reload, as before.
Results
Listen server on nt_rise_ctg as Jinrai, Release builds of master (f426c22) and this PR. A temporary harness logger
(not part of this PR) printed the reload start, magazine load, animation end, cancel and shot times, and the server
switched to the knife a set time after the reload started and back 0.7 s later.
tick): ZR68S/C 2.280, ZR68L 2.535, Jitte 2.640, MX 2.505, SRM 2.835, MPN 2.700, AA13 4.200, Kyla 1.770, M41
3.375, Milso 1.635, Tachi 1.710, PZ 5.145, SRS 3.075. The reserve drops by one magazine only.
Switch 0.05 s before it: this PR loses the reload on all 20, as intended.
(+0-1 tick) on all 20 guns (the semi-automatic AA13 with fire tapped every 40 ms: 4.680-4.725 s on both).
net_fakelag 75and predicted weapon switches (slot3/slot1,hud_fastswitch 1): the client loads the magazine on the server's tick and stays in the reload animation to itsend; switches after the click keep the full magazine on both, switches before it lose the reload, and the client
never showed a full magazine that the server then took back. A client on a dedicated server was not tested.
asserts.
Toolchain
Linked Issues