MC-1 fun-gate PASSED (kill-switch cleared); MC-4 built as the combo-chain melee primary-verb variant, both adversarial reviews folded in. Roadmap MC-1/MC-4 status updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.4 KiB
date, type, tags, permalink
| date | type | tags | permalink | ||||||
|---|---|---|---|---|---|---|---|---|---|
| 2026-06-10 | session |
|
gamevault/07-sessions/2026/2026-06-10-mc4-combo-melee |
MC-4 — Combo-chain melee as the PRIMARY verb (code-complete; fun-gate pending)
Implements DR-030_MC4_Combo_Melee_Primary_Verb. Direction Path_to_Fun (MC-4) · DR-028_Combat_Primary_Verb_Depth_First · combat-first-depth-before-breadth. MC-1 PASSED its fun-gate this session (operator: "It's fun — the dash feels fine") → the project kill-switch is cleared, the combat thesis holds, depth continues. Status: all code + 294/294 EditMode + Play-validation done; the MC-4 FUN-GATE (feel pass) is the open operator item.
MC-1 fun-gate: PASSED
The first action was the MC-1 feel gate (the kill-switch). Operator confirmed the dash feels right and the duel is fun — DR-028's literal "spacing/timing matters and we didn't want to stop" sign-off. Recorded here as the milestone event; MC-1 is now genuinely done (was code-complete-but-ungated per 2026-06-09_MC1_Implementation / 2026-06-10_MC0_TuningConfig_LiveTuning).
What was built (the full uncommitted slice)
The operator chose, from a 4-option ladder, the combo-chain Attack shape and melee = PRIMARY verb (ranged demoted). Hades-like. NEW: MeleeConeMath (pure collect-all cone predicate — AutoTarget's exact range+bearing test, lifted as a bool because AutoTarget.Resolve is a single-winner reducer), MeleeCombo (predicted owner-replicated [GhostField] Step/SwingStartTick/LockUntilTick), MeleeComboSystem (the system). MODIFIED: PlayerInput (+Attack InputEvent), TuningConfig (+9 melee knobs across all 6 surfaces + the wire report), PlayerAuthoring (bake MeleeCombo), PlayerDeathStateSystem (clear on death), PlayerInputGatherSystem (the rebind), DebugOverlay (melee tuning rows), CombatFeedbackSystem (swing juice).
- Input rebind (direct device reads, no
.inputactionsregen — the Dash precedent): melee = left-click / pad-West (PRIMARY); rangedFire= right-click / pad-left-trigger; both&& !BuildPaletteState.Active. Right-click stays build-cancel (modal — the guard separates the uses). - Combo state machine (predicted, idempotent ABSOLUTE writes): fresh
Attackpress (not locked, not mid-dash, dash wins same-tick ties via!Dash.IsSet) → chain if re-pressed in[LockUntilTick, LockUntilTick+grace)else reset to 1; finisher (Step==ComboLength) widens range + scales dmg/knockback/recovery byMeleeFinisherMult. Movement-commit scalesMoveVelocitywhile in the swing window (lower-bounded onSwingStartTick— the DashSystem rollback fix), and a dash overrides it ([UpdateBefore(DashSystem)]). - Server-only cleave (mirrors
ProjectileDamageSystem): collect living enemies (EnemyTag/TrainingDummyTag, Health>0) in the per-step cone, appendSourceTick-stampedDamageEvent+ stampKnockbackState. Drained same tick byHealthApplyDamageSystem. So a cleave on a staggered Charger scores the whiff-punish for free. - Live-tunable feel: 9
TuningConfigknobs inDEV ▲→ "Melee …" rows. No per-step blob; the MC-6 archetype byte was deferred (the melee is its own verb — building dispatch infra now would be breadth-before-need; flagged to the operator, not silently dropped). - Juice:
CombatFeedbackSystemswing whoosh/arc-burst/camera-nudge edge-detected offMeleeCombo.SwingStartTick, burst scales with the step, finisher FOV-pop keyed off the liveComboLength.
The two mandatory adversarial reviews (operator's standing rule)
- Pre-code (3 lenses → 21 findings → 8 confirmed): PRED-1 (the combo Step is path-dependent → REPLICATE it + absolute-write; the draft's
prev+1would diverge under rollback) · GRP-1 (my "append in the predicted group to keep the whiff-punish" rationale was FALSE — the stagger is a 36-tick window scored once regardless of group; the placement is still right but for theProjectileDamageSystem-precedent reason) · BURST-1/F5-1/SCOPE-1 (archetype byte →AbilityDefBlobonly / defer to MC-6; noMeleeStepBlob; melee feel all-live) · REUSE-1 (extract aMeleeConeMathpredicate, don't callResolve) · INPUT-1 (NOT right-mouse — it's build-cancel + the kbm-scheme sentinel). All folded in before coding. - Post-build (3 lenses → 18 findings → 4 confirmed, ALL FIXED): (1) server gathered every enemy every tick even with no swing + (4) client allocated lists it never filled → restructured to queue swings in the player loop and gather enemies server-only ONCE, only when a swing fired; (2) the finisher juice-pop hard-coded
step>=3→ now keys off the liveComboLength(so tuning ComboLength=2 still pops); (3) test-coverage gaps → +4 tests (comboLen=2 finisher, same-tick Attack+Dash tie, Attack-during-dash-recovery, two-player co-op cleave). The 14 refuted were correctly dismissed (e.g.AppendToBufferis safe — enemies always bake aDamageEventbuffer;NonZerodeadline can't wrap; comboLen=1 heavy-only is an intended floor).
Validation (all gates)
- Compile: clean — 0 errors / 0 warnings (Bursted
MeleeComboSystemincl. the post-fix restructure; no enum-on-Burst, byte combo-length). - EditMode: 294/294 green (was 290 pre-fix; +23 over the 267 baseline: 8
MeleeConeMath, 15MeleeComboincl. the +4 hardening tests). The genericTuningConfigTests(iterating< Count) auto-cover the 9 new knobs and guard that all surfaces are wired. - Play (real netcode session, server+client), twice (pre- and post-restructure): no
ComponentSystemSortercycle (chain acyclic), player ghost re-baked withMeleeComboin BOTH worlds (idle 0/0/0 — server==client; the new[GhostField]s didn't break the handshake),MeleeComboSystemregistered + running both worlds, zero console errors/exceptions (only the benign Server-Tick-Batching warnings). The refactored OnUpdate is a valid Burst entry point (no stale-binary / "not a known entry point").
Notes / deviations (deliberate)
- Archetype byte deferred to MC-6 (stated to the operator up front, not silently). The melee is a standalone verb; MC-6 owns ability dispatch.
- Live damage E2E (a cleave landing on a Husk during a siege) is the operator's feel gate; the synthetic E2E is covered deterministically by the 19
MeleeComboEditMode tests (real system, GameServer world). No mid-Play input injection (no click sim). Docs/Vault/_scratch/MC4_ComboAttack_DesignDraft.mdwas the pre-code review artifact; superseded by DR-030_MC4_Combo_Melee_Primary_Verb and removed.
Open items (operator)
- The MC-4 fun-gate (gate 3): focused-editor feel pass — dash-in → light·light·finisher → dash-out reads as one verb;
cleaveTargetsPerSwing > 1.5in a swarm; cleave chosen over the projectile when surrounded; finisher reads as the big hit. Tune live viaDEV ▲→ "Melee …" rows (dmg/range/cone/recover/chain/move-x/knock/finish-x/combo-len). MC-4 is NOT done until it passes. - After MC-4 passes → EB-1 (machines can die) is the next committed milestone (Path_to_Fun).
- The slice is uncommitted (12 files: 5 new + 7 modified). Offered for commit.
Links
DR-030_MC4_Combo_Melee_Primary_Verb · Path_to_Fun · DR-028_Combat_Primary_Verb_Depth_First · DR-029_Path_A_Fork_Locks · 2026-06-09_MC1_Implementation · 2026-06-10_MC0_TuningConfig_LiveTuning · validate-netcode-design-before-coding