Docs: DR-030 MC-4 combo melee (primary verb) + session log; Path_to_Fun MC-1 passed / MC-4
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>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
---
|
||||
id: DR-030
|
||||
title: MC-4 = a combo-chain melee as the PRIMARY verb (ranged demoted); predicted-replicated combo state
|
||||
status: accepted
|
||||
date: 2026-06-10
|
||||
tags:
|
||||
- decision
|
||||
- design
|
||||
- combat
|
||||
- netcode
|
||||
- mc-4
|
||||
permalink: gamevault/07-sessions/decisions/dr-030-mc4-combo-melee-primary-verb
|
||||
---
|
||||
|
||||
# DR-030 — MC-4: Combo-Chain Melee as the Primary Verb
|
||||
|
||||
## Context
|
||||
|
||||
[[2026-06-10_MC4_Combo_Melee]] · direction [[Path_to_Fun]] (MC-4) · forks ritual [[DR-029_Path_A_Fork_Locks]] · combat thesis [[DR-028_Combat_Primary_Verb_Depth_First]] / [[combat-first-depth-before-breadth]].
|
||||
|
||||
**MC-1 PASSED its fun-gate** (operator, 2026-06-10: *"It's fun — the dash feels fine"*). The project kill-switch is cleared and the combat thesis is validated — so depth continues. The operator then chose to address the flattest-feeling thing: the default offense (`AbilityFireSystem`'s auto-aim hold-to-fire projectile — the *only* offense verb). Of the four MC-4 shapes presented (single cleave / Attack+Special pair / combo-chain / full weapon-kit), the operator picked **combo-chain Attack**, and on the role/binding fork picked **melee as the PRIMARY verb** (ranged demoted to a secondary poke). Hades-like.
|
||||
|
||||
The slice is netcode-heavy (predicted combo state under rollback), so per the standing rule it went through the **mandatory pre-code adversarial review** (3 lenses → 21 findings → 8 confirmed) before any code, and a **post-build review** (3 lenses → 18 findings → 4 confirmed, all fixed).
|
||||
|
||||
## Decision
|
||||
|
||||
**1. Melee combo is the player's PRIMARY verb.** Left-click / gamepad-West = the 2–3-hit combo; the ranged projectile (`Fire`) is demoted to right-click / gamepad-left-trigger. Both are direct device reads in `PlayerInputGatherSystem` (no `.inputactions` regen — the MC-1 Dash precedent), both suppressed while the build palette is open. Right-click stays the build-cancel (modal; the `!BuildPaletteState.Active` guard separates the two uses). Dash unchanged.
|
||||
|
||||
**2. The combo `Step` is path-dependent → it is REPLICATED, not derived.** Unlike the dash (a stateless-per-tick decision whose `DashState` is non-replicated and re-derived each tick), which chain-link you are on depends on the *sequence + timing* of prior presses, and the bounded input command buffer cannot reconstruct it across a reconnect / long rollback. So `MeleeCombo{ [GhostField] byte Step; [GhostField] uint SwingStartTick; [GhostField] uint LockUntilTick }` is **owner-predicted replicated state** (one player-ghost re-bake; in-family with `DashCooldown`/`AbilityCooldown`). The ADVANCE writes are **ABSOLUTE functions of (restored Step, tick)** — never an in-place `prev+1` of a non-restored field — so a rollback restores the authoritative anchor and the predicted re-sim converges (the `DashSystem` idempotency idiom). *(Pre-code review PRED-1/ROLLBACK-1 — this overrode the reuse-lens scope objection: correctness over saving a re-bake.)*
|
||||
|
||||
**3. Damage is SERVER-ONLY in the predicted group, mirroring `ProjectileDamageSystem`** (not for a whiff-punish reason — that premise was false; the Charger stagger is a multi-tick window scored once regardless of group). The combo STATE advance + movement-commit run on BOTH worlds (predicted, idempotent, instant local feel); the cleave (collect-all enemies in the per-step cone via the new `MeleeConeMath` predicate, append `SourceTick`-stamped `DamageEvent` + stamp `KnockbackState`) runs only `if (isServer)`. `MeleeComboSystem` sorts `[UpdateAfter(PlayerControlSystem)] [UpdateBefore(DashSystem)]` so a dash overrides the swing's movement (dash-cancel) and `HealthApplyDamageSystem` ([UpdateAfter(DashSystem)]) drains the cleave the same tick. Chain `PlayerControl < MeleeCombo < Dash < Health` is acyclic (Play-validated).
|
||||
|
||||
**4. The combo is fully LIVE-tunable — no per-step authored blob, and the MC-6 archetype byte is DEFERRED.** The whole per-step shape derives from ~9 live `TuningConfig` knobs (damage / range / cone-half-angle / recover / chain-grace / move-scale / knockback-speed / finisher-mult / combo-length) + one finisher multiplier — so the operator tunes feel mid-Play with no recompile/re-bake. Because the melee is its own verb (own input → own system, not an ability dispatch), the `Archetype`-byte-on-`AbilityDefBlob` dispatch infrastructure is **deferred to MC-6** where it is actually needed (avoids building breadth before it earns its place; pre-code review BURST-1/F5-1/SCOPE-1).
|
||||
|
||||
## Consequences
|
||||
|
||||
- The combo grammar is **dash-in → light → light → finisher → dash-out**, with the projectile as a ranged poke. The finisher (Step == ComboLength) widens range + scales damage/knockback/recovery by `MeleeFinisherMult`; `ComboLength` is a live knob (1 = heavy-only floor, 2 = light+finisher, 3 = light·light·finisher default).
|
||||
- **Status: code-complete + reviewed; the MC-4 FUN-GATE is the open operator item** — `cleaveTargetsPerSwing > 1.5` in a swarm, dash-in/cleave/dash-out chosen over the projectile when surrounded, a blind-test watcher can tell cleave from projectile by feel. Tunable live via `DEV ▲` → the new "Melee …" rows. MC-4 cannot "pass" until MC-1's feel is held (it just was). After MC-4 passes → **EB-1** (machines can die) is the next committed milestone.
|
||||
- Reversible via the same fork ritual; the live-singleton picks flip at playtest. The structural shapes (Step replicated, melee-primary binding, server-only cleave) are committed.
|
||||
Reference in New Issue
Block a user