55 Commits

Author SHA1 Message Date
vtroc7 acc57a5c9d Make underbarrel attachments work across families, bound transport and qualify match publication
- 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>
2026-10-16 16:28:56 +03:00
vtroc7 5b4897bc56 Merge treuenten gameplay, effects and map-loading fixes
Includes PRs #100, #101, #102, #103, #104, #105, #106, #107 and #108.
2026-10-14 10:55:29 +03:00
JohnM 00849fd0e6 Let shotgun pellets break and push props such as cash registers
Bullets reach the client as bullet hit events, which on_entity_bullet_hit
turns into dynent damage and impulses. Shotgun pellets (and turret
rounds) arrive as pellet records instead, and drain_pellet_fx only drew
their tracers and impacts, so a shotgun never broke a cash register, a
suitcase or a card reader, and never pushed a prop.

Each pellet segment that ends on a surface now strikes the nearest
dynent on it the way a bullet does, from the authoritative copy only:
drain_pellet_fx sends a DynEntPelletHit, and hit_dyn_ents_from_pellets
finds the dynent on the segment and damages and pushes it with the
weapon's hit damage.

Checked on the Mac on mp_terminal, two short AA-12 bursts at the
food-court register: before, the register and card readers stayed
whole; after, both broke. Reported from an iPhone match where the
AA-12's pellets kicked up dust on suitcases that a SCAR then burst open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:43:59 +10:00
JohnM 967c2a1dad Remove bullet marks from shot-out glass once the mark pool has wrapped
The mark pool recycles its oldest slot, but the list of marks attached to
script-model bones kept every entry until the match reset. Once the pool
had filled, an old attachment on a car's body bone pointed at a new
bullet star on its window, so the star kept drawing after the window was
shot out and its glass hidden. Stray marks were also drawn through other
entities' bones.

An attachment is now dropped when its slot is allocated again, and
whenever the slot no longer holds a mark on its own entity. This also
stops shot models being posed every frame for marks that are long gone.

Checked on an iPhone build on mp_estate: after 8 minutes of play, the
bullet stars went with an SUV's window glass when it was shot out.
Before, on the same map late in a match, the stars stayed hanging in the
air after the glass was gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:28:05 +10:00
JohnM 679118da0b Light walls with the warm colour of muzzle flashes and explosions
Muzzle flashes, bullet impacts and explosions lit walls and snow blue or
cyan while their own flash and fireball sprites stayed orange. The effect
colour is stored B,G,R,A. render_fx swaps it once to R,G,B,A for every
sprite, trail and spark, and the light path then passed that value to a
helper that swapped red and blue a second time. GfxLightPack.color is
R,G,B like a map primary light, so every effect omni and spot light came
out with red and blue reversed.

The helper is now elem_light_color_rgb and keeps the order. The light
instance field and the omni and spot pack parameters are renamed
color_rgb so the names say what the value holds. Read in the same order
the sprites use, the light elements of these effects are amber and
orange, matching their flash and fireball sprites.

Measured on the Mac on mp_subbase, facing the concrete wall above the
snow bank: the light an RPG blast adds to wall and snow went from linear
R:G:B 0.28:0.81:1.00 (cyan) to 1.00:0.82:0.33 (amber), and an M4 burst
from 0.34:0.48:1.00 (blue) to 1.00:0.60:0.55 (warm). Wall and snow
before the shots are unchanged, since map lights take another path. On
an iPhone build on mp_subbase, a long burst at a concrete wall lit it
warm instead of blue.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 20:24:01 +10:00
JohnM 07f7a40f4e Send dirty static-model lighting tiles to the GPU as tile writes
update_smodel_lighting wrote each dirty static-model lighting tile into the
model lighting atlas through a tracked Assets::get_mut. Every frame with a
dirty tile therefore marked the whole atlas modified, so Bevy extracted all
of it again and rewrote the whole texture on the GPU, up to 1 MiB, for a few
256-byte tiles.

The tile is now written through an untracked borrow and queued in
ModelLightingAtlasTileWrites, as the moving-model lighting cache already does
for the same atlas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:07:40 +08:00
vtroc7 c47684e141 Improve native rendering, background menus and community setup 2026-10-12 20:34:48 +03:00
vtroc7 08b4224efd Add Theater editing and chat, improve controller UI, audio, combat and network recovery
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:43:30 +03:00
Gh4zi a690ea55c0 Sun shadows: trees cast through their shadow-caster mesh again
MW2 trees (Favela's oaks: mc/mtl_tree_oak_*) cast their sun shadow only
through a separate, never-drawn mesh (mc/mtl_tree_shadow_caster). Its
shadow-only material was kept out of the static model colour material keys,
and the sun shadow pass looked its material up in those same keys, so the
surface was dropped and the trees cast nothing. What stayed was the
lightmap's sun mask: MW2's shader forces shadow where the mask is 0, which
showed as blocky dark rectangles on otherwise sunlit ground under the trees.

Shadow-only materials are now listed in their own key, read by the sun
shadow pass only; the colour pass still never sees them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 17:13:49 +03:00
Gh4zi d9f497322e Sun shadows: script models out of view still cast into it
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>
2026-10-11 17:13:49 +03:00
vtroc7 a2f189df10 Scope match lifetimes and restore gameplay and menu presentation
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>
2026-10-10 23:01:34 +03:00
vtroc7 5273074e72 Integrate contributor rendering, gameplay and development fixes 2026-10-10 01:33:23 +03:00
JohnM 3039cf4943 Draw effect model pieces such as cash register bills
Effect model pieces (the bills and halves of a shot cash register, food,
luggage contents, plant pots, glass pieces) have not drawn since 69cf9ff
moved the effect model geometry into the Plan phase of the world spawn.
That phase runs before world_occupancy::place builds the model lighting
atlas, so prepare_fx_model_geometry found no atlas and quietly returned an
empty plan, and every model elem that passed its LOD and cull checks was
dropped for want of geometry.

The geometry is now built in spawn_world_finish straight after
world_occupancy::place. The Plan phase still installs an empty plan so its
readers find the resource. A missing atlas is now a warning with the model
count, and one line reports the models and LODs prepared and refused.

The bills had a second fault. mp_terminal stores `,fx_cash01` as a
placeholder for common_mp's fx_cash01, and the effect catalog kept the
comma in the model hint, so the edge never bound. Model hints now use the
bare name (AssetRef::bare_name), so fx_cash01 resolves against common_mp.

One model whose packed rows do not match its decoded vertices would make
the packed payload of all effect model geometry Unavailable, and the merged
xmodel lane then drops every xmodel draw (viewmodel, bodies, script models)
for the frame. Such a LOD is now refused and logged when the geometry is
built, and fill_fx_model_plan only draws effect models from geometry whose
Iw4 packed rows cover every decoded vertex.

The player's own first-person shell casings are still skipped by the
render-flag check in fill_fx_model_plan.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:20:19 +08:00
JohnM 2036c3653e Stop models vanishing for two frames when the model lighting cache runs dry
The model lighting cache has 1024 tile slots and keeps a slot for two more
frames after its owner leaves it. Only glass could rewrite its own slot when
it moved. Every other moving owner (awake physics props, players, corpses,
the viewer's own sample) took a fresh slot each frame and so held three.
When the pool ran dry, as it does when many models need a slot at once, an
owner that missed got handle 0 and was not drawn that frame (props, players,
corpses, effect and world models, the viewmodel); a glass pane was drawn
with default lighting instead. One mp_highrise match (2412 dynents) on an
iPhone logged "model light cache alloc failed — remote body skipped" on 14
frames.

WorldModelLightingCache now records which owner each slot was given to, and
an owner that still holds its slot rewrites that tile in place when it
moves. The tile write is queued after every earlier frame's draws, so those
draws still read the old tile. An owner that still misses, one with no slot
of its own, is drawn with the viewer's tile for that frame, and the log line
names it. The viewer's own sample has no tile to borrow, so a miss there
still hides the viewmodel for that frame. A failed light-grid sample still
returns no lighting, as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:01:01 +08:00
JohnM 7ac8c28f8d Rebuild the xmodel merge when effect pieces or dynents start or stop drawing
The merged xmodel lane patches draws in place (the concat path) while its
topology key holds. That key hashed which body, script, missile and item
draws the scene admits, but not whether effect pieces or dynents had any
draws, and a full merge leaves a source with no draws out. So when dynents
went from no draws to some while the merge was in its concat layout, their
draws were spliced into a layout with no room for them: they indexed the
wrong surfaces and shifted the sky ranges behind them. The same happens to
the first effect piece after a frame with none. Whether each of the two has
draws is now part of the occupancy hash, so either transition forces a full
merge.

Effect model geometry is also appended whole instead of compacted to the
surfaces drawn that frame. It holds every prepared model at every LOD and
does not change once built; compacting it dropped the concat layout, so
every frame with a live piece would re-merge and re-upload the whole
vertex buffer.

Effect pieces do not draw yet, so for now only the dynent transition is
reachable; the effect piece half prepares for drawing them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:12:09 +08:00
JohnM e95b40a0c3 Admit the sky model to the xmodel merge only when it has draws
A sky model whose surfaces were all refused still publishes a plan with no
draws. The full merge leaves a source without draws out, but admitted_mask
marked the sky admitted whenever the plan existed. The next concat recopy
then added sky rows the merge never laid out, the packed payload came out
the wrong length, and every xmodel draw (viewmodel, bodies, props) was
dropped for the frame. This repeats on every frame whose vertices change.

The sky now counts as admitted only when it has draws, like the effect
model and dynent sources. Only the T5 and T6 lanes produce a sky model.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:11:45 +08:00
Gh4zi 61b7c43e28 Fix flower pots floating up when woken; walking past moves clutter only
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>
2026-10-09 07:40:52 +03:00
Gh4zi 65a7ce4963 Fix animated models vanishing when the first cell queued for their bounds is not theirs
A scene DObj seen through several cells gets a bounds command per cell visit. The first one
to run bounded the DObj and tested its box against that command's cell; every later command
saw the gate already past idle and returned, so a DObj whose box did not reach the first
cell was dropped even when it reached the next. Terminal's atrium pine
(foliage_cod5_tree_pine05_large_animated) was queued first for the eye's cell from some spots
in the hall and disappeared there.

Later commands now test the bounded box against their own cell until the DObj is visible.

Checked on mp_terminal: the pine shows at 1682 6115 192 (missing before) and 1554 6135 192;
the rooftop tank at 2187 4290 304 still shows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 07:22:07 +03:00
Gh4zi b65454ab88 Fix models disappearing as the player moves; fix red tint on breakable glass
- Map models (Terminal's rooftop tank, boxes and barrels; Favela's laundry) disappeared and
  came back as the player moved, out in the open as well. The DPVS walk visits a cell once per
  visibility portal it is seen through, but only the first visit's clip planes were kept, and
  the cell entity commands culled against those alone, so anything visible only through a
  later portal was dropped. The walk now reports every visit and the cell entity commands run
  once per visit, as IW4 queues them. More visits than the cell queue holds falls back to the
  camera frustum, never to one visit's planes.
- Separately, breakable glass skipped model lighting for a pane whose centre was more than 64
  units off screen, then drew it anyway with lighting handle 0 and reflection probe 0:
  Terminal's wide glass panes showed a red tint with a hard edge. The test now uses the pane's
  own radius.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 03:47:41 +03:00
vtroc7 91217cd0ac Restore native effects and objectives, scope zoom, camouflage and lighting 2026-10-08 22:04:32 +03:00
vtroc7 983fd97853 Publish prepared presentation contracts and predict local bullet impacts 2026-10-07 22:44:14 +03:00
vtroc7 25c008b391 Prepare coherent match assets, native camouflages and server releases
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 20:30:21 +03:00
vtroc7 ea45cf7dcc Preserve native families, soldier hands and T6 world materials 2026-10-07 00:13:36 +03:00
vtroc7 f1f4c07feb Bind prepared runtime assets to their owners and correct T6 rendering 2026-10-06 21:37:31 +03:00
vtroc7 d655b952cb Prepare asset products, restore T6 rendering and select community servers 2026-10-06 15:57:22 +03:00
vtroc7 f026f5fca0 Improve runtime readiness, rendering, audio and Linux game discovery 2026-10-05 23:41:16 +03:00
vtroc7 65052d3f51 Add native T5 audio, Black Ops II maps, independent movement, late join, skill ratings and varied bot loadouts
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.
2026-10-05 13:13:28 +03:00
neptune bb575b897c Tidy the Black Ops II work for review
- 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>
2026-10-03 17:21:51 -04:00
neptune e3ff4be7d1 Give Black Ops II equipment its own effects and sounds
iw4l_t6/equipment plays T6's equipment effects and sounds: team-coloured
lights on bouncing betties, trophy systems, shock charges and C4, the
betty's launch and burst, the trophy's deploy and intercept flashes, the
shock charge's warning and zap, the sensor's scan, EMP fizzles.

T6 effects are captured with every effect they play in turn (runners and
spawned children), and the report names any the converter refuses. T6
rows use their own projectile explosion effect when it was captured. T6
equipment aliases are captured, and T6 aliases record whether they loop
so scripts can play them. Script effects honour hide()/showToPlayer()
(protocol 104), so team lights, and IW4's tactical insertion flares, show
to their side only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 17:53:22 -04:00
neptune f7c3b953ee Merge upstream master (d352dbd) into bo2-weapons
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>
2026-10-02 14:04:01 -04:00
vtroc7 d48a9f6502 Steam MW2 discovery, embedded licences, weapon variants, lock-on launchers, double-barrel fire and a two-client dev-master scenario
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 19:36:24 +03:00
vtroc7 3694c35041 Audio control runtime, typed player accounts, self-updates, thermal and shellshock screens, third person, guided killstreak HUD, player cards, a lobby cheats toggle and god mode
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 15:57:27 +03:00
neptune af8ee254c1 Add Black Ops II weapons, native T6 shaders and Game Folders
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>
2026-10-01 15:56:23 -04:00
vtroc7 bfe3c2aa70 Breath, shields, crossbow, car destruction, remote animation and GSC services
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>
2026-10-01 19:18:44 +03:00
vtroc7 03016c48d6 Script-driven post effects, fog and earthquakes; equipment recovery, akimbo viewmodels, end-game leave and scope edges
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 20:01:29 +03:00
Bulat Fatykh bbdfb7c1b6 One owner for the alpha-test table and three shared constants; drop the unread GameEnded (#15)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 19:54:22 +03:00
vtroc7 56c6d8ebcb Improve equipment, missile guidance, animations and weapon audio
Remove unused weapon summaries and catalog APIs, share model geometry helpers, and consolidate per-frame renderer census resets.
2026-09-30 08:30:12 +03:00
Bulat Fatykh b7f04c53f3 Remove unused runtime code and dependencies 2026-09-30 07:53:22 +03:00
vtroc7 41115ebf53 Keep mixed-device input seamless and stabilize depth-equal rendering 2026-09-30 07:49:50 +03:00
vtroc7 38aa9cf741 Run IW4 match flow, menus and killstreaks from the game scripts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 18:35:44 +03:00
chazmm 7af11e5500 Roughly double no-bot frame rate by cutting per-frame CPU work
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 18:35:44 +03:00
vtroc7 72ee2098da Improve killcams, combat effects, and asset presentation 2026-09-25 00:05:20 +03:00
vtroc7 69cf9ff9fa Prepare weapon presentation and add alternate modes, device feedback and collision fixes 2026-09-24 05:30:17 +03:00
vtroc7 f357ef16be IW5 attachments and weapon overrides, a blood film on the HUD, and team-tinted obituaries
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 23:45:43 +03:00
vtroc7 94e3983bfc Shared common content, prepared weapon families, and one way out of a session
- 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>
2026-09-23 17:10:02 +03:00
vtroc7 52d31f1ee2 A loading screen that says what the load is doing, and a first-person rig prepared once per composition
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 23:28:55 +03:00
vtroc7 b7e00544bb Destructible props, a live scoreboard, and film vision on the console
Destructibles walk their stage staircase on the host: each stage carries
its model, the parts it throws off, the effects it fires on the way out
and the health it bleeds afterwards, and the loops a prop is speaking are
published as sound aliases the client resolves through the configstring.

The scoreboard, overhead names and the compass draw against the live
roster -- team identity survives player-supplied color escapes, ranks and
prestige come out of the menu tables, and the final snapshot is kept when
it lands ahead of the next scores command.

Film vision presets load from the map and common fastfiles; visionSetNaked
and visionReset transition between them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 14:41:01 +03:00
vtroc7 bca31343e5 Bots that fight and take objectives, and glass that cracks into real shards
Host bots bake a navigation graph off the clip map and walk it — drop and
break-glass edges, routes that resume across ticks under a shared per-tick
query budget, firing positions chosen from baked supports rather than a ring
around the bot. They pick a weapon, reload or switch when the magazine runs
out, and plant, defuse and claim flags on their own.

A broken pane now builds a planar crack graph and emits shards carrying their
holes and open cracks, so tessellation and repeated hits read the stored
geometry instead of assuming a convex fan from vertex zero.

Sun cascades are clipped to the view. Class select and the options menu match
the layout players expect. Weapon definitions load from IW5 and T5 fastfiles.

The test suite is removed: it had grown into scaffolding for the dig rather
than a description of the runtime, and new tests will be written against the
behaviour that stayed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 02:49:55 +03:00
vtroc 2fb3e4558b Decode on the loader's own threads and only what is still claimed, and time the age of the presented state.
Image decode takes the pool it runs on as a parameter and every lane hands it
the loader's. `ComputeTaskPool` is the frame's pool, with its own thread count
and its own affinity, so a load stage that decoded on it ran on the frame's
threads and competed with the frame for them. Material compile chunks move onto
the same load pool instead of raw `std::thread::scope` threads: the pool's
workers set their affinity to the process CPUs when they spawn, while a thread
spawned from an `AsyncComputeTaskPool` worker inherits that pool's narrower set.
The compile scope is explicitly non-cooperative, so the calling thread waits for
its chunks rather than ticking the pool's queue.

The `common_mp` FPV plan is held rather than enqueued, and decodes once the
donor plans have merged. `prune_to` drops every demand whose rows the merge
would not fill — the same predicate `apply` uses, so pruning changes when the
question is asked and not what the catalog ends up holding — and
`release_claims` hands the rows back when nothing survives, which is otherwise
`apply`'s job and would leave later stages skipping every name the plan had
claimed. The census counts `pruned_variants` and `pruned_rows` on their own,
apart from duplicate claims and from discards, and the report line carries what
was cut, what is left and what asking cost.

`presented_state_age` and `presented_frames_behind` measure from a render
frame's extract to the render graph's Finish set: how old the state a frame drew
was, and how many main frames had opened since it was taken. They get their own
table in the counter report, because an age divided by a frame is not a share of
one, and a line in the frames section beside main/render overlap — what
pipelining costs, next to what it buys. Both say where they stop: bevy presents
after the graph schedule returns, so the present, the compositor and the panel
are outside, and neither is an input-to-photon latency.

`IW4L_FRAME_LATENCY` sets the surface's `desired_maximum_frame_latency` without
a rebuild. The backend may clamp it, so the manifest records the number asked
for and never a grant this process cannot read back. Env switches now read
through one rule in `perf::switch`: absent, empty, `0`, `false` and `off` are
off. `IW4L_MULTI_DRAW=0` therefore turns the indirect path off instead of
enabling it, which is what a paired run across it needs.

A lightmap page counts the bytes of all six of its images in `handed_bytes`,
`bytes_total` and against the budget pacing the overlay frames, and a slot that
takes another slot's handle no longer counts as having handed anything over.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 00:44:05 +03:00
vtroc 9856f91a98 Share one decode between askers, and time each frame from its own wall.
The split of an image variant into `payload` and `usage` is now what sharing
keys on. A registry holds the texels an archive entry decodes to — the mip
chain in one allocation, laid out as an upload wants it — and the `Image` is
built over them where the row is placed. Two materials that want the same file
under a different colour space or sampler cost one read, one inflate and one
decode, and the second of them a copy of the chain; the last asker copies
nothing, because the decode's own buffer becomes the image's. Asking whether a
name is a cubemap reads the thirty-two byte IWI header out of the entry instead
of inflating the megabyte behind it.

The resident-bytes ceiling is charged per payload rather than per batch, so two
batches pointing at one buffer hold one allocation between them. Load rows
split `produced_bytes` into `prepared_bytes` and `reused_bytes`: only the first
is work, and their sum is what the plan served. The merge census names who won
a disputed claim by plan id, not only that somebody did.

The frame clock closes the row and opens the next at the top of `First`, before
anything else runs, so every main-phase interval falls wholly inside one frame;
the frame the process exits from is closed at exit and its row carries
`partial`. Which spans are a frame's coverage roots is declared by
`Span::coverage_root` rather than read off a thread's stack — an executor is
free to run a schedule's `begin` and its `end` on two workers — and spans a
migration left behind are pruned. A counter measured on another thread is
charged to the frame it ran in through `emit_at`, and a sample that finds no
row is counted rather than moved to whichever frame is open.

`IW4L_PIPELINED_RENDERING=1` runs the render world a frame behind on its own
thread, and it is the only thing the switch moves; the manifest records which
branch a run took. The report gains `main/render overlap`, read off the
intervals rather than off the frame a render stage names as its origin. A
`bevy-trace` build writes bevy's own spans as a Chrome trace, which is the only
place the render graph's submit can be timed from, and
`scheduling.bevy_tracing` says whether a run was one.

Glass keeps its shattered material while damaged, scales the authored UV to it,
picks its shatter effect by whether the piece is landing, and carries the
surface normal on the presentation event.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 16:28:01 +03:00