Boon overhaul CODE-COMPLETE (mechanic-changers): design forks locked, pre-code review (11 findings folded), post-impl review (incomplete on a session limit — raised findings self-verified, 2 real bugs fixed). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
21 KiB
title, date, tags, permalink
| title | date | tags | permalink | |||||
|---|---|---|---|---|---|---|---|---|
| Iteration 2026-07 — Co-op Hades Conversion (Trunk + Hub-ification + Depth + Blender) | 2026-07-06 |
|
gamevault/06-roadmap/iteration-2026-07-coophades |
Iteration 2026-07 — Co-op Hades Conversion
Operator decision (2026-07-06, dev-loop iteration session): commit the Fix-the-Fight-in-Place trunk PLUS the full
Co-op Hades direction — cut/mothball the tower-defense layer, base becomes a Hades-house hub, boons become
mechanic-changers, kit gains a second ability, real node types, second boss, co-op revive. Depth folds in now (not
after a playtest gate). Blender scope: hero props + decals. No time estimates (operator directive). Grounded by a
9-agent analysis workflow (wf_8afc6e5a-b9e, 9/9 clean) + a live end-to-end play tour with screenshots
(Assets/Screenshots/iter_*.png).
Evidence base (why this direction)
- Live tour findings: half of all rooms (sub-slot X+1500) have no ground/colliders/decor; enemies interpenetrate
into a blob and spawn converges on the player; HUD header reads "AT BASE" inside expedition rooms; boon offer
contained a strictly-dominated pair (-25% vs -15% ability cooldown); portal beacon renders as a blown-out white egg;
storage crate floats; save-persisted
RunRuntime.WasAllReady=1deadlocks the next session's launch (un-ready → re-ready is the only escape). - Critique consensus: every reward is a flat stat mod (zero mechanic-changers/synergies); kit = 3 verbs/class with 1 distinct ability; run 2 ≡ run 1; threat is walk-out-able (boss slam escape needs 4.07 u/s vs 5.1 available; melee knockback stunlocks all trash; death = free heal + re-conscription); the boss is a 1.6× Charger with one attack. The code-side feel layer (cones, slash arcs, hit-stop, flashes) is STRONG — the gap is the asset/scene layer under it.
- Market: Windblown's chart-topping demo = 1 biome + 1 boss (loop is demo-sized already); Cult of the Lamb = the base↔run tie done right, Moonlighter = the cautionary tale; HoH2's retention lever = every run banks something; Synty-look ceiling proven by Death Scourges / RoR2 / Soulstone Survivors (dynamic-light-first, dark ambient).
Phase 0 — Stabilize (bugs found live, do first)
- Commit the working-tree portal fix (incl. the
_portalMatcomment-swallow NRE repair applied 2026-07-06 — the NRE killed CombatFeedbackSystem every session and auto-paused the editor via Error Pause). Re-run 456 EditMode first. RETRACTED (2026-07-06): misdiagnosis caused by frozen-world polling (theWasAllReadysave deadlockexecute_codemain-thread-sleep hazard) —CycleDirectorSpawnSystem's restore buildsRunRuntimefresh (HostSalt only, WasAllReady=0) and nothing persists it; the observed "deadlock" was a run that had already launched between MCP calls. Lesson reinforced: never sleep-poll; checkisPausedfirst.- Lifecycle-aware HUD header (kill "AT BASE" in rooms; kill stale "choose your boon" after pick — the location-line switch had NO RoomExplore case, so the RoomReward text stuck through the loot window).
- Ground the floating storage crate (root cause:
GridOrigin.y=1is the CC capsule-center plane —CellToWorldreturns it; center-pivot meshes (Turret/Wall) look grounded there, base-pivot meshes (crate) float 1 u. Watch this on every future grid-placed base-pivot mesh); tame the portal-beacon HDR (2.6/3.4 bloomed to a white egg) + ground the beacon (itspos.ywas the capsule plane too).
Phase 1 — Trunk (direction-agnostic physical/feel/teaching layer)
- Rooms become places: fix the X+1500 void (ground + collider ring + decor for sub-slot 1); seed 3–6 collidable Environment-layer props per room so cover/LOS/Charger-baiting exist; readable room edge.
- Enemy separation (server-side repulsion, MaxAlive=12 so O(n²) is fine) + soft player pushout; no standing inside the boss. Verify spawn ring staggering reads (spawn VFX).
- Animation triage: Synty Sword/Bow Combat anim packs (shared Generic skeleton, no retarget) — death clips + corpse window, spawn, hit-react, ranged-fire, dash; creature locomotion for monsters (stop human jog on Husks).
- Threat repair: poise byte (light hits stop stunlocking trash); boss second attack (re-enable its baked Charger lunge) + party-size HP scaling.
- Live knobs: promote all Boss*/enemy/grace-timer knobs into the TuningConfig overlay + values-to-clipboard.
- Teaching: RMB class ability + dash coach-marks; fix stale copy (StartingOre 50→90 etc.); run-failed banner.
- Clarity swaps: distinct spit/pickup/harvest meshes (Synty interim), class weapon meshes on the hand bone, ground darkening + character rim/outline, point lights on projectiles (RoR2 trick).
Gate: one honest solo campaign to Victory + one 2-instance LAN lap with the overlay open.
Gate outcome (2026-07-07 operator playtest): trunk holds mechanically, but the verdict is "not cohesive, very static, visually boring — comparable games' environments are dynamic and interactable" + ability upgrades boring + the 07-07 harvest shrink/pop never showed on-screen (root cause later pinned same day: a swallowed
[RuntimeInitializeOnLoadMethod]attribute — NOT the pre-flagged PTM-on-root risk, which live-verified correct). → Phase 1.5 (World Alive) inserted below; mechanic-changer boons PULLED FORWARD from Phase 3 (Phase 1.7). Explicit operator framing: make the game look better, not more "juice" — the code-side hit-feel layer stays as-is.
Slice B folded design (design-review wf_fd177263-b67, 2026-07-06 — 3 lenses done, 15 verify verdicts ALL isReal=true; synthesis died on session limit, folded by hand from the verified findings)
- B3 Dying window: server-only
Dying{uint UntilTick}(TickUtil.NonZero, stamp ONCE on the 0-crossing in HealthApplyDamageSystem for EnemyTag; destroy after ~54 ticks via Temp ECB). At the mark: zero the REPLICATEDAttackWindup, disableIsLunging, zeroKnockbackState(else corpses keep live telegraphs). CONFIRMED: no AI pass self-health-gates today and EVERY count edge counts entities — gate the actor passes (EnemyAI/BossAI move, windup, contact) and make every count LIVING-only: RoomEnemyDirectorSystem :48/:68 (room clear + MaxAlive fit), ExpeditionObjective.Remaining, boss-summon cap, base-siege cleared checks, aggro snapshots, ProjectileDamageSystem :83-91 target snapshot + gamepad auto-aim (no Health>0 filter today — corpses become shields/aim magnets). Client: EnemyAnimationDriveSystem writesIsDead = Health.Current<=0(param exists, never written); CombatFeedbackSystem fires the kill CRUNCH at the 0-crossing (today it fires at prune — would land ~1 s late), prune keeps only a cleanup puff; hide health bars at <=0. - B1 separation: a pass INSIDE EnemyAISystem (sole-position-writer invariant; BossAISystem only has [UpdateAfter(EnemyAISystem)]). Pairwise among LIVING enemies, skip lunging/knocked/Dying receivers, boss immovable (others push out of its radius), displacement through the swept EnemyMoveUtil move (no wall-shoving). Player pushout radius SMALL (< melee range, ~HitRadius+0.35) or grunts can't strike + Spitter cornered-hold re-breaks.
- B2 poise: the windup-cancel is the knockback CONTINUE branch (EnemyAISystem :119-133 grunt, :234-248 charger).
Threshold on the EXISTING
KnockbackState.Speedchannel (no per-kind data): below it, kb velocity nudges but the windup/lunge survives; at/above it, stagger as today. Make the finisher + Warrior cone stamp a higher kb Speed so the channel actually distinguishes (light 6 / heavy 9, threshold ~7). - B4 boss lunge: BossState gains a server-only attack byte; lunge = reposition move (no unique damage — the
slam stays the damage beat). Telegraph rides
AttackWindup+ the boss's already-bakedIsLungingghost bit; the client boss-ring override SKIPS the slam ring while IsLunging (draws the standard Charger lunge tell). The windup-elapse branch keys on the state byte (today it would deal SLAM AoE on any elapse). - B5 party HP scale: in the RoomEnemyDirectorSystem boss branch (sole spawn site), scale Health by LIVING EXPEDITION players (RegionTag+Health>0), NOT RunParticipant (dead-respawned keep the tag at base).
- B6 run-failed banner: client-only; cache Charge + a wentInRun flag at launch; on the (in-run)->Staging transition with Charge unchanged -> "EXPEDITION FAILED" banner. NEVER key on Returning (1-tick transient, and the bank lands one tick after it). Launching->Staging aborts don't count (wentInRun gate).
- B7 fire-anim pulse: stateless absolute window derived from AbilityCooldown (the SwingActive idiom) — no cached edges (rollback/join-unsafe).
- Hygiene: bytes not enums in Bursted systems; no new [UpdateBefore/After] edges; ~54-tick window + stagger threshold + separation strength as live TuningConfig knobs. ⚠ Bursted query-set edits on an UNFOCUSED editor can leave a stale Burst binary — have the editor focused for the compile, or expect the restart cure.
Phase 1.5 — World Alive (inserted 2026-07-07 from playtest verdict; visual + dynamism, explicitly NOT juice)
Operator interactivity scope (all four selected + two write-ins): breakable clutter with drops · environmental hazards · cosmetic reactivity + ambient motion · destructible cover · collision precision · more distinct attacks/animations/effects. Art direction deliberately UNDECIDED — lighting pass first, then pick (see gate).
Stabilize first (bugs, do before the pass)
Node harvest feedback fixFIXED (2026-07-07 session B). Root cause was NOT the pre-flagged PTM-on-root risk — live inspection proved the Model child properly parented and root-PTM propagation exact (root PTM 0.783 → child LTW 1.723 = 2.2×0.783). The 07-07 knob edit had swallowed the[RuntimeInitializeOnLoadMethod]attribute offWorldFeelConfig.ResetDefaults→Enabled=false→ the WHOLE feedback slice (shrink/pop + chips + SFX + micro-punch) silently dead. One-line restore; verified on-screen + numerically on a live server-spawned node; 455/455. Operator still eyeballs a real harvest in the next playtest.Collision precision passDONE (2026-07-09, gate-approved incl. missing-collider adds).ColliderFitTools(Editor, audit/apply) refit everything to the Game.unity visuals: rings rebuilt 16/24/24→54/82/82 fine segments fitted to torso-band cliff vertices; cover = convex MeshColliders of the actual rock meshes (needed Read/Write on 2 PNB meshes — new CLAUDE.md gotcha); landmarks hint-matched OBB fits; 11 solid-prop colliders added (tree/turbine/crates/dish/solar). Verified in the baked CollisionWorld (ring closure, cover 8/8 solid, server==client parity) + enemy backstop re-validated live (embedded enemy depenetrates out of a cover hull and keeps moving). Operator feel-lap still pending. See 2026-07-09_B4d_Tail_Collision_Grounding.
Short-term wins (asset/scene/client layer)
Lighting/atmosphere passDONE (2026-07-09,414f9ff62) — dark ambient + DynamicLightSystem (projectile/portal/node/impact-flash lights) + landmark mood lights + per-biome dark palettes; found+fixed the dead Linear-fog density knob. ART LOOK LOCKED (operator, 2026-07-09): CLEAN DARK-SYNTY — pixel filter OFF ("everything feels smoother & sharper without it"); the PixelOutline feature stays dev-toggleable (F3) with_MasterEnabled=0shipped. Operator is open to experimenting with OTHER fullscreen/shader effects later (sharpen/vignette/grade variants — backlog). Every later visual choice keys off clean dark-Synty.- Ambient motion layer (client-only, zero netcode): foliage sway/rustle on walk-through, per-biome dust/embers/fog drift particles, critters that scatter, flags/banners. Biggest bang-per-effort for "not static".
Breakable clutter with dropsDONE (2026-07-09,53bc21143) — the BlightClutter chain already existed end-to-end (seeding/unified-sweep/drops); the gap was feel: barrels (SM_Prop_Barrel_01) replace the rock chunk, ONE-hit pop (Remaining 8→2), density 6→8/room. Live-verified pop + drop credit.- Attack distinctness — CODE-SIDE DONE (2026-07-09,
a335ca3f2): per-kind telegraph colours (shapes were already per-kind), per-kind windup voices, ownership-keyed projectile lights. The anim-side depth (per-kind clips, creature locomotion — still open from Phase 1.3) rides the parallel Blender workstream.
Long-term (server-sim; adversarial design-review REQUIRED per slice)
- Environmental hazards — v1 SHIPPED (2026-07-10,
cd607ae15, review-firstwf_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. - Destructible cover — SHIPPED (2026-07-10,
bbf418e77, review-firstwf_e14dd739-069): PHASE 1.5 IS COMPLETE. Cover = BlightClutter ghosts (Variant 4) with baked env-layer colliders — genuinely block (the anti-stuck nudge is now cover-aware) until carved (8 hits, zero yield — deposit decoupled from durability); no cover in Boss rooms; backstop re-validated live (block/depenetrate/carve all proven). Follow-ups: Charger smashes cover; true projectile-blocking. See Destructible_Cover_Build_Spec.
Phase 1.5b — World Alive II (operator expansion, 2026-07-10; ALL four bundles locked)
Post-1.5 operator verdict: barrels fixed (radius disc + 1.5 s fuse, eb7f57216) but "the ground is very
plain" — expand 1.5 before 1.7. Locked bundles, sequenced ground-first:
- ✅ Ground bundle (SHIPPED
2fc5ae9a1): (a) material pass — real tiling (22×/26×) + Synty normals + generated LINEAR macro-noise detail textures w/ baked rim vignette (★ an sRGB-imported detail map mul2x DARKENS 2.3× — import detail albedo LINEAR); per-room-biome ground tint via MPB insideWorldAtmosphereSystem; (b)RoomDressingSystem+RoomDressingConfig— 26 seeded biome-flavoured props per room inside the room's ACTUAL shape (hash stream 0xD2E55; 47 build-safe prefab refs), room-torn-down; live-verified incl. teardown + exact Meadow tint convergence; (c) worn paths storage→warpgate/base-gate; (d) 357 base flora re-enabled (buildings/pond/FX stay parked). - ✅ Decals (SHIPPED, Part P — all procedural, client-only, zero netcode): explosion scorch pool
(fading disc pool via
ScorchDecalSystem.RequestScorch, wired from the barrel boom; reusable by the geyser) · cover damage-CRACKS keyed on replicatedBlightClutter.Remaining(Variant 4) + proximity-gated shatter-scorch · light room-arena crack/scorch scars (viaRoomDressingSystem). ★ The specifiedURPMaterialPropertyBaseColordarken would have silently no-op'd — cover's SyntyGeneric_Basicshadergraph declares_BaseColorUnity-Per-Material, NOT Hybrid-Per-Instance (only the DOTS-authoredAnimatedLitShaderhonours the EG per-instance override); operator fork → decal quads instead. Base POIs skipped (Part O baked their wear). Knobs inDecalConfig. - ✅ Hazard variant — Blight geyser (SHIPPED, Part Q; review-FIRST
wf_900e9965-8f0→ 11 folded, post-implwf_5c8299f8-299clean): a PERMANENT periodic both-sides telegraphed AoE, Blight-biome rooms only (operator forks). ONE new[GhostField] uint NextEruptTick; serverGeyserEruptSystem(INVERTED invalid-guard- lazy-stamp — a baked-0 tick must NEVER erupt; reschedule
=now+period), clientGeyserTelegraphSystem(absolute-tick disc + latched/armed crossing burst — NEVER edge-detect the field; reuses bundle-2 scorch). Seeded inRoomFieldSystem(born-correct staggered), spawner wired into the subscene. 474/474 + live no-storm end-to-end. See Geyser_Build_Spec.
- lazy-stamp — a baked-0 tick must NEVER erupt; reschedule
- ✅ Critters + weather beats (SHIPPED, Part R): client-only
AmbientLifeSystem(+AmbientLifeConfig) — fleeing bug/bird pool (dart out of the flee radius = the scatter beat, biome-tinted), drifting cloud-shadow discs, and Blight-room-only double-blink lightning flash + thunder (dedicated flash light, no RenderSettings conflict). Reuses theFeedbackFxdisc/scorch primitives; 474/474 + live-verified at base.
Phase 1.5b COMPLETE (all four bundles shipped). Gate: the "no longer static" lap, now with ground + decals
- geyser + critters/weather judged explicitly (the biome-gated beats — geyser erupt, Blight lightning — seen in a real Blight room).
Gate: operator playtest says "no longer static"; node harvest feedback visibly works; art direction LOCKED.
Phase 1.7 — Boon overhaul (PULLED FORWARD from Phase 3) — ✅ CODE-COMPLETE 2026-07-12
SHIPPED (2026-07-12, review-first wf_c4bdd60d-7b2 11-finding + post-impl wf_d2a0a673-af5): 8 mechanic-changers +
4 stat boons on a NEW per-player replicated BoonEffects (SendToOwner): projectile pierce / split / ricochet
(Ranger), detonating finisher (Warrior), blade dash (trail damage), gravity pull (knockback→pull), siphon
(on-kill heal) + frenzy (on-kill cooldown surge, both). Offers gained dedup + dominated-offer protection + light
build-bias (Family tags). 488 EditMode green + Play smoke server==owner-client. Operator forks (this session):
ability-swap boons DEFERRED to Phase 3 (content-thin + AbilityRef→class coupling); synergy = tags only (no bonuses).
See DR-047_Phase17_Boon_Overhaul_Mechanic_Changers · Boon_Overhaul_Build_Spec · 2026-07-12_Phase17_Boon_Overhaul.
Gate: operator feel/balance playtest — two consecutive runs feel different from boons alone (knobs to tune: fork cap 8, dash-trail radius/dmg 1.6/12, frenzy 240t/-0.30, siphon 8, finisher radius 3.5).
Phase 2 — Hub-ification (structural; adversarial design-review REQUIRED before coding)
- Mothball, don't delete: sieges/CoreIntegrity/turret-ammo retired from the flow via baked toggles (the
ScheduleEnabledpattern); code + tests keep compiling for reversibility. - Win condition moves fully into the expedition (N boss-clears / final-boss Victory;
GoalReachedSystem+RunOutcomerework; SaveData v7 additive). - Base = hub: class/prep/meta/ready + deposit; visible growth (unlocks at Charge milestones); staging HUD → progressive disclosure (5 dense panels → contextual).
- Economy simplification (4 currencies is bureaucracy; turret-ammo Charge frees up) — scope at the design review.
Gate: returning player goes staging→launch in <60 s; hub reads as prep+growth, not friction.
Phase 3 — Depth (folded in now; design-review per netcode-heavy slice)
- Kit: second ability slot + one new active per class (reuse AbilityRef catalog + predicted-input review).
BoonsMOVED to Phase 1.7 (pulled forward 2026-07-07 — operator playtest called flat-stat upgrades boring).- Real node types: Elite (affixed alphas via the boss spawn-stamp pattern), Shrine (combat-free choice), Survive, Cursed.
- Second boss chassis (Spitter artillery) so lap 2 differs.
- Co-op: downed/revive (ex-MC-5), duo boons, party-scaled spawns/HP; death-cost design lands here (with revive in, death = run stakes, killing the suicide-heal exploit).
Gate: two consecutive runs feel different (build + path + boss); a duo playtest yields a clutch-revive moment.
Phase 4 — Blender workstream (parallel from Phase 1; hero props + decals)
Portal gate ring · hub Core crystal centerpiece · boss bone-socket armor/spike kitbash (no new rig) + second-boss silhouette parts · distinct projectile/pickup/harvest meshes · class weapons · ground decal/telegraph quad set. Pipeline (validated + researched): UV new geometry onto the existing Synty atlas for style match (or Imphenzia palette PNG); FBX for anything skinned (glTFast Mecanim-clip issues), glb via gltfast for statics; Apply Scalings = FBX Units Scale; Key All Bones for clips; realize geo-nodes instances before export; Play-verify materials (dark-frame hazard).
Phase 5 — Dev tooling (woven through)
New DebugOps: KillRoom (death-path kill — ClearEnemies destroys without kill credit), SkipToRoom/SpawnBoss, GrantBoon,
run-state line in the overlay · pause-proof screenshot rig (MCP bridge ScreenshotUtility calls EditorApplication.Step()
and leaves the editor PAUSED — unpause after every capture; never Thread.Sleep-poll in execute_code, it freezes the
sim) · encounter-composition buttons in DevSandbox · WasAllReady regression test.
Consolidation notes
Supersedes the DR-042 "final beat = base siege" lock (win moves fully expedition-side). DR-034 Core / EB-1/2 siege systems → mothballed, not deleted. The "present forks" ritual re-runs at each phase's design review.
2026-07-07 restructure (Phase 1 gate playtest): Phase 0 + Phase 1 SHIPPED (commits 7c1fee097…cc2e7ad95, incl.
Blender clips, sword combo, pixel-art render style, enemy-stuck fix, markers, harvest feedback). Gate playtest verdict
= static/boring world → Phase 1.5 World Alive inserted (stabilize: node-feedback fix + collision precision; short:
lighting→art-look gate, ambient motion, breakables, attack distinctness; long: hazards + destructible cover, review-first)
and boons pulled forward to Phase 1.7. Phase 2 (hub) now follows 1.7. Order: 1.5 → 1.7 → 2 → 3 → 4/5 parallel.