diff --git a/Docs/Vault/02_Game_Design/Combat_Attack_Feel_Guidelines.md b/Docs/Vault/02_Game_Design/Combat_Attack_Feel_Guidelines.md new file mode 100644 index 000000000..7fc95eabf --- /dev/null +++ b/Docs/Vault/02_Game_Design/Combat_Attack_Feel_Guidelines.md @@ -0,0 +1,225 @@ +--- +title: Combat Attack & Ability Feel Guidelines (research-based) +date: 2026-07-20 +tags: [game-design, combat, feel, clarity, animation, vfx, guidelines, lantern] +status: DRAFT — pending operator review +permalink: 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.7–1.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](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, + Disc Room's ~50 ms lethal-contact grace, Overwatch's inflated friendly-projectile hitboxes ([Game-feel survey, arXiv 2011.09201](https://arxiv.org/pdf/2011.09201), [TVTropes](https://tvtropes.org/pmwiki/pmwiki.php/Main/HitBoxDissonance)). +- **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. + +### 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](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, + not a generic centered flash. +- **WildStar's telegraph canon** ([wiki](https://wildstar.fandom.com/wiki/Telegraph)): 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](https://gamecritics.com/gc-staff/shape-of-dreams-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](https://www.gamedeveloper.com/pc/combat-canceled-i-god-of-war-i-action-game-design)): +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](https://arxiv.org/pdf/2011.09201)); too-long buffers execute stale intent +([yosispring — Input Buffering](https://medium.com/@yosispring/input-buffering-action-canceling-and-also-forbidden-knowledge-47a3f8a95151)). + +### R8. Juice has an optimum — medium-high, not maximum +Empirical result (Kao study, via [arXiv survey](https://arxiv.org/pdf/2011.09201)): 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](https://screenrant.com/shape-of-dreams-eunseop-shim-interview/), [Loot Level Chill interview](https://lootlevelchill.com/features/shape-of-dreams-interview-we-are-standing-on-the-shoulders-of-giants/)): +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 R1–R5 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 2–4t, recovery carries the weight. +- **Player heavy verbs** (finisher, slam): anticipation 15–22t, *held* top-of-swing frames allowed, contact still 2–4t. +- **Enemy attacks**: anticipation ≥ **reaction + escape + buffer** = 15t (0.25 s) + dash-trigger (~6t) + 9–15t + difficulty buffer → **≥ 30t (0.5 s) floor for basics, 45–60t 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 = 4–5 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 ≈ 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 | ☐ operator | +| 2 | **Reach retune** (G2.2) — `MeleeRange` 2.6→2.2, finisher reach ×1.5→×1.25 | DO with #1 as one package | ☐ operator | +| 3 | **Weapon scale ×1.25 + tip trail** (G2.3) | DO — cheapest honesty win | ☐ operator | +| 4 | Victim-vibrate + finisher hold ladder (G5) | DO — pure presentation | ☐ operator | +| 5 | Input buffer 6–10t (G7) — a small predicted-sim change | DO after #1 lands (same system) | ☐ operator | +| 6 | Class cancel policies (G7) — Bathynaut commit / Harpooner crisp | Ratify as design law | ☐ operator | +| 7 | Hades frame-count follow-up session (fill the research gap) | Optional, low priority | ☐ operator | + +*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. diff --git a/Docs/Vault/07_Sessions/2026/2026-07-20_Attack_Feel_Guidelines_Research.md b/Docs/Vault/07_Sessions/2026/2026-07-20_Attack_Feel_Guidelines_Research.md new file mode 100644 index 000000000..d75f918ba --- /dev/null +++ b/Docs/Vault/07_Sessions/2026/2026-07-20_Attack_Feel_Guidelines_Research.md @@ -0,0 +1,26 @@ +# 2026-07-20 — Attack/ability feel guidelines (research session) + +**Trigger:** operator on the 07-19 pass — "the size of the swings don't line up visually"; asked for a +research-based, game-grounded guideline set for attacks/abilities (clarity, feel, animation), prompted for review. +Scope locked by operator: full combat grammar · research-derived reach proposal · references = SoD + Hades + +V Rising + Souls/MH + D4/PoE2/LE. + +**What shipped:** [[Combat_Attack_Feel_Guidelines]] (`02_Game_Design/`, status DRAFT — pending operator review). +R1–R9 research canon (three-phase anatomy, player/enemy anticipation inversion, weight-through-time, D4 payload +honesty + read hierarchy + emissive-in-dark rule, Sakurai hit-stop canon, WildStar telegraph color/fill canon, +GoW cancel taxonomy, juice optimum, SoD kit grammar) → G1–G8 LANTERN rulebook → 7 review forks incl. the +swing-size fix package (damage-at-contact-tick, range 2.6→2.2 + finisher reach ×1.25, weapon ×1.25 + tip trail). + +**Research provenance:** deep-research workflow `wf_1e5183c1-13c` — 5 angles, 21 sources, ~95 claims. Ran into +session-quota agent deaths TWICE (the known masquerading-as-clean failure); resumed with `resumeFromRunId` per +memory protocol (cached search/fetch replayed free). Final: 12 confirmed 3-0/2-0, **0 refuted**, 13 unverified +(quota-killed votes; quote-backed). Synthesis step died both times — the doc synthesizes from the raw verified +claim inventory (journal.jsonl) instead. Gap flagged in-doc: Hades/PoE2/V Rising primary material resisted +extraction (video sources) — optional follow-up frame-count session. + +**Quantified driver:** camera Distance 13 / FOV 55° ≈ 13.5 m visible plane → the 2.6 m arc = ~20% of screen +height vs the axe+arm ~1.7–1.8 m; finisher 3.9 m arc reads >2× the weapon. Damage also lands at `SwingStartTick`, +~16 ticks BEFORE the animation's blade contact — dishonest in size and in time. + +**Next:** operator reviews the fork table (7 items) in the guidelines doc; approved items become the next +implementation session (damage-at-contact is the netcode-touching one — needs the ★ pre-code review).