Skip to content

Hold an empty weapon on its empty idle - #2247

Closed
sunzenshen wants to merge 1 commit into
NeotokyoRebuild:masterfrom
sunzenshen:vm-empty-slide-lock
Closed

sunzenshen wants to merge 1 commit into
NeotokyoRebuild:masterfrom
sunzenshen:vm-empty-slide-lock

Conversation

@sunzenshen

@sunzenshen sunzenshen commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Description

For the tachi, match the parity animation where the slide moves back and stays open when empty.

Contrasts with #2248 which is not parity, but maintains the slide open position between weapon switch attempts.


The Tachi and Milso viewmodels ship an idle01empty sequence (ACT_VM_IDLE_EMPTY) with the slide held back, but neo never plays it. After the last round, an empty pistol holds the fire sequence's last frame for 2.0 s and then idles with the slide forward. In the original NEOTOKYO, the slide goes back as the last shot ends and stays back until the reload. That covers drawing the empty pistol again: the normal draw plays, then the slide goes back.

This PR uses the SDK's own pattern for an empty weapon's idle, from CWeaponCrossbow::SendWeaponAnim. While the clip is empty, CNEOBaseCombatWeapon::SendWeaponAnim sends ACT_VM_IDLE_EMPTY in place of ACT_VM_IDLE, when the model has that sequence. The shot that empties the clip moves on to that idle when its fire sequence ends, instead of 2.0 s later. That is +24 lines in weapon_neobasecombatweapon.cpp/.h: one override, one private helper, and one check after the clip is decremented. A weapon without idle01empty behaves exactly as before. Draw, holster, dry fire and reload are unchanged, since the original game plays the normal draw and reload too.

Other models ship idle01empty as well: the MPN, SRM, MX, ZR68C/L/S and AA13 families, and the shotgun model. On the MX it looks the same as the loaded idle from the first-person view (checked). The original game's ZR68S also shows no difference when empty.

Independent of the other animation PRs from the review page. #2245 and the "Keep the ZR68L raised while sprinting" PR edit the same file in other functions; trial merges of this branch with each are clean.

How this was compared

Per-frame viewmodel logs on nt_rise_ctg (a harness-only client log of the local viewmodel's sequence, cycle and clip each frame). Video was recorded on a black background with only the lit viewmodel drawn, so the slide can be read. The original game was filmed in the same way, as Jinrai Assault with the Tachi.

The scripted pass, the same in all three, with cl_autoreload_when_empty 0 in neo:

  1. Empty the magazine with single taps, then wait 3 s.
  2. Pull the trigger twice on empty.
  3. Switch to the primary and back.
  4. Wait 3 s, then reload.

Release builds of master (f426c22) and this PR.

How to test

  1. Tachi or Milso: fire the magazine dry. The slide stays back from the end of the last shot.
  2. With autoreload off, switch away and back: the normal draw plays, then the slide stays back.
  3. Reload: the normal reload plays, and the slide is forward afterwards.
  4. MX or MPN: emptying and reloading behave as before.

Results

original NEOTOKYO master this PR
Tachi, after the last shot slide back ~0.5 s after the shot, held until the reload fire pose held 2.0 s, then slide forward idle01empty from 0.40 s after the shot (the fire sequence's length), held until the reload
Tachi, dry pull starts the reload fireempty, then slide forward fireempty, then idle01empty
Tachi, drawn while empty normal draw, then slide back draw, then slide forward draw, then idle01empty
Milso - as the Tachi on master as the Tachi in this PR
MX, after the magazine - idle01 idle01empty, which looks the same

With the default cl_autoreload_when_empty 1, the empty idle shows until the automatic reload 3 s later, or until a dry pull starts the reload.

Unchanged:

  • Shot intervals: MX 0.106 / 0.107 s, Tachi and Milso the same in both builds.
  • Reload lengths: Tachi 2.11 s, Milso 2.09 s, MX 2.88 s in both.
  • With net_fakelag 75, the Tachi pass showed no switching between the loaded and empty idles, with autoreload off or on.

The Tachi and Milso viewmodels have an idle01empty sequence with the
slide held back, which neo never played: an emptied pistol held its
last fire frame for 2.0 s and then idled with the slide forward. The
original NEOTOKYO holds the slide back from the end of the last shot
until the reload. Send ACT_VM_IDLE_EMPTY for ACT_VM_IDLE while the
clip is empty, as the SDK crossbow does, and go to it as the emptying
shot's sequence ends. Models without the sequence are unchanged.
@sunzenshen sunzenshen added the Animations Animation stuff. Including the syncronizing of animations between client and server based on state. label Oct 16, 2026
@sunzenshen

Copy link
Copy Markdown
Contributor Author

Demo:

case8c-tachi-empty-slide.mp4

@sunzenshen

sunzenshen commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor Author

#2248 might be the better solution, but this PR is closer to parity with the original animation behavior.

@sunzenshen
sunzenshen marked this pull request as ready for review October 16, 2026 09:27
@sunzenshen
sunzenshen marked this pull request as draft October 16, 2026 10:15
@sunzenshen

Copy link
Copy Markdown
Contributor Author

https://github.com/NeotokyoRebuild/neo/pull/2248/commits already has this PR's commit, and offline discussion agreed that #2248 looks better.

@sunzenshen sunzenshen closed this Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Animations Animation stuff. Including the syncronizing of animations between client and server based on state.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant