Repository navigation
Hold a pistol's slide back from the last shot to the reload - #2248
sunzenshen wants to merge 5 commits into
Conversation
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.
The Tachi and Milso viewmodels ship a drawempty sequence, the normal draw with the slide held back, but it carries no activity, so an empty pistol drew with the slide forward and only pulled it back as the empty idle faded in. Pick drawempty by name in Deploy when the clip is empty. Models without it, and loaded draws, are unchanged.
The shot that emptied a Tachi or Milso played its normal fire sequence, whose slide closes within 0.2 s, and the slide went back only when the empty idle followed 0.4 s later. Both pistols ship a dry fire sequence that is a shot's kick with the slide held back throughout, ending on the empty idle's pose, so the last round's shot plays that instead.
A reload always played the reload sequence, whose slide is forward from its first frame, so the slide of an empty pistol closed as the reload began. The Milso ships a reload for an empty gun (ACT_VM_RELOAD_EMPTY) that keeps the slide back until its release near the end, the same length as the reload; an empty weapon now plays it where the model has one.
|
PR (2259) is the more complete solution, but I am proposing this PR #2248 simultaneously, because I think we need to figure out how to handle the raw precompiled animation files from NeotokyoRebuild/neoAssets#170 . Maybe they shouldn't be in neoAssets? So it might be easier to merge this PR first before we figure out the answer to animation file management. |
| // an empty weapon reloads with its slide held back until the release, where the model has that reload | ||
| if (UsesClipsForAmmo1() && m_iClip1 <= 0 && SelectWeightedSequence(ACT_VM_RELOAD_EMPTY) != ACTIVITY_NOT_AVAILABLE) | ||
| { | ||
| if (!DefaultReload(GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD_EMPTY)) |
There was a problem hiding this comment.
do we have any weapons that benefit from this change? It might be a good idea regardless, but from what I can tell the tachi reload has the slide forward when reloading while empty
There was a problem hiding this comment.
That's a fair point, and maybe for consistency, arguably the full animations need to be implemented for this to be cohesive.
This PR is the same idea but with a custom animation to fix the tachi slide back:
These are the differences between master and the two PRs:
case8c-slide-reload-tachi.mp4
|
Drafting in favor of #2259 |
Description
The tachi/milso slide locks back on the last shot, stays open when empty and between changing weapon slots, and stays back through a reload from empty. This PR includes the commit of #2247 (closed), the parity animation where the slide moves back and stays open when empty, so it stands on its own.
Case 8: first-person weapon animations.
Review page: exported review page (Dropbox) · live review page (opening it lets you request access with your email or Claude account).
The Tachi and Milso viewmodels ship an
idle01emptysequence (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 about 0.5 s after the last shot and stays back until the reload; drawing the empty pistol again plays the normal draw, then the slide goes back.This PR makes five changes, all in
CNEOBaseCombatWeapon(+57 / -2 lines inweapon_neobasecombatweapon.cpp/.h):CWeaponCrossbow::SendWeaponAnim. While the clip is empty,CNEOBaseCombatWeapon::SendWeaponAnimsendsACT_VM_IDLE_EMPTYin place ofACT_VM_IDLE, when the model has that sequence. A weapon withoutidle01emptybehaves exactly as before.fireempty(ACT_VM_DRYFIRE) instead of a fire sequence. On both pistols that sequence is a shot's kick with the slide held back from the first frame, ending on theidle01emptypose, so the slide locks at the shot and the empty idle follows when it ends (0.4 s, the same length as the fire sequences). The fire sequences close the slide within 0.17 s, so with the empty idle alone the slide would lock only as the empty idle faded in.ACT_VM_RELOAD_EMPTYwhere the model has it: the Milso's shippedreloadempty, the same 2.1 s asreload, holds the slide back until it is released over its last 0.3 s. The Tachi ships no such sequence and keepsreload, whose slide is forward from its first frame. Tachi: reload from empty with the slide held back neoAssets#170 adds one, and this code plays it with no further change.PLAYERANIMEVENT_RELOADas a reload with rounds left does, so other players still see the reload gesture. This was found in review of the change above; a server log of the event in game showed it at clip 0 (empty reload) and at clip 9 (partial reload).drawemptysequence: the same 0.8 s draw with the slide held back. Bone data shows it differs fromdrawonly in the slide, and by up to 2.1 u at one forearm bone. It has no activity tag, so nothing could select it.CNEOBaseCombatWeapon::Deploynow picks it by name when the clip is empty. Models without adrawemptysequence are unchanged, and so are loaded draws.The empty idle is classic parity. The lock at the last shot, the empty draw and the slide held through the reload go past it, as asked in review.
The last-shot check names the two pistols. On the rifles,
fireemptyis a small trigger click, andidle01emptyis identical toidle01in every frame and bone in the MX, SRM, ZR68S, MPN and AA13, so an empty rifle has no slide or bolt pose to show. Their empty idle plays but looks the same as before. Neither pistol's reload sound has a slide release; that is unchanged.For reviewers who want to merge the Tachi asset at the same time: #2259 is the same code as this PR, paired with NeotokyoRebuild/neoAssets#170. Merge this PR or #2259, not both.
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), and the slide bone's position per frame read from the shipped models. 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 every build, with
cl_autoreload_when_empty 0in neo:Release builds of master (f426c22) and this PR.
How to test
cl_autoreload_when_empty 0, switch away and back. The slide is back from the first frame of the draw and stays back.Results
fire, slide back ~0.5 s after the shotfire, pose held 2.0 s, slide forwardfireempty: slide back at the shot,idle01empty0.40 s laterfireempty, then slide forwardfireempty, thenidle01emptydraw, thenidle01(slide forward)drawempty, thenidle01empty(slide back throughout)reload(slide forward from its start)reload(unchanged without the neoAssets PR;reloademptywith it)reloadempty(slide released at 1.77-2.07 s)idle01idle01empty, which looks the sameWith 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:
reloademptyreachesidle012.07 s after it starts.net_fakelag 75, the Tachi pass showed no switching between the loaded and empty idles, with autoreload off or on.A Debug client with 12 bots ran 210 s each on
ntre_rise_ctgandntre_skyline_ctg. The local player emptied the Tachi, then switched away and back. It logged only known asserts:neo_root.cpp (378) localizedWszStrat startup, plus oneclientleafsystem.cpp (1025)onntre_rise_ctg.Rerun after the last-shot and reload changes (Debug,
ntre_rise_ctg, last shot, dry, draw, reload from empty, partial): only the knownneo_root.cpp (378)at startup. The third-person reload fix was checked in a Release build.Trial merges with #2246, #2249, #2250 and #2244 are clean. #2245 conflicts in
Reload(), where both change the last lines: the merge keeps this PR's empty-reload branch and sets #2245's ready time after either reload (as done in #2251).Not changed: the Milso's
holsterempty, which is a secondACT_VM_HOLSTERsequence that the SDK already picks at random, and the 2.0 s hold after shots that do not empty the clip.Related