Track B. All 21 one-shot cues funnelled through FeedbackFx.PlayClip ->
AudioSource.PlayClipAtPoint, which allocates a GameObject + AudioSource per call
and schedules a delayed Destroy — ~20-33 times a second in light combat. New
OneShotAudioPool is a 32-voice 3D ring behind an UNCHANGED PlayClip signature, so
all 20 consuming call sites are untouched.
Parity is the whole game here: PlayClipAtPoint sets spatialBlend = 1 explicitly (a
fresh AudioSource is 2D) and leaves the rest at stock defaults. Two deliberate
divergences, both forced by the voices being long-lived: playOnAwake = false, and
dopplerLevel = 0 because a pooled voice TELEPORTS between events and would
otherwise pitch-bend. Root is DontDestroyOnLoad (WorldLauncher does
LoadScene(Single) while the client world is alive) with a SubsystemRegistration
reset, or session two rents destroyed voices.
Authored impact VFX are pooled per prefab instead of Instantiate/Destroy per hit:
components cached per INSTANCE (refs are instance-scoped), main.stopAction forced
to None (a prefab set to Destroy silently drains the pool), instances filled under
an inactive root so Awake/Start never run — which is what makes the DestroyImmediate
in StripCosmetic safe — ps.Clear before Play, TrailRenderer.Clear after the
reposition, and a Rented flag as the at-most-once guard against a double Return
aliasing one instance to two callers.
Per-frame allocation: the slash-arc and enemy-wedge mesh builders each allocated
four arrays on every call (up to twice a frame, and once per winding enemy); HUD
and ability-bar labels rebuilt their strings every frame; damage-number fades
rewrote TextMesh vertex colours every frame; health bars pushed uGUI writes
unconditionally; two systems played back an empty EntityCommandBuffer (a
structural-change sync point) every frame.
Also closes an AudioClip leak across all seven clip-owning systems: an
AudioClip.Create'd clip is a standalone UnityEngine.Object, so destroying a
system's FX root left it alive (MusicSystem ~6.8 MB, AmbientAudioSystem ~2 MB per
client-world teardown).
CombatFeedbackSystem's TryHold call sites go with this commit because they share
the file; the camera-side removal lands in the next one.
Verified live: PlayClipAtPoint's "One shot audio" GameObject never appears again
across 270 frames of combat with kills; the VFX pool fills to its retain cap and
stabilises; real cues route through the ring. 304/304 EditMode green.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review-first netcode slice (design review wf_900e9965-8f0 -> 11 folded;
post-impl wf_5c8299f8-299 clean). A PERMANENT periodic telegraphed AoE in
Blight-biome rooms only; one new [GhostField] uint NextEruptTick.
- Geyser component + GeyserEruptSystem (server): inverted invalid-tick guard
(a baked-0 tick must NEVER erupt -> lazy-stamps born-correct instead of the
party-wiping per-tick barrage), inline both-sides gather (SourceNetworkId=-1),
reschedule = now + period (never +=), never destroyed.
- GeyserTelegraphSystem (client): absolute-tick growing warning disc +
erupt burst on the >0->=<0 crossing, latched per NextEruptTick + arm-guard
(never edge-detects the replicated field -> no phantom on 0->stamp /
relevancy re-entry). Reuses ScorchDecalSystem + DynamicLightSystem.
- Seeded in RoomFieldSystem (Blight-gated on plan.Biome, born-correct staggered
stamp from live ServerTick), GeyserFieldSpawner + authoring wired into the
Gameplay subscene. Geyser.prefab duplicated from ResourceNode (no collider).
- BuildDisc promoted to FeedbackFx (shared with the barrel fuse ring).
- 474/474 EditMode incl. the unstamped-storm regression; live no-storm end-to-end.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
All procedural, client-only, observe-only in PresentationSystemGroup, zero
netcode surface (read existing replicated state). Shared FeedbackFx decal
primitives (scorch blob + crack star meshes + transparent decal material).
ScorchDecalSystem: static RequestScorch queue -> pooled fading discs
(mirrors DynamicLightSystem), wired from the barrel boom, reusable by the
geyser. CoverDamageSystem: crack accretion keyed on BlightClutter.Remaining
(Variant 4) + proximity-gated shatter-scorch. RoomDressingSystem: persistent
arena scars on a distinct hash sub-stream, torn down with dressing. Knobs in
DecalConfig. Cover cracks use decals (not URPMaterialPropertyBaseColor) because
the Synty prop shader is not Hybrid-Per-Instance.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Operator feel report: the explosion radius was unreadable and the fuse
too short to react to. Two changes:
- Tuning.BarrelFuseTicks 36 -> 90 (~1.5s): long enough to READ the
danger and walk out, and better for baiting enemies onto a lit
barrel.
- WorldFeedbackSystem draws a pulsing ground DISC at exactly
Tuning.BarrelExplodeRadius under every lit fuse (keyed on the same
replicated Remaining=0-on-a-live-barrel cue as the boom split; one
shared pulsing material; removed via the existing prune path).
Verified live: disc appeared 0.07s after the pop (first fuse
snapshot), persisted to the boom at 1.54s, scale read exactly 3.25 =
the true detonation radius; 470/470 EditMode; console clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 1.5 environmental hazard v1 (design-review wf_2cb10454-fdf: 13
findings confirmed + folded; Build Spec in the vault). ~25% of room
clutter seeds as EXPLOSIVE (Variant 3 on the existing replicated byte
- zero new GhostFields/prefabs/RPCs).
The FUSE is the review's fold - one mechanism closes both HIGHs:
- Pop sites (projectile sweep + isServer-gated melee harvest) do NOT
destroy an explosive: they zero the replicated Remaining + add a
server-only BarrelFuse (~36 ticks). The client sees Remaining=0 on a
still-alive barrel across snapshots -> unambiguous fuse cue, and
booms at despawn ONLY when cached Remaining<=0 - a teardown despawn
carries Remaining>0, so portal-advance teardowns can never fire
false booms (HIGH #1).
- HazardExplosionSystem (server, plain group, presence-gated on
BarrelFuse, never lifecycle-gated) detonates at ExplodeTick: radius
damage to LIVING enemies AND players (boss-slam player filter
verbatim; friendly fire = the bait mechanic), SourceTick stamped at
detonation = the authoring moment (HIGH #2: the authored-tick
contract dash i-frames negate against), SourceNetworkId=-1 (the
environment convention - a player id would consume Charger
whiff-punish windows). Fuse rides the RoomTag'd barrel -> teardown
cleans lit barrels free.
- Lit barrels are unhittable at both snapshot sites (no double-pop).
- Client: WorldFeedback caches Variant -> boom-vs-puff split (big
burst + light flash + boom SFX vs the old puff); DynamicLightSystem
gives Variant-3 barrels a red danger glow that STROBES once fused.
Verified: 470/470 EditMode (4 new: fused pop instead of destroy +
unhittable, both-sides damage w/ -1 source + authored tick, dead-player
+ radius filters, unelapsed-fuse inert); live smoke - seeded 3/8
explosive, real-sweep pop, CLIENT observed the fuse cue on the live
ghost, pinned bait enemy took exactly 26 (30->4), walk-out escape
confirmed; console clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New FeedbackFx static (MakeClip/MakeParticleMaterial/MakeBurst/PlayClip/EmitTinted/EmitAt); the 3 *FeedbackSystem copies + AmbientAudio.MakeSting now route through it via 'using static'. MakeBurst takes the FX-root + the per-use gravity/radius/sizeTail that were the only diffs between copies; MakeClip folds in noise + decay. Behaviour-identical by construction (every particle/clip param preserved exactly).
459/459 EditMode tests pass; compiles clean. VFX are presentation-only (no EditMode coverage) -> wants a Play-mode smoke to eyeball hit/death/harvest/structure bursts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rebuild the in-game HUD on UI Toolkit (HudUi/HudSystem, Aether palette) consistent with the menu; build-palette bar (BuildPaletteState) drives cursor->cell ground-ghost preview (green/red via BuildPreviewMath), left-click place / right-click cancel / rotate; fire suppressed in build mode; combat juice restyle. +4 BuildPreviewMath EditMode tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>