10 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 c47684e141 Improve native rendering, background menus and community setup 2026-10-12 20:34:48 +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 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 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 25c289bae0 Hold every docs file to the fifty-line limit it claims for itself.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KkgiSVEPTbsVZ1RpARujF6
2026-09-15 01:53:18 +03:00
vtroc 846ab99a73 Rewrite the README around the runtime and clear the dig marks out of docs.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KkgiSVEPTbsVZ1RpARujF6
2026-09-15 01:44:07 +03:00
vtroc 7dcdd6831e Give every loaded population one owner, and publish it without the walk that built it.
The zone walk and the runtime were the same types. A catalog carried the
walk's `Ptr → row` link maps, its half-captured names and its scratch into
the published result, so nothing said the linking was over except a
convention — and the runtime, which has no zone open any more, could not
have used them anyway.

Build and published types are now separate for materials, effects, tracers
and reticles: `MaterialDefinitions`, `FxDefinitions`, `TracerDefinitions`
are what a finished build hands on, `publish` is the only way to get one,
and the pointer lookups and absorbs stay behind on the builder. The
presence those pointers stood in for is one shared type, `AuthoredRef {
slot, alias }`. Every published asset type is free of zone pointers except
`WeaponCombatFx`, which waits on splitting `WeaponRegistry` the same way.
That split also turned up dead code the old types had hidden:
`resolve_after_absorb` looked weapon icons up by pointer after `finalize`
had emptied the map, so every lookup there returned `None`.

Map load is a transaction with one terminal outcome. Preflight assembles a
`MatchInstallPlan` — nothing to publish exists until every check that can
refuse has passed — and any refusal writes `MapLoadFailed` for the request,
including "no drawable world", which used to be a `MatchInstalled` the
lifecycle read as success and the UI read as failure. A canceled walk
returns `MatchLoadOutcome` instead of orchestrating on with empty products.
The match carries one material population (`PreparedMatch.materials`)
rather than reaching for it through geometry that may not exist, and the
transport schema around the boundary — the six `LoadCapture` wrappers,
`PreparedSpawn`, the doubly-owned map facts, `ZoneMemory` held to the end
of install — is gone.

Copies that had no reason to exist: the absorbs that already consume their
donor now move its rows instead of cloning every `ModelSkel` and
`RawXAnimParts`; sim and the dyn-ent physics share one `ClipMeshTables`
behind an Arc instead of each holding a deep copy of the collision.

Ownership on the live side follows the same cut. `SessionCore` takes a full
room identity and revision before any transport effect, so a stale
teardown cannot override a different match key. `HostMatchEvent::Applied`
carries no match key, so the peer's phase is its whole guard — it now
passes before anything is written, instead of landing a retired match's
connection id on the live peer on the way to being refused. `ClipStore` owns every PCM
conversion and every terminal decode failure, with Play/Stop on one ordered
channel scoped by namespace, entity and epoch. `SimContent` holds the
immutable definitions behind a consumed builder, so authority and
prediction share one backing instead of deep-copying per tick. Direct UDP
launch is removed; relay, listen and replay stay.

In the renderer each producer publishes whether its rows actually moved,
and the xmodel merge stops re-hashing seven producers' draws, materials and
vertex counts every frame to find out. Payload fields are `pub(crate)`
behind read-only accessors, so a consumer that wanted to finish a
producer's work no longer compiles. Colour extract is split from the
installed world, scene and shadow get their own bind caches, and record
census stays off the hot refusal path.

Docs: `CONTEXT.md` gains "Before shipping: the scaffolding goes back out",
and `make mr` and `cargo xtask mr` point at it. MAP-LOAD describes the
transaction as it now ends.

Scaffolding: the share and census probes that only proved the split are
out. What stays is five tests, each holding several independent systems to
one claim and each verified to fail when that claim is broken:

  - one alias carried from two-zone capture through absorb, edge binding,
    the alias-chain walk, the prep workers' decode and finally cancel —
    every stage has to mean the same clip by it;
  - a replacement match driven through all three cores that decide whether
    a player is in one (host admission, session view, local load), then
    every event the retired match still had in flight, replayed against a
    live peer, moving nothing;
  - a rejected room view leaving no bridge identity, membership, bootstrap
    or admission effect behind;
  - the seven draw producers published through their own API and asked of
    the consumer that replaced the merge's per-frame hashing: the stamp
    moves for exactly the producers whose rows moved;
  - authority and prediction proved to share one immutable world by
    tracing it, and to keep tracing their own after the other replaces it.
2026-09-13 23:23:58 +03:00
vtroc 0f387098e7 IW4L 2026-09-13 13:52:33 +03:00