Files
Project-M/Docs/Vault/02_Game_Design/Combat_Attack_Feel_Guidelines.md
T

20 KiB
Raw Blame History

title, date, tags, status, permalink
title date tags status permalink
Combat Attack & Ability Feel Guidelines (research-based) 2026-07-20
game-design
combat
feel
clarity
animation
vfx
guidelines
lantern
DRAFT — pending operator review gamevault/02-game-design/combat-attack-feel-guidelines

Combat Attack & Ability Feel Guidelines

Why this doc: the 07-19 melee weight pass surfaced a systemic problem — the cleave arc telegraphs 2.6 m (3.9 m finisher) while the axe + arm visually covers ~1.71.8 m; at our camera (Distance 13, FOV 55°, ~13.5 m visible plane) the finisher arc reads at >2× the weapon's visual reach. Rather than patch one number, this is the research-based grammar for every attack and ability in LANTERN — player melee, the 4-socket kit (projectile / cone / zone / movement), and enemy attacks. Deep-research run wf_1e5183c1-13c: 21 sources, ~95 extracted claims, 3-vote adversarial verification on the top 25 — 12 confirmed (3-0/2-0), 0 refuted anywhere, 13 unverified only because verifier agents died on session quota (each still carries a verbatim source quote from the fetch pass). The confirmed set covers the load-bearing rules: the hit-stop canon (R5), the D4 readability hierarchy (R6), the cancel/buffer taxonomy (R7), and the SoD skillshot framing (R9). Sources cited inline. Scope + reach-philosophy + reference set approved by operator 07-19 (full grammar · research-derived reach proposal · +Souls/MH +D4/PoE2 schools).

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). 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, slynyrd — 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): 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, slynyrd). 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).
  • 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).
  • 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, Disc Room's ~50 ms lethal-contact grace, Overwatch's inflated friendly-projectile hitboxes (Game-feel survey, arXiv 2011.09201, TVTropes).
  • 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, gdkeys).

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, Source Gaming translation of Famitsu vol. 490). The canon:

  • Scales with damage (Smash: ~8f for a mid hit in Melee up to 15f in Ultimate; hard caps 2030f ≈ 333500 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, SSBWiki — Hitlag).
  • Spend the technique beyond hits: "boss stop" on kill-confirms and any big moment; brief slow-mo that snaps back.

R6. Readability = a strict loudness hierarchy + ownership colors + fill-up timing

  • 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).
  • 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, not a generic centered flash.
  • WildStar's telegraph canon (wiki): fixed ownership colors (blue = yours, red = enemy, green = ally); a fill line whose arrival at the border = the impact moment; the fill direction encodes one-shot vs persistent effects. Documented failure mode: red telegraphs on red floors.
  • SoD's cautionary tale: even a praised skillshot game saturates into unreadability in 4-player co-op when every ability is loud (GameCritics review) — the hierarchy must be enforced per on-screen actor budget, not per ability in isolation.
  • SoD's accessibility rule: every enemy attack has a visual telegraph; audio is reinforcement, never the sole channel.

R7. Responsiveness = buffers + cancel windows anchored to contact frames

God of War's combat designer (Eric Williams — Combat Canceled): cancel-window design is a primary determinant of whether combat reads crisp or sluggish (Kratos: ~4,000 authored cancel branches in GoW2). The taxonomy: partial cancels open in windows anchored to the hit frame (pre-hit / post-hit); Ninja Gaiden allows zero pre-hit cancels (full commitment school); inputs arrive via a buffer (stored, fires when the window opens — the forgiving default) or instant (frame-exact). Buffer norms: a few frames up to ~0.23 s (arXiv survey); too-long buffers execute stale intent (yosispring — Input Buffering).

R8. Juice has an optimum — medium-high, not maximum

Empirical result (Kao study, via arXiv survey): medium and high juiciness outperform both extremes. The canonical kit (screen shake, recoil, color flash, particles — Juice it or lose it, Nijman's Art of Screenshake, Swink's Game Feel) is applied proportionally to significance, and the loudest levels are reserved so they stay meaningful.

R9. The SoD kit grammar (our closest cousin, by design lineage)

Shape of Dreams = MOBA QWER grammar (HotS + RoR2 lineage, per the director interview, Loot Level Chill interview): manual-aim skillshots, 4 slotted "memories" + essence modifiers, cooldown-gated (no resource), positioning as the core skill, short compact fights, and difficulty redesigned away from real-time pressure so players can read their abilities. Its praised feel comes from the MOBA cast grammar; its documented failure is VFX saturation in co-op. We inherit the first and must budget against the second.

Research gaps (flagged honestly): Hades primary sources (Noclip documentary, Supergiant GDC talks) and PoE2 / Last Epoch / V Rising specifics resisted extraction (video-heavy sources) — the Hades school here rides on the general R1R5 principles it exemplifies rather than on quoted primary material. If we want its exact numbers (e.g., dash-cancel windows), that's a follow-up frame-count session, not a blocker for these rules.


Part 2 — The LANTERN rulebook (the grammar applied to this game)

Ground truth these rules bind to: 60 Hz server-auth prediction; swing/cast anim window = CastFacingTicks (26t ≈ 0.43 s) < MeleeRecoverTicks (30t ≈ 0.50 s); cleave = instant server cone at SwingStartTick; camera Distance 13 / FOV 55° (≈13.5 m visible plane); Rukhanka client-derived anim; procedural FX; the murk (Exp² teal fog, emissive reads win — R6 is our art direction's physics).

G1 — Time signature: every attack declares its three phases in ticks

Author every player attack/ability as (anticipation, contact, recovery) ticks against the R1/R3 template:

  • Player light verbs (Swing1/2): anticipation ≤ 10t (~0.17 s), contact 24t, recovery carries the weight.
  • Player heavy verbs (finisher, slam): anticipation 1522t, held top-of-swing frames allowed, contact still 24t.
  • Enemy attacks: anticipation ≥ reaction + escape + buffer = 15t (0.25 s) + dash-trigger (~6t) + 915t difficulty buffer → ≥ 30t (0.5 s) floor for basics, 4560t for heavies (Grunt/Charger windups already comply).
  • Contact is never slowed to add weight (R3). Weight lives in anticipation holds + recovery + impact (G5).

G2 — Reach honesty: the damage cone, the weapon, and the arc must be one object

The fix for the driving complaint, per R4 (recommended package, operator-approvable line by line):

  1. Damage resolves at the contact tick, not the swing-start tick. Today the cleave lands at SwingStartTick while the animation's blade contact is ~16t later — damage precedes the visible hit. Move the server cone resolve to SwingStartTick + ContactTick (per-step, from the clip's WindUp take length). This is D4's payload rule (hit region tracks the visual in time) and makes the arc a true record of the blade. (Netcode note: a scheduled-tick pattern identical to enemy AttackWindup — well-trodden, but it is a gameplay change: light melee gains a ~0.2 s windup. The heavy fantasy wants exactly this; flag for feel-test.)
  2. Shrink the drawn arc to the real cone and the real cone to the believable weapon: MeleeRange 2.6 → 2.2 m (axe tip ~1.8 m + a 0.4 m player-favoring margin per R4-generosity; still comfortably beats enemy melee range), finisher ×1.5 → ×1.25 range (keep ×1.5 on damage/recover — reach was the offender, not power).
  3. Sell the remaining reach visually (R4 reach-tricks): scale the axe ×1.25 (Synty proportions absorb it); anchor a short weapon-tip trail (the smear) that traces the actual swept edge from the blade, not a body-centered ring; keep the ground arc as the hit-region record but draw its outer rim AT 2.2 m so rim = truth.
  4. The arc sweep must finish WITH the contact (R6 fill-timing): sweep-reveal completes at the contact tick, then only fades — never still-painting reach after the blade has passed.

G3 — Ownership palette (the WildStar canon, LANTERN-toned)

Locked vocabulary across every system (already ~true; now it's law):

  • Enemy threat = red family (per-kind hue variants stay: amber/crimson/toxic/yellow) — ground decals only for incoming danger, fill-to-border = impact moment (already our EnemyDangerTelegraphSystem contract).
  • Local player = warm-white/teal weapon-anchored FX; the finisher's lamp-amber is the warm accent (light is territory — warm = ours).
  • Ally = dimmer cool-blue of the same shapes (RemoteSlashColor already complies).
  • Never red for player/ally anything; never warm-amber for enemies. Murk-red-on-red check: the seabed is teal — we're structurally safe from WildStar's red-floor failure, keep it that way (no red biomes without re-audit).

G4 — Loudness hierarchy + the co-op budget (SoD's failure is our ceiling)

Priority when pixels compete: enemy telegraphs > local player contact/impact > ally attacks > ambient.

  • Per-ability loudness is keyed to cost/cooldown/power (R6-D4): the melee chain and spammable sockets stay quiet (current toned arc = correct); big-cooldown sockets get the loud pass; "ultimate-grade" reserved for rare moments.
  • Budget rule: at 4 players + a wave on screen, ally FX auto-degrade first (fewer particles, shorter lives — a FeelConfig ally-fx scalar), enemy telegraphs never degrade. Add a dev toggle that spawns the worst case (4 casters + 12 enemies) as the standing saturation test.
  • All combat VFX are emissive (R6 dark-scene rule) — never rely on scene light to read an attack in the murk. Audio reinforces but never solely carries a threat (SoD accessibility rule; our per-kind windup voices are the reinforcement layer, the decal is the message).

G5 — Impact ladder (hit-stop canon mapped to our camera-only stack)

Time.timeScale stays banned (netcode); our hit-stop = camera Hold + FOV kick + flash — same ladder, per R5:

  • Scale with significance: chip hit = flash only; solid melee hit = 2-frame hold (current) + directional hit-flash; finisher/slam connect = 45 frame hold + the victim-vibrate trick (offset the enemy's render child ±3 cm for the hold frames — visual only, zero sim); kill = the loudest (existing kill-pop) — a "boss-stop" grade hold (~8 frames + flash) reserved for elite/boss kills.
  • Per-attack hand-tuning is expected (R5): expose the hold frames per verb in FeelConfig, don't derive.
  • Cap it: ≤ 8 frames (~130 ms) — beyond Smash's feel-cap territory scaled to our pace.
  • Directional feedback (R6): hit-flash bursts flow along the swing direction from the struck body part (EmitColored already takes a position — use the contact point, not the enemy center).

G6 — Cast grammar for the 4-socket kit (the SoD inheritance, made explicit)

  • Move-cast is the default (SoD/MOBA school): sockets never self-root; the cast window turns the body (CastFacingTicks) while legs keep the move vector (already our model — now it's the rule for every new Spark).
  • Cooldown-gated, no resource (R9) — matches the socket model; any future resource is a per-Spark exception.
  • Every socket declares its G1 time signature + a G3-compliant visual: projectile = muzzle + tracer (its trail is its honesty); cone = the G2 arc rules; zone = a WildStar-grade fill decal (fill completes at damage start, one-shot vs persistent encoded by fill direction per R6); movement = trail + i-frame shimmer (no telegraph — it's an escape verb).
  • Skillshots stay honest: no homing-by-default; assist only where a Spark explicitly buys it (the existing AutoTargetRange = 0 default per DR-050).

G7 — Responsiveness contract (buffers + cancels, netcode-shaped)

  • Input buffer ≈ 610 ticks (0.10.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 InputEvents 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 610t (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

Implementation record: 2026-07-20_Melee_Feel_Forks_B (design review wf_000bc247: 19 confirmed findings folded in, 5 refuted).

Checklist for any new attack/ability (the doc in one box): declare G1 ticks → G2 volume==visual==timing → G3 color → G4 loudness tier → G5 impact tier → G6 cast grammar → G7 buffer/cancel policy → (enemy) G8 decal+pose.