**The one-sentence thesis:***feel* is made by how an attack spends its time (anticipation → contact → recovery),
*clarity* is made by drawing exactly what the simulation does — when it does it — inside a strict loudness
hierarchy; every rule below is one of those two statements specialized.
---
## Part 1 — The research base (what the five schools agree on)
### R1. Every attack is three phases, and the contact phase is nearly instant
Decompose every attack into **Anticipation → Contact → Recovery** ([gdkeys — Anatomy of an Attack](https://gdkeys.com/keys-to-combat-design-1-anatomy-of-an-attack/)).
The contact (active) portion is a *few frames*, constant speed; weight and readability are bought in the other
two phases. Published example frame data (Hollow Knight's Hornet @30fps): Dash = 15f anticipation / 10f attack /
10f recovery.
### R2. Player vs enemy anticipation INVERTS
For the **player**, anticipation frames trade weight against responsiveness — too few reads weightless, too many
reads as input lag ([gameanim — 12 Principles in Games](https://www.gameanim.com/2019/05/15/the-12-principles-of-animation-in-video-games/), [slynyrd — Melee Attacks](https://www.slynyrd.com/blog/2018/9/8/pixelblog-9-melee-attacks)).
For **enemies**, anticipation IS the telegraph and should be deliberately *longer* — its function is giving the
player time to react. Telegraph lead-time formula ([gdkeys](https://gdkeys.com/keys-to-combat-design-1-anatomy-of-an-attack/)):
**lead = human reaction (0.25 s) + the player's escape-move trigger time + difficulty buffer.**
### R3. Weight = slower anticipation + longer recovery — never a slowed contact
Perceived weight is inversely tied to speed, but the fix is *where the time goes*: heavy weapons get slower
wind-ups and added hold frames while **smear/contact frames stay few and fast** ([gameanim](https://www.gameanim.com/2019/05/15/the-12-principles-of-animation-in-video-games/), [slynyrd](https://www.slynyrd.com/blog/2018/9/8/pixelblog-9-melee-attacks)).
Recovery is the *safer* place to spend weight-frames than anticipation (the action already resolved). This is the
Souls/MH commitment school: weight lives in commitment, not in slow-motion swings.
### R4. Honesty: the damage volume must match what is drawn — when it is drawn
- **Diablo IV's "payload" rule**: damage areas animate over frames so the hit region *tracks the VFX in time* —
AoEs expand outward with the visual, melee damage areas follow the weapon's motion ([D4 Quarterly Dec 2021](https://news.blizzard.com/en-us/diablo4/23746639/diablo-iv-quarterly-update-december-2021)).
- **Smash's sword-lines rule**: when a hitbox is disjointed from the body, make the *visual* honest — add trails /
enlarge the weapon at full extension — rather than shrinking the hitbox ([TVTropes — Hitbox Dissonance](https://tvtropes.org/pmwiki/pmwiki.php/Main/HitBoxDissonance)).
- **Monster Hunter's lesson**: hitboxes grossly beyond the visual (Plesioth hipcheck) are infamous; MH:World moved
to animation-driven honesty where only the attacking appendage damages.
- **Generosity has a direction**: mismatches are tuned *in the player's favor only* — small player hurtboxes,
- **Reach tricks are legitimate**: animators deliberately elongate the weapon/arms at max swing extent and mark
the dangerous part of a swing with a trail ([slynyrd](https://www.slynyrd.com/blog/2018/9/8/pixelblog-9-melee-attacks), [gdkeys](https://gdkeys.com/keys-to-combat-design-1-anatomy-of-an-attack/)).
### R5. Hit-stop is the cheapest weight in games — scale it, cap it, spend it beyond hits
Sakurai: hit-stop (a brief pause at the moment of connection) is *critical* — "the same game plays completely
differently with versus without it" ([Sakurai on Creating Games — Hit Stop](https://www.youtube.com/watch?v=OdVkEOzdCPw), [Source Gaming translation of Famitsu vol. 490](https://sourcegaming.info/2015/11/11/thoughts-on-hitstop-sakurais-famitsu-column-vol-490-1/)).
The canon:
- **Scales with damage** (Smash: ~8f for a mid hit in Melee up to 15f in Ultimate; hard caps 20–30f ≈ 333–500 ms).
- **Both parties freeze together**, same duration; the victim *vibrates* during the freeze (visual only).
- **Hand-tuned per attack**, not purely formula: sword tips ×1.25, electric ×1.5, projectiles get *less*.
- Old-school flat values work too: Final Fight = a universal 6f; Capcom pauses only attacker+victim, the rest of
the world keeps simulating ([shane-sicienski hitstop analysis](https://shane-sicienski.com/blog/blog-post-title-one-55pmn), [SSBWiki — Hitlag](https://www.ssbwiki.com/Hitlag)).
- **Spend the technique beyond hits**: "boss stop" on kill-confirms and any big moment; brief slow-mo that snaps back.
- **D4's intensity hierarchy**: visual loudness is *keyed to ability power* — spammable skills deliberately quiet,
ultimates loud; a skill's VFX intensity grows as its power grows ([D4 Quarterly Dec 2021](https://news.blizzard.com/en-us/diablo4/23746639/diablo-iv-quarterly-update-december-2021)).
- **D4's dark-scene rule** (LANTERN-critical): pure PBR lighting muddies gameplay readability in the dark, so
combat VFX deliberately break physics — they are *emissive and cast their own light*.
- **Directional, body-part hit feedback**: impacts flow with the attack's direction and emit from the struck spot,
- **Input buffer ≈ 6–10 ticks (0.1–0.17 s)** for melee-chain and socket presses: a press during the last ~10t of
a lock fires on the first legal tick (R7 buffer method; our `InputEvent`s already latch per tick — the buffer is
a server-side "held intent" check against `LockUntilTick`, deterministic and rollback-safe). Never longer — stale
intent (R7's SSBU warning).
- **Cancel taxonomy per class fantasy** (R7): the **Bathynaut commits** — no pre-contact cancel on swings (Ninja
Gaiden school; the dash already refuses to interrupt a swing — keep); **post-contact, dash-cancel opens** (spend
recovery on weight but hand back agency for the escape verb — the Souls-roll compromise). The **Harpooner** is
the crisp school: pre-contact cancel on line-casts at the cost of the cooldown tick.
- Movement-commit (`MeleeSwingMoveScale` 0.35) is the melee's "self-root lite" — keep; it is the commitment read.
### G8 — Enemy telegraph compliance (mostly ratifying what exists)
The existing system already matches canon (per-kind color + shape + voice, fill-ends-at-impact, strike beep at 8t).
Additions to make it law: every NEW enemy attack ships **decal shape = true damage volume** (G2 honesty applies to
enemies doubly — their generosity direction is *toward the player*: decal may be ≥ the true volume, never smaller);
anticipation floors per G1; one **signature silhouette pose** per kind's windup (readable without the decal, R2).
---
## Part 3 — Review items (the forks in this doc)
| # | Fork | Recommendation | Status |
|---|---|---|---|
| 1 | **Damage at contact tick** (G2.1) — light melee gains ~0.2 s real windup | DO — it's the honest heavy-weapon model; feel-test behind a knob | ✅ SHIPPED 07-20 (`MeleeCleavePending` schedule-and-consume; knob `MeleeContactTicks`, 0 = legacy) |
| 2 | **Reach retune** (G2.2) — `MeleeRange` 2.6→2.2, finisher reach ×1.5→×1.25 | DO with #1 as one package | ✅ SHIPPED 07-20 (`MeleeFinisherRangeMult` knob 30) |
| 3 | **Weapon scale ×1.25 + tip trail** (G2.3) | DO — cheapest honesty win | ✅ SHIPPED 07-20 (axe ×1.25; blade-smear ribbon; arc reveal ends AT contact) |
| 4 | Victim-vibrate + finisher hold ladder (G5) | DO — pure presentation | ✅ hold ladder SHIPPED (`FinisherHoldFrames`); **vibrate CUT** — Rukhanka folds the render child's inverse transform into skinning, an offset is a no-op (review C8); follow-up = additive anim layer |
| 5 | Input buffer 6–10t (G7) — a small predicted-sim change | DO after #1 lands (same system) | ✅ SHIPPED 07-20 (`BufferedAttackTick` GhostField; unlock-edge validity, batch-slack 4) |
| 6 | Class cancel policies (G7) — Bathynaut commit / Harpooner crisp | Ratify as design law | ✅ LAW + Bathynaut side SHIPPED (dash refused pre-contact); Harpooner side lands with the Harpooner |
| 7 | Hades frame-count follow-up session (fill the research gap) | Optional, low priority | ☐ operator |
smear look, finisher hold weight. DebugOverlay rows for the 3 new knobs = a 5-minute add on request.
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.