- Underbarrel attachments work across IW4, IW5, T5 and T6, including
per-family impact FX, T5 flamethrower streams and T6 launcher fuses.
- Viewmodel notetrack sounds play in third person.
- Transport operations and queues are bounded; Quinn congestion control
returns to its default.
- Match publication, presentation context and prepared content semantics
are qualified and validated; cosmetic and entity occurrence lifecycles
are preserved.
- GPU skinning batches within supported device budgets.
- Immutable UI projections and correlated class replies are reconciled.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A placed prop often starts inside the world: a monitor's stand sits a
hair inside the desk, and its unrotated model bounds reach into the
cubicle wall behind it. integrate_body stops a body that starts inside,
so such a prop never moved however often it was shot, such as the
back-office com_widescreen_monitor on mp_terminal. The physics also
collided only with solid, while a static-model desk stands in the
clipmap as item clip, so a keyboard or phone knocked off its spot
dropped through the desk to the floor.
On its first wake a body now takes the nearest clear pose (small lifts
up to 2 units, then a footprint narrowed to 75% or 50%), colliding with
solid and item clip where it can and with solid alone where it can't,
and keeps that mask. A prop with no clear pose stays where it was
placed and settles, as 61b7c43 made it. Props still only slide; they
don't tip over.
Measured on our build with a replay of the map data: of the 1007
mp_terminal dynents with physics, 78 started stuck and this frees 38 of
them, and it freezes none that moved before. On an iPhone build on
mp_terminal, the back-office keyboards, phones and monitors moved when
shot and stayed on their desks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A dead player's body drew whatever shield its player had at that moment,
read from the victim's live client state. That state changes after
death: a bot that respawns with a riot shield in hand gives every one of
its old bodies a shield on the left arm, posed with the body and sunk
into the floor. On mp_subbase this showed as upright shields half in the
floor beside bodies, next to the shield dropped as a pickup.
Each corpse slot now records the shield stowed on the victim's back when
the body is made, and sends it with the corpse pool. A body draws that
shield and nothing else; a live player still draws the one it holds. A
shield held in hand at death is the one dropped as an item, so the body
takes no copy of it.
The corpse pool's wire format changes again, so PROTOCOL_VERSION is 118.
Checked on an iPhone build in two matches with riot-shield bots
(mp_favela and mp_estate), killing bots with the shield held up and
with it on their back: dropped shields lay flat and no shield stood
upright by a body.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The client kept a corpse's animation tree only while the corpse's tr_time
stayed the same. The server changes tr_time whenever a body's fall changes:
when it goes over an edge, when it slides down a wall, and when it lands.
Each change copied the tree again from the victim, whose tree is already
gone because a dead player is not posed, so the corpse got a fresh tree
with the death clip back at its first frame. Bodies flew off standing
upright in the clip's first 50 ms, stood against walls, and then played
the whole fall again where they stopped.
The server now stamps each corpse slot with the level time of the death
(spawn_time_ms, sent with the corpse pool), and the client keys the tree
on that time and the victim. Both stay the same for one body's life and
change when the slot holds another body. When there is no victim tree to
copy (a body first seen late, or an entity number that now holds another
body), the fresh tree starts as far into the death clip as the body is
old, so an old body shows the pose it already lies in instead of dying
again.
The corpse pool's wire format changes, so PROTOCOL_VERSION is 117.
Seen on the Mac (mp_favela, point-blank SPAS-12 kills of a bot on an open
terrace, with temporary logging): every body copies its tree once and its
death clip plays once, from the victim's pose to the end. Before, the same
kill copied it 18 times and drew the body upright in the clip's first
50 ms for about 0.8 s. On an iPhone build, point-blank shotgun kills on
mp_favela no longer glided off upright, stood pinned to walls or replayed
their fall.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The authority steers a remote missile once a tick, so the link angles in
the snapshots change in 20 Hz steps, and the missile camera showed the
presented snapshot's angles as they came: at 60 fps the view turned on one
frame in three, up to 2-3 degrees at once, and stood still on the other
two. The eye position was already carried along the trajectory every frame;
the angles were not.
The missile view now keeps the link angles of the last four snapshots of
the missile it shows and draws the angles a tick behind the presentation's
trajectory time (the listen clock live, the delayed replay time in a
killcam seat), interpolated per axis along the shortest arc between the two
snapshots around it, so 359 to 1 degree turns 2 degrees and not 358. It
never runs past the newest snapshot, so when the pilot lets go the view
stops where the missile stopped instead of overshooting and swinging back.
A new life, a new missile, losing the link, or a switch between live and
archived presentation starts a fresh history. The last matters for the
final killcam of the pilot's own kill, which replays the same missile of
the same life from seat snapshots stamped with the live tick. Four samples
cover a seat's clock running up to two ticks behind its archived snapshot.
The missile turns by the remote-control stick axes in each command, not by
the pilot's view angles, so there are no locally predicted angles to show
instead. Extrapolating the turn rate would answer sooner but overshoot by
up to a tick's turn every time the stick is released. The cost is at most
one tick (50 ms) of turn latency.
Checked on the Mac (mp_estate, a Predator steered by scripted mouse input),
frames drawn while the snapshots' link angles were changing that turned the
view, before / after: with the stick held, 28 of 75 (up to 2.8 degrees in
one frame) / 71 of 71 (at most 1.3, median 0.45); a second flight steered
over and back, 19 of 49 / 54 of 54; that flight's final killcam, 19 of 47
/ 51 of 51. After the stick is released the view never goes past the
missile's final angles. On our iPhone build in a Sub Base match, steering
was smooth.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On every Predator impact the screen showed about 83 ms of black world under
the Predator HUD, then about 50 ms of the player's own first-person laptop
view, and only then the static.
The black frames came from the camera running past the snapshot. The
missile camera evaluated the trajectory at the presentation clock with no
limit, and that clock runs up to a tick ahead of the newest snapshot, so on
the last frames of the flight the eye went through the ground. Up to the
newest snapshot the trajectory is now exact. Past it, the eye extrapolates
for one tick at most and stops at the first world surface (a camera-sized
box trace), which is where the missile detonates.
The camera also follows the presentation's trajectory time rather than the
live clock. The same camera draws the killcam replay of a Predator kill,
which has no killcam entity, and a killcam seat shows an archived snapshot
held back by the proxy delay. At the live clock the replayed eye sat a tick
past every snapshot and moved only when a new one arrived, 20 times a
second.
The first-person frames came from dropping the camera too early. The
missile leaves the snapshot on impact and the controls unlink a tick later,
but the script keeps the camera linked until after the static. The last
missile pose is now held for as long as the player's remote missile link
exists, and cleared when the link goes, on a new life, or when a different
missile is linked. The view counts as third person for the whole link, so
the laptop viewmodel stays hidden under the hold.
Checked on our iPhone build in a Sub Base match: Predators steered into
the ground cut straight from the missile view to the static, with no black
frame and no glimpse of the arms and laptop.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Favela's hanging laundry is animated script models. They were posed only
when the camera's scene-entity walk reached them, so once the clothes left
the screen their shadows on the wall below vanished (only the static rope's
stayed). IW4 culls scene entities for each sun partition apart from the
camera; here a script model the walk hid is kept for the sun shadow only
(colour refused, no lighting request) while its bound is inside one of the
sun partitions.
The partitions are published before the models are posed, from one shared
builder the command context now uses as well, so both see the same planes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Prepare progression and loading through Bevy scheduling, preserve round HUD and bombsite props, restore grenade and T5 shadow presentation, and keep menus usable while classes load. Report update progress and continue startup after update failures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A map zone streams the materials it shares with common_mp as ",name"
references: stubs with no textures and no technique set. Since
capture_material refuses a material without a technique set, the slot of
such a reference was never bound and every model surface on it was
dropped: 97 of the 14551 map model surfaces on mp_terminal and 28 of the
14125 on mp_favela, among them a surface of the wall fan cs_wallfan1 and
one of the air conditioner com_ex_airconditioner.
When the capture refuses a reference, the slot is now bound to the real
material of the same name and namespace, which the common pool already
holds. A reference with no real counterpart stays unbound as before.
",mc/shadowcaster" references bind now too, so scene_lit_pass_material
skips shadow-only materials for script models and dyn ents, as the static
model path already does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every PersistentRemoteTree holds an Arc<SoldierBodyAnimation> (since
25c008b), which owns the match's player XAnimCatalog and BodyMeshCatalog.
reset_anim_for_match clears the other per-match animation state on
MatchInstalled and MatchTornDown, but not RemoteBodyTrees, and the trees'
only pruning (retain_live in pose_remote_bodies) runs once the next match
poses remote bodies. When a different map loads, load_prepared_match drops
the resident copy of the last match before walking the new one, and from
then until the first remote pose the trees alone keep the old match's
catalogs alive, through the peak of the next load.
Reset RemoteBodyTrees with the rest of the per-match state. The trees are
rebuilt when remote bodies are posed in the new match.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A physics prop's hull is its model's whole bounds, a potted plant's leaves included, so a pot
where the map placed it can already overlap a pillar or shelf. Once woken, every physics step
found it starting in solid and lifted it a unit, so it rose until the hull cleared the
obstacle and fell asleep in the air; each later wake lifted it again. A prop starting in solid
now stays where it is and settles.
Walking past woke any physics prop whose bounding sphere touched the player's box and gave it
the player's velocity: a large pot's sphere (75 units, the leaves) reached the player well
before the pot did, so walking near one pushed it along. Only clutter (cans, bottles, luggage)
is moved by walking now; bullets and explosions still move breakable props.
Checked on mp_terminal: pots floated after walking past them on this branch before the change;
with it, walking past the bookshop pot (com_potted_plant_large at 1177 5453) leaves it on the
floor.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Decode Black Ops audio natively and load Black Ops II worlds, faction
models, equipment, materials, lighting and weapon camouflage.
Rework capsule collision, solid recovery, penetration, recoil, effects
and sentry placement; synchronize late joins and player event delivery.
Keep local skill ratings and signed player accounts.
Show the selected community and master ping on the main menu. Add twenty
asset-filtered class presets across IW4, IW5, T5 and T6, plus fifty-two
unique player-style names shared by AI bots and dummies. Honor the chosen
dev descriptor in the two-client approved scenario and credit contributors
and weapon, map and attachment QA testers.
Validated with the approved gameplay lifecycle and two-client dev-master
scenarios, installed class-asset audit, bot-name uniqueness checks and
Linux IW4/IW5/T5/T6 gameplay smoke runs. Foreign-weapon match-stat schema
coverage remains incomplete.
- Format with rustfmt and clear the clippy warnings on lines this branch
adds (fixed-size chunks via as_chunks, explicit fallbacks instead of
unwrap_or_default, range patterns, elided lifetimes).
- The engine-supplied equipment script is t6_equipment.gsc.txt, since
publish-check treats any .gsc as game data; FNV constants are named.
- NOTICE credits the Plutonium t6-scripts dump that the equipment
behaviour was worked out from.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A weapon's gunXModel / worldModel slots 1-8 are its camouflage models
(woodland ... orange_fall, numbered as mp/camoTable.csv). They are now
captured, aliased arrays included, and bound per weapon.
Classes carry a camouflage per weapon (classes.txt: two optional trailing
fields, written only when one is set; PersonalClass on the wire, protocol
103). MW2's _class.gsc reads it from customClasses...camo and gives the
weapon with its number; giveWeapon stores it as the slot's weaponModel in
weapon_data, which replicates. First person swaps the gun's materials for
the camouflage model's (it shares the gun's surfaces); third person draws
the camouflage world model.
Create-a-Class goes weapon, attachment, then camouflage, as MW2 does,
offering only the camouflage the weapon has, and MW2's panel shows it
behind the weapon. Console: give ... camo=<name|slot>, bot give ...
camo=<name>.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts kept both sides: Steam discovery next to Game Folders and
sibling titles, upstream's profile/account persistence next to the
folder picks and saved position, SAB/FLAC beside blake3, the T6
localize loader on the raw-bytes catalog (cache format 3), and our
tactical insertion equipment mapping with upstream's specialty_null.
The fire-delay fix takes upstream's form. Exit silencing now mutes the
new audio runtime instead of Bevy audio sinks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
T6 effects named in T6_EFFECTS are captured from the T6 zones and
converted to IW4 effects: a T6 element is laid out as a T5 one, lines
become tails along the effect's forward axis at half size, and sample
colours go from RGBA to BGRA. Their materials stand in on IW4's glow
stick material with the T6 colour maps.
The flare glows IW4's scripts light on a T6 tactical insertion play the
T6 team or enemy light instead, from the insertion, straight up. The
planted model lies flat as in Black Ops II.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The T6 tactical insertion sits in the tactical slot and throws with the
tactical button beside the lethal: the class script is handed a smoke
grenade standing for it, and its giving starts IW4's tactical insertion
perk. The glow stick IW4's scripts plant for it carries the T6 planted
model, drawn as a projectile mesh standing on end, and the thrown grenade
is removed once it is planted.
IW4's own tactical insertion chosen as the lethal is given as the
equipment perk instead of a frag.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Reticles draw T6's emissive technique (T6 "unlit" is Radiant's preview);
packed constant rows, floatZ stand-in, blended surfaces drop depth writes
- Zone pointer lookups go through per-asset bound slots (reused memory)
- Holo and rangefinder swap to their ADS models when fully aimed
- BO2 scope overlays (variant/unique overlay materials); sights looked
through (ACOG, iron sights) on snipers aim down the 3D sight
- Select fire and other zero-timed alt raises last their clip
- Stat-only configurations (FMJ) keep the bare weapon's hides
- HUD names configurations with their attachments; equipment uses its
BO2 HUD icon; attachment and overlay icons decoded for the class menu
- World models (planted equipment, third person) use native T6 materials
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every attachment a T6 weapon offers, alone or in a compatible pair, is a
weapon row (`an94_acog_grip`) built from the base row and the weapon's
WeaponAttachmentUnique assets: the attachment's first-person and world
models at the weapon's own placement, hidden gun bones, clip overrides,
fire sounds and alternate weapon. Stat-only attachments make rows that
change nothing shown yet.
- fastfile_t6: AttachmentUniqueView; loaded assets record the asset each
pointer field named at load time, since walk memory is reused.
- Each attachment model is captured per weapon (`model@unique`) with its
offset as root rest and the gun bone it hangs from (ModelSkel::mount_tag).
- T6 guns hide parts by collapsing bones in skinning: their sights share
the body's surfaces.
- Bare T6 rows hide what their `none` unique hides.
- The full T6 attachment table loads; stats-table names like `acog_sniper`
map to `acog`.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
T6 (Black Ops II) weapons load from the BO2 install beside MW2 and play
with their own models, materials, animations, sounds and icons, standing
in for an MW2 weapon row for gameplay.
- fastfile_t6: T6 zone walking and weapon views; IPak/SAB image and sound
sources in asset_transport.
- dxbc_sm5: DX11 shader bytecode lowered to WGSL, so T6 materials draw
with their own technique sets (t6_techset, dxbc_abi).
- Materials: borrowed draw states come from the stand-in's opaque body,
never a lens; colour-map alpha (the camo mask) reads as one on opaque
surfaces; specular and probe reflection scaled for IW4 lighting; maps
named by another kind's samplers fall back to the same-role map.
- Dual wield (`X_dw` + `X_lh`) through the shared secondary-gun viewmodel,
and the `dw` attachment from T6's attachment table.
- Melee: guns without their own melee clip (and pistols, whose clip is the
tactical knife's) borrow knife_mp's knife and swings; the hip ADS layer
returns after a melee.
- T6 clip names match case-insensitively.
- Game Folders option for BO1/MW3/BO2 installs, multi-game lookup fixes,
clean exit, crosshairs, save/load/loadspawn console commands.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Scoped weapons hold breath with recovery feedback and sound. Riot shields
block and deflect bullets in hand and on the back; explosive crossbow bolts,
destructible map cars with round resets, and T5 map model collision work.
Remote players show last stand, weapon change, jump, mantle, landing,
ladder and stun animations, and server hitboxes follow the shared torso tree.
GSC gains spectator follow cameras, chat, kick, vehicle paths and flight
controls, physics spheres, slow motion, slide and mantle movers, damage
triggers, music, ambience, rumble and live audio fades over a shared mixer.
IW5 and T5 maps get sun shadows with per-stage sun selection; post-fx
pipelines compile before a vision blend needs them. The lobby browser keeps
focus and selection, and rooms can be password protected. Console supply
and give commands search every item category. Frames and replays decode
only the current wire protocol.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- One common set per content profile, shared by every match and the loadout
menu; a restart over the same map keeps its images and static geometry.
- Weapons resolve as families: attachments are chosen from each game's own
tables, checked, and composed into prepared configurations with their
first-person skeleton assembled once.
- Sessions end through one teardown and one process exit; retired resources
are dropped on a worker, not the frame.
- Sound is captured by the walks that already read each zone.
- A loading screen that reports what the load is doing.
- Tests live only in crates/approved_tests (heavy_gameplay_lifecycle);
publish-check refuses them anywhere else.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>