Skip to content

Research: segmented reload viewmodels and per-phase reload sounds (proof of concept) - #169

Draft
sunzenshen wants to merge 25 commits into
NeotokyoRebuild:masterfrom
sunzenshen:research-reload-phases
Draft

sunzenshen wants to merge 25 commits into
NeotokyoRebuild:masterfrom
sunzenshen:research-reload-phases

Conversation

@sunzenshen

@sunzenshen sunzenshen commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Draft. The assets for neo's research branch research-reload-phases (segmented, resumable reloads), which is
now the bundle of all our pending fixes (Option A #2244, #2245, #2248 with its slide fixes, #2249, #2246, #2250) and
includes #170. The two branches move together, and both are
rebased onto master whenever a bundled PR merges, resolving here whatever that merge changed.

What it adds

  • Recompiled viewmodels (neo/models/weapons/) for the ZR68S/C/L, MX, MX-S, M41, M41S, M41L, Jitte, Jitte
    scoped, SRM, SRM-S, MPN, MPN unsilenced, AA13, PZ, SRS, Milso, Tachi, Kyla and Supa7, Jinrai and NSF (42 models):
    the original NEOTOKYO viewmodels decompiled and recompiled unchanged (every shipped animation within 0.03 units of
    the original, a few long or fast frames within 0.14 units / 0.44 degrees), plus the new sequences: reload_partial,
    reload_from_{drop,seat,slap}_{dry,partial}, draw_resume_drop_{dry,partial}, the Tachi's reloadempty, the Supa7's
    rack. MDL v48 (studiomdl of the Source SDK Base 2013).
  • Sources (neo/modelsrc/weapons/<model>/): QC, reference SMD, every animation SMD, the segments.csv rows the
    sequences are built from, and a README with the recipe (ntre's mdl2smd.py + segments_build.py + studiomdl).
  • The Tachi's muzzle-flash events: the research decompile dropped the shipped AE_MUZZLEFLASH on fire..fire3;
    the Tachi QCs take them back from Tachi: reload from empty with the slide held back #170 and both Tachis are recompiled (every sequence otherwise
    unchanged). Its reloadempty is the same animation as that PR's, so the two do not conflict in content.
  • Sound pieces (neo/sound/weapons/<gun>/<gun>_reload_<phase>.wav): each reload wav cut at its quiet gaps into
    drop / seat / slap / bolt pieces, each starting 0.02 s before its first transient. The Milso / Tachi slide-release
    piece is a placeholder (PLACEHOLDER.txt beside it).

Commits, one per gun or step

e328d4a, 3b56371, d866497, 2433878, 40c5842, 18444e3 (ZR68S and the ZR68 sounds), 1ef27f1 (ZR68C), 9e2a6b1 (ZR68L), b6b9cb3
(MX), f7d3f3b (M41), 794a2c2 (Jitte), 8d0eda6 (SRM, MPN), ccbe908 (AA13, PZ), 8a10b89 (SRS), 4dda8b8 (draw-resume
park fix), 8f7daa8 (Milso, Tachi), 542c4bb (Kyla), 720e674 (placeholder slide sound), ff0c2fc (Supa7 rack), 9e3653e and e799355 (MX bolt resume), f4d180d (merge of
#170, Tachis recompiled with their muzzle-flash events).

Size

1165 files, mostly text SMD sources (one animation set per model where the bone frames differ). A merge would
likely keep the compiled models and move or drop the sources; the reviewers' call.

Open items, decisions, videos

As in the neo PR (NeotokyoRebuild/neo#2251): placeholder slide-release sound, holster magazine fade, Supa7 shell-shot pump sound (parked), the
stealth option, Option A's cases not re-filmed on the bundle. Every
dry Milso and Tachi sequence holds the slide back until the release (checked per frame), so the bundle needed no new
pistol animation. Tests on the bundle build: as in the neo PR. Videos per gun in ntre proposals/0057 review-media/<gun>-permutations/ (Milso and Tachi on the bundle build:
<gun>-permutations-bundle/) and the overview reel.

Recompile the Jinrai and NSF ZR68S viewmodels from decompiled sources
with one new sequence, reload_partial: the reload up to the magazine
tap (frame 56), then 10 frames to the idle pose, skipping the
charging handle. Research branch only: the code that plays it lives on
neo's research-reload-phases branch.

Sources (QC, SMD) are under neo/modelsrc/weapons/zr68s.
Add five resume sequences beside reload_partial to the Jinrai and
NSF ZR68S: reload_from_{drop,seat}_{dry,partial} and
reload_from_slap_dry, each a reach from the idle pose to the grab
pose of the next phase followed by the shipped frames. Built from
segments.csv by ntre's segments_build.py; reload_partial is
regenerated by the same builder (equal to the previous build).
Slice zr68_reload.wav into drop, seat, slap and bolt pieces at the
quiet gaps between its bursts, each starting 0.02 s before its first
transient with 10 ms fades. The full wav stays for the plain reload.
The audio at values in segments.csv move to the measured transients
(0.306, 1.294, 1.729, 2.029 s).
The reaches were sized by the straight distance from the idle hold to
the grab pose, but the hand travels a longer arc around the gun and
peaked at 9 units a frame. Size each reach so the hand's peak speed
stays at the shipped 2.5 units a frame, with even steps along the arc:
27, 20 and 30 frames instead of 12, 6 and 16.
A reload interrupted after the old magazine dropped resumes from the
draw: draw_resume_drop_{dry,partial} bring the gun up one-handed while
the support arm and the fresh magazine stay below the screen, tilt
the gun into the reload and continue from the magazine insert. No
magazine slides out of the well on screen and no bodygroup is needed.
Cut the drop piece from 0.126 s instead of 0.286 s so it keeps the two
soft sounds at 0.146 and 0.235 s where the hand starts toward the
magazine.
The ZR68C carries the ZR68S's reload bones, so it gets the same
partial, resume and draw-resume sequences, built from its own
decompiled animations by the same segments.csv rows. It shares the
ZR68's reload sound pieces.
The ZR68L gets the partial, resume and draw-resume sequences from its
own decompiled animations, and its own reload wav cut into drop, seat,
slap and bolt pieces. The wav lags the shared animation after the
seat, so the slap and bolt pieces are timed 0.17 s and 0.30 s earlier
than in the wav.
Partial, resume and draw-resume reload sequences for the four MX
viewmodels from the shared MX plan, each built from its own
animations. The bolt resume reaches to the pose where the hand closes
on the charging handle (f72). The reload wav is cut into drop, seat,
slap and bolt pieces; the seat rattle plays 0.27 s early, at the
silent magazine seat.
Partial, resume and draw-resume reload sequences for the six M41
viewmodels, with the slap as a phase of its own: a partial ends after
the slap, a resume after the seat replays the slap first. The M41L
(an NT;RE model) has the same hands as the M41, so it shares the plan.
The reload wav is cut into five pieces: the tap rattle plays 0.455 s
early at the silent magazine seat, the tap clicks stay on the tap.
…earch)

Partial, resume and draw-resume reload sequences for the four Jitte
viewmodels from one plan (no slap: the partial ends in the hold after
the seat). The reload wav is cut into the fetch rustle and the
magazine-out click (played 0.20 s early, at the magazine leaving),
the insert and the bolt.
Partial, resume and draw-resume reload sequences for the four SRM and
four MPN viewmodels (one plan per gun, no slap), and their reload
wavs cut into drop, seat and bolt pieces. The MPN's loud seat click
plays 0.18 s early, on the magazine seat.
Partial, resume and draw-resume reload sequences for the AA13 and PZ
viewmodels. The PZ's drum latch is its slap phase: the partial ends
after it, a resume after the seat replays it. Both reload wavs are cut
into per-phase pieces; the PZ's drum-away rustle is a second drop
piece.
Partial, resume and draw-resume reload sequences for both SRS
viewmodels; the resume after the drop picks up the magazine's carry
back to the well at f45. The reload wav is cut into drop, seat and two
bolt pieces; the bolt-open click plays 0.27 s early, with the bolt.
These three guns' insert grab pose is itself in view, so the
draw-resume brought the hand and magazine on screen during the draw.
Park them 20 units lower during the draw and swoop them up into the
grab during the gun's tilt.
Resume and draw-resume reload sequences for the Milso and Tachi, the
Tachi's dry reloadempty (its slide held back, then released like the
Milso's), and the slide release alone for a resume after the seat.
The reload wavs are cut into drop and seat pieces; the slide release
has no sound in either wav.
The Kyla revolver gets a draw-resume and a reach resume for a reload
interrupted after the cylinder swung open, and its reload wav cut into
the open-and-eject, the rounds in, and the close.
Neither pistol's reload wav has a slide release, so the release
piece is a slice of the game's MP5 slide sound, marked as a
placeholder until a proper one is recorded.
Add a rack sequence to both Supa7 viewmodels: the support hand
reaches from the hold to the pump and racks it once, for a reload
press with the tube full.
The bolt resume reached to reload f72, where the handle is already
springing forward and the hand has let go (the Charge bone moves back
f62-70 and returns f70-75), so the handle moved with the hand nowhere
near it. Reach straight up beside the gun to the handle hold at f62
(26 frames, same length, credit and sound time) and play f62-86.

Sources only; the compiled models follow once the game is idle.
The four MX viewmodels compiled from 95187e1's sources: only
reload_from_slap_dry changes (compiled f26-50 equal reload f62-86);
every other sequence within 0.006 u of the previous compile.
The Tachi viewmodels had no reload for an empty gun, so a reload from
empty played the normal reload, whose slide is forward from its first
frame, and the slide closed as the reload began. Add reloadempty
(ACT_VM_RELOAD_EMPTY) to the Jinrai and NSF Tachi, built the way the
Milso's shipped one is: the normal reload with only the slide changed,
held back and released over frames 54-62 after the magazine is seated.
Every other sequence is the shipped one, recompiled.
The research Tachi already has the same reloadempty, so its models and
sources stay. The recompile keeps the shipped muzzle flash event on
fire, fire1, fire2 and fire3, which the research decompile dropped and
vm-empty-slide-assets restored.
fire_chamber_onehand: a 4-frame ease-out flick from the insert grab to
the centered hold with the support arm and magazine parked out of
view, the shipped fire (Tachi: fireempty, slide locked) one-handed,
the swoop back into the insert grab and the rest of the dry reload;
fadein 0.133, the bullet at the script's fire_at. fire_blend: the
shipped fire without snap, for the first shot after a cancelled
reload. Built from segments.csv rows *.fire_chamber_onehand; the
other sequences compare equal to the previous models.
fire_chamber_onehand and fire_blend for the ZR68S, ZR68L, MX, MX-S,
M41, M41S, M41L, Jitte, Jitte scoped, SRM, SRM-S, MPN, MPN
unsilenced, AA13, PZ and Milso, Jinrai and NSF, as for the ZR68C and
Tachi: a 4-frame flick to the hold (MPN 6 frames, its reload rolls
the gun about 75 degrees), the shipped fire one-handed, the swoop
back and the rest of the dry reload. The other sequences compare
equal to the previous models; the support arm and magazine stay off
the first-person view through the fire frames on every model.
@sunzenshen

Copy link
Copy Markdown
Contributor Author

I'm expecting critical feedback on where to actually put the pre-compilation animation files. Probably don't want to commit every file as is in this initial commit to neoAssets.

But this entire branch can be dumped onto a local build of NeotokyoRebuild/neo#2251 to try out these experimental animation systems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant