Docs: exploding-barrels Build Spec + session log Part J + roadmap tick
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: Exploding_Barrels_Build_Spec
|
||||
type: note
|
||||
permalink: gamevault/03-design/exploding-barrels-build-spec
|
||||
---
|
||||
|
||||
# Exploding Barrels — Build Spec (Phase 1.5 hazard v1, design-review-hardened)
|
||||
|
||||
Review: `wf_2cb10454-fdf` (3 lenses, 23 agents, 13 findings CONFIRMED / 3 refuted; the first run lost 8
|
||||
verifiers to a session limit and was resumed from cache — the [[workflow-agent-quota-failures-look-clean]]
|
||||
protocol held). This spec is the fold; it supersedes the pre-review draft.
|
||||
|
||||
## The core mechanism: the FUSE (one fix for both HIGHs)
|
||||
|
||||
On pop the barrel does NOT die. The server zeroes the barrel's REPLICATED `BlightClutter.Remaining` and adds
|
||||
a server-only `BarrelFuse { uint ExplodeTick }` (`TickUtil.NonZero(now + Tuning.BarrelFuseTicks≈36)`). The
|
||||
client therefore sees `Remaining==0` on a still-alive barrel across multiple snapshots → an unambiguous
|
||||
"about to blow" cue, and the boom-vs-puff choice at despawn keys on the CACHED `Remaining<=0` — a room-
|
||||
teardown despawn carries `Remaining>0` → **no false booms** (HIGH #1: despawn-inference is cause-blind;
|
||||
players stand in torn-down rooms through RouteSelect — RunDirectorSystem.cs:247-251, WorldFeedbackSystem
|
||||
prune :96-119). Detonation is the AUTHORING moment → `DamageEvent.SourceTick = TickUtil.NonZero(detonation
|
||||
tick)` honors the authored-tick contract dash i-frames negate against (HIGH #2; DamageEvent.cs:20-24).
|
||||
The fuse also: dissolves the melee self-hit complaint (pop → step out), creates the bait loop (lure enemies
|
||||
onto a lit barrel), and — because the fuse lives ON the RoomTag'd barrel — room teardown/Staging sweep
|
||||
clean fused barrels for free (the orphaned-ExplosionEvent lifecycle findings dissolve).
|
||||
|
||||
## Server
|
||||
|
||||
- **Seeding** (RoomFieldSystem clutter loop): `bc.Variant = crng.NextFloat() < 0.25f ? (byte)3 : (byte)(i % 3)`
|
||||
(seeded rng, deterministic; variants 0-2 stay cosmetic).
|
||||
- **Pop sites** (BOTH: ResourceHarvestSystem projectile sweep; MeleeComboSystem isServer-gated harvest block):
|
||||
gate on `isClutter && Variant==3` INSIDE the destroyed-bitset guard (nodes share the packed arrays with
|
||||
Variant slot 0 — confirmed LOW). On rem<=0 for an explosive: mark destroyed[i] (unhittable this tick),
|
||||
`SetComponent(BlightClutter{Remaining=0,...})` + `ecb.AddComponent(BarrelFuse{ExplodeTick})` — NO destroy.
|
||||
Both target snapshots SKIP entries with `Remaining <= 0` (a fused barrel is not hittable → no double-pop).
|
||||
- **`HazardExplosionSystem`** (new, ProjectM.Server, plain `SimulationSystemGroup`, NO ordering attributes,
|
||||
NO lifecycle gating — a fused barrel must always drain (confirmed LOW: never RequireForUpdate-gate it);
|
||||
`TryGetSingleton<NetworkTime>` invalid → skip tick, fuse persists): query `(BarrelFuse, LocalTransform)`;
|
||||
when `ExplodeTick` elapses (NetworkTick.IsNewerThan semantics): radius scan (XZ, `Tuning.BarrelExplodeRadius
|
||||
≈3.25`) — players via the BossAISystem:62-70 gather VERBATIM (`Health>0 && RegionTag==Expedition`; confirmed:
|
||||
dead players persist at death pos for DelayTicks) + enemies (`EnemyTag && Health>0`, excludes Dying corpses)
|
||||
→ `AppendToBuffer(DamageEvent{ Amount=Tuning.BarrelExplodeDamage≈26, SourceNetworkId=-1, SourceTick=
|
||||
TickUtil.NonZero(now) })` → `ecb.DestroyEntity(barrel)` (single destroy site).
|
||||
**SourceNetworkId = -1** (environment convention — confirmed: a player id would score+consume Charger
|
||||
whiff-punish windows via HealthApplyDamageSystem:102, the sole reader).
|
||||
- **No chain reactions** v1 (clutter has Remaining, not Health). Damage numbers as `Tuning` consts v1;
|
||||
promote to TuningConfig knobs when the knob-table extension is worth it (confirmed-LOW tension, deferred
|
||||
deliberately — noted here per [[ask-before-deferring-during-implementation]]: the overlay knob table is a
|
||||
separate mechanical slice).
|
||||
|
||||
## Client (all new work — confirmed: NO existing per-variant path; Variant is read by zero client systems)
|
||||
|
||||
- **WorldFeedbackSystem**: add `Variant` to the Cache struct; at prune, `IsClutter && Variant==3 &&
|
||||
Remaining<=0` → BIG boom (burst + `DynamicLightSystem.RequestFlash` large orange + low boom SFX); else the
|
||||
existing small puff. Teardown despawns (Remaining>0) keep the puff.
|
||||
- **DynamicLightSystem**: Variant==3 barrels get a red glow light (node-glow pattern); when the cached
|
||||
`Remaining<=0` (fuse lit) the glow strobes hard — the flee cue. (Body tint via URPMaterialPropertyBaseColor
|
||||
on LEG children = polish, deferred.)
|
||||
|
||||
## Tests
|
||||
|
||||
- ResourceHarvestSystemTests: explosive pop → BarrelFuse added, Remaining==0, entity ALIVE; fused barrel
|
||||
not re-hittable.
|
||||
- New HazardExplosionSystemTests: elapsed fuse → DamageEvent(Amount, SourceNetworkId=-1) on in-radius living
|
||||
enemy AND living player, dead player skipped, out-of-radius skipped, barrel destroyed once; un-elapsed
|
||||
fuse → nothing.
|
||||
|
||||
## Wire/bake classification
|
||||
|
||||
ZERO new [GhostField]s / ghost prefabs / RPCs; `BarrelFuse` is server-only; Variant==3 rides the existing
|
||||
replicated byte. No new ordering edges. Re-bake: none (code + seeded-value only).
|
||||
@@ -145,8 +145,11 @@ attacks/animations/effects**. Art direction deliberately UNDECIDED — lighting
|
||||
|
||||
### Long-term (server-sim; adversarial design-review REQUIRED per slice)
|
||||
|
||||
7. **Environmental hazards:** exploding barrels, Blight geysers, trap tiles — damage BOTH sides so enemies can be
|
||||
baited into them. Real combat interplay; replication + predicted-damage surface needs the review.
|
||||
7. **Environmental hazards — v1 SHIPPED (2026-07-10, `cd607ae15`, review-first `wf_2cb10454-fdf`):**
|
||||
exploding barrels — ~25% of clutter seeds explosive; pop lights a ~0.6s FUSE (replicated Remaining=0 =
|
||||
the client cue, strobing red glow) then radius-damages BOTH sides (bait mechanic; escapable). Zero new
|
||||
replication. Geysers/trap tiles = later hazard variants on the same HazardExplosionSystem chassis.
|
||||
See [[Exploding_Barrels_Build_Spec]].
|
||||
8. **Destructible cover:** in-room cover rocks take damage and crumble (Charger smashes through, players carve LOS).
|
||||
Structures already have Health; **re-validate the enemy stuck-fix backstop when cover can disappear mid-fight.**
|
||||
|
||||
|
||||
@@ -214,14 +214,28 @@ Verified live: a 12 s combat histogram showed zones rendering K0+K1 materials ke
|
||||
Client presentation file that only used Simulation types before). Remaining distinctness depth (per-kind
|
||||
anim clips, creature locomotion) rides the parallel Blender workstream.
|
||||
|
||||
## Part J — exploding barrels SHIPPED (`cd607ae15`; 07-10, session continued past midnight)
|
||||
|
||||
The 1.5 long-term hazard v1, **review-first as mandated**: 3-lens adversarial workflow `wf_2cb10454-fdf`
|
||||
(23 agents; the first run lost 8 verifiers to the session limit — resumed via `resumeFromRunId`, cache
|
||||
replayed, 13 findings CONFIRMED / 3 refuted; Build Spec kept at [[Exploding_Barrels_Build_Spec]]).
|
||||
**The fold: the FUSE** — one mechanism closed both HIGHs (despawn-inference false booms on room teardown ·
|
||||
the SourceTick authored-tick contract): pop → replicated `Remaining=0` on a still-alive barrel + server-only
|
||||
`BarrelFuse` (~36 ticks) → detonation damages LIVING enemies AND players (boss-slam filter verbatim,
|
||||
`SourceNetworkId=-1`, SourceTick at detonation) → single destroy. Client: boom-vs-puff keys on cached
|
||||
`Remaining<=0` (teardowns carry >0 → no false booms); Variant-3 barrels get a red glow that STROBES when
|
||||
fused. ~25% seeding on the existing replicated Variant byte — **zero new GhostFields/prefabs/RPCs**.
|
||||
Verified: 470/470 (4 new tests) · live smoke: client OBSERVED the fuse cue on the live ghost, pinned bait
|
||||
enemy took exactly 26 (30→4), walk-out escape confirmed (fuse is escapable by design — first unpinned bait
|
||||
simply left the radius) · console clean.
|
||||
|
||||
## Next-session intent
|
||||
|
||||
**Phase 1.5 short-term wins are COMPLETE** (collision ✓ lighting ✓ art-look ✓ ambient motion ✓ breakables ✓
|
||||
attack distinctness ✓). Next: either the 1.5 long-term slices (**environmental hazards** / **destructible
|
||||
cover** — BOTH adversarial design-review-first, and cover must re-validate the enemy backstop) or jump to
|
||||
**Phase 1.7 boon overhaul** (~12 mechanic-changers; design review required — replicated ability swaps).
|
||||
Operator gate: a feel-lap over the whole 1.5 package ("no longer static"?) decides. Queued taste items:
|
||||
re-enable curated base flora · arid brightness · craters call · B5 split-panels smoke.
|
||||
Phase 1.5 remaining: **destructible cover** (the last long-term item — design-review-first, MUST re-validate
|
||||
the enemy stuck-fix backstop when cover can vanish mid-fight) → then the 1.5 gate lap → **Phase 1.7 boon
|
||||
overhaul** (design review required — replicated ability swaps). Queued taste items: re-enable curated base
|
||||
flora · arid brightness · craters call · B5 split-panels smoke · barrel VFX polish (authored explosion
|
||||
prefab instead of the procedural burst).
|
||||
|
||||
Related: [[Iteration_2026-07_CoopHades]] · [[2026-07-07_Workflow_Consolidation]] ·
|
||||
[[2026-07-07_Expedition_Enemy_Stuck_Harvest_Feedback]]
|
||||
|
||||
Reference in New Issue
Block a user