diablo2-web/PROJECT.md

12 KiB
Raw Permalink Blame History

Project: Diablo II: Lord of Destruction v1.13c Complete Player Skill System (diablo2-web)

Architecture

  • Ground Truth Stack: Mounts /usr/local/google/home/taodao/d2-data (d2data.mpq, d2char.mpq, d2exp.mpq, Patch_D2.mpq) in overlay precedence order so Patch_D2.mpq provides authoritative 1.13c .txt tables (Skills.txt, SkillDesc.txt, Missiles.txt, States.txt, ItemStatCost.txt, CharStats.txt, MonStats.txt, MonStats2.txt, Overlay.txt, PetType.txt, ElemTypes.txt, Events.txt, SkillCalc.txt, MissCalc.txt) while d2exp.mpq provides HitClass.txt and AnimData.d2 (570,304 bytes, 3,558 records).
  • Universal 1.13c Skill Engine (src/game/engine/):
    • data-registry.ts: Loads and indexes all 1.13c Excel tables and AnimData.d2.
    • calc-ast.ts: Complete D2Common RPN/AST formula evaluator supporting lvl, blvl (strictly base allocated STAT_SKILLPTS only — 1.13c Marrowwalk fix), ulvl, par1..8, ln12..78, dm12..78, edmn, edns, edmx, edxs, enma, exma, usmc, toht, clc1..4, skill('...'.<prop>), sklvl('...'.<lvl>.<prop>), stat('...'.accr), miss('...'.<prop>), and 1.13c table edge cases (unclosed ( in Fire Wall, par34 in Bone Wall, *12/*16 in royalstrikechainlightning).
    • stat-list.ts & state-bus.ts: D2StatListStrc in 256-fixed-point (<< HitShift) integer arithmetic with dwExpireFrame expiration, curse exclusivity (cursetype === 1 mutually exclusive, STATE_ATTRACT cursetype === 2 immune to overwrite), aura stacking (slvl comparison + pulse lingering), and reactive auraeventfunc triggers (Chilling/Frozen/Shiver Armor, Bone Armor, Cyclone Armor, Energy Shield, Iron Maiden, Life Tap, Clay/Blood Golem).
    • combat-pipeline.ts: 1.13c RollToHit & SUnitDmg pipeline (srcdam / 128, AR vs Defense, Shield/Weapon Block, Amazon Dodge/Avoid/Evade, Masteries, Conviction/Lower Resist 1/5 immunity-breaking efficiency when base res >= 100%, -Enemy Res, Absorb, Blessed Hammer 1.13c rule NOT ignoring Undead/Demon Magic Resistance, Corpse Explosion 70%–120% base monster HP, Venom 10-frame poison duration clamp).
    • anim-dispatcher.ts, missile-engine.ts, aura-scanner.ts, summon-manager.ts: AnimData.d2 frame event (0x01 melee/cast, 0x02 missile) dispatcher with 1.13c EIAS/EFCR diminishing-returns speed scaling and STATE_SKILLDELAY cooldowns, UNIT_MISSILE loop (pSrvDoFunc, pSrvHitFunc, pSrvDmgFunc, NextDelay, Pierce, sub-missiles), radial Aura pulse scanner, and SUMMON_CreatePet manager enforcing PetType.txt caps/groups and 17 pet/trap AI sub-skills (IDs 281..338).
  • 7-Class Renderer & Verification Arena (src/render/unit-sprites.ts, src/game/engine/world-arena.ts, acts.html):
    • Decodes all 7 player classes (am, so, ne, pa, ba, dz, ai across d2char.mpq and d2exp.mpq with 16 composite layers hd..s8 and frame offsetX/offsetY pivots), 391 .dcc missile sprites, 384 .dcc + 1 .dc6 state/cast overlays, and 19 summon/trap/morph monster sprite tokens.
    • Exposes URL-driven deterministic arena mode (acts.html?arena=1&class=<cls>&skill=<skillId>&slvl=<lvl>&autocast=1) with targetable Normal, Undead, Demon, Immune, and Corpse units plus window.__d2webArena inspection and triggerCast() APIs.
  • Zero-Conflict Isolated Worktree Skill Architecture (src/game/skills/):
    • src/game/skills/registry.ts auto-discovers per-skill modules in src/game/skills/impl/<class>/skill-<id3>-<slug>.ts via import.meta.glob('./impl/**/*.ts', { eager: true }) (with fallback to Skills.txt data-driven srvdofunc/srvmissile execution).
    • Each isolated skill worktree (../wt-skill-<id> on branch feat/skill-<id>) adds only src/game/skills/impl/<class>/skill-<id3>-<slug>.ts and tests/skills/<class>/skill-<id3>-<slug>.test.ts, guaranteeing zero merge conflicts across all 221 skills.

Feature Inventory

Every feature from the Survey phase is assigned to a milestone below:

# Feature Description Milestone Source
1 Worktree & main Reconciliation Reconcile d2w-wg1-main (6e4d038 + 7-class baker/tests + samples/d2 & samples/d2-packs) into /usr/local/google/home/taodao/diablo2-web on branch main and remove d2w-wg1-main worktree. M1 Survey 1
2 1.13c MPQ Data Registry (D2DataRegistry) Parse & index 1.13c Skills.txt, SkillDesc.txt, Missiles.txt, States.txt, ItemStatCost.txt, CharStats.txt, MonStats.txt, Overlay.txt, PetType.txt, ElemTypes.txt, HitClass.txt, Events.txt, AnimData.d2. M1 Survey 2 & 3
3 D2Common calc AST Formula Evaluator Full RPN/AST evaluator (lvl, blvl base-only, ulvl, par1..8, ln12..78, dm12..78, edmn, edns, enma, usmc, skill(), sklvl(), stat(), miss()) + 5 1.13c edge cases. M1 Survey 2 & 3
4 UnitStatList & StateBus 256-fixed-point (<< HitShift) stat/damage math, dwExpireFrame, cursetype=1 curse exclusivity, STATE_ATTRACT (cursetype=2) overwrite immunity, aura stacking, reactive auraeventfunc. M1 Survey 2 & 3
5 1.13c RollToHit & SUnitDmg Pipeline srcdam/128, AR vs Def, Block, Dodge/Avoid/Evade, Masteries, Conviction/Lower Resist 1/5 immunity break, Blessed Hammer 1.13c Undead/Demon magic res rule, CE 70-120% HP, Venom 10f clamp. M1 Survey 2 & 3
6 AnimData.d2 Dispatcher, MissileEngine, AuraScanner, SummonManager 25Hz AnimData.d2 action frame (0x01/0x02) dispatch with EIAS/EFCR & STATE_SKILLDELAY, UNIT_MISSILE (pSrvDoFunc/pSrvHitFunc/pSrvDmgFunc/NextDelay/Pierce), radial Aura pulses, PetType.txt summons & 17 pet/trap AI sub-skills. M1 Survey 2 & 3
7 7-Class DCC/COF/Missile/Overlay Renderer & Deterministic Arena (?arena=1) Render all 7 classes (am, so, ne, pa, ba, dz, ai from d2char.mpq+d2exp.mpq), .dcc missiles/overlays, summon sprites, and ?arena=1&class=<cls>&skill=<id>&slvl=<lvl> with window.__d2webArena & headless Chromium screenshot script. M1 Survey 1 & 3
8 Gitea Milestone & 221 Per-Skill Tracking Issues Create Milestone "All Player Skills (v1.13c Parity)" on https://git.projectdiablo2.cn/troytt/diablo2-web and create individual Issues for all 210 class skills (IDs 6..155, 221..280) + 11 universal player skills (IDs 0..5, 217..220, 350), saving src/data/gitea-skill-issues.json. M2 Survey 1 & 2
9 R3 Cohort A: Universal (11), Amazon (30), Sorceress (30), Necromancer (30) Skills Isolated git worktree lifecycle (feat/skill-<id>), 1.13c implementation, Vitest (slvl 1/10/20 + synergies + runtime effect), headless Chromium screenshot, Gitea Issue PNG + evidence comment, merge to main (fixes #<issue>), push origin/main, worktree cleanup (101 skills). M3 Survey 2 & 3
10 R3 Cohort B: Paladin (30), Barbarian (30), Druid (30), Assassin (30) Skills Isolated git worktree lifecycle (feat/skill-<id>), 1.13c implementation, Vitest (slvl 1/10/20 + synergies + runtime effect), headless Chromium screenshot, Gitea Issue PNG + evidence comment, merge to main (fixes #<issue>), push origin/main, worktree cleanup (120 skills). M4 Survey 2 & 3
11 Final E2E Test Pass (Tiers 1–4), Tier 5 Hardening & Cleanliness Audit Pass 100% of E2E test suite (TEST_READY.md), Tier 5 adversarial coverage audit, verify all 221 Gitea issues closed with screenshots, git worktree list single tree, npx tsc --noEmit + npm test + npm run build zero errors on main. M5 Survey 1, 2 & 3

Milestones

# Name Scope Dependencies Status
M1 M1-R1-Skill-Engine-And-Arena Reconcile d2w-wg1-main into diablo2-web (main), implement R1.1–R1.4 shared 1.13c skill engine, 7-class renderer, ?arena=1 browser harness, import.meta.glob skill registry, Vitest suite, merge to main & push to origin/main (550787c). none DONE
M2 M2-R2-Gitea-Milestone-And-Issues Create Gitea Milestone "All Player Skills (v1.13c Parity)" (#9) and 221 individual per-skill Gitea Issues (#154–#374) via Gitea REST API; write src/data/gitea-skill-issues.json. none DONE
M3 M3-R3-Uni-Ama-Sor-Nec Execute R3 isolated git worktree implementation, Vitest verification (slvl 1/10/20 + synergies), headless Chromium PNG screenshot capture, Gitea issue comment + attachment, fixes #<issue> merge to main, push & worktree deletion for Universal (11), Amazon (30), Sorceress (30), and Necromancer (30) skills (eb0317b). M1, M2 DONE
M4 M4-R3-Pal-Bar-Dru-Ass Execute R3 isolated git worktree implementation, Vitest verification (slvl 1/10/20 + synergies), headless Chromium PNG screenshot capture, Gitea issue comment + attachment, fixes #<issue> merge to main, push & worktree deletion for Paladin (30), Barbarian (30), Druid (30), and Assassin (30) skills (eb0317b). M1, M2 DONE
M5 M5-Final-E2E-And-Audit Phase 1 E2E Test Suite Pass (Tiers 1–4), Phase 2 Tier 5 Adversarial Coverage Hardening, and 100% Acceptance Criteria & Worktree/Gitea Audit (reviewer_m5_1..2 APPROVE, challenger_m5_1..2 APPROVE, auditor_m5_1 CLEAN). M3, M4, E2E DONE
E2E E2E-Testing-Track Requirement-driven opaque-box E2E test infrastructure (TEST_INFRA.md), Tiers 1–4 test cases (144/144 passing in tests/e2e-skills-113c/), published TEST_READY.md. none DONE

Interface Contracts

src/game/engine/ ↔ src/game/skills/registry.ts & src/game/skills/impl/<class>/skill-<id3>-<slug>.ts

  • SkillModule:
    export interface SkillEvalResult {
      skillId: number;
      name: string;
      charClass: string;
      slvl: number;
      blvl: number;
      manaCost: number;          // human-readable mana cost (and manaCost256 in 256-fixed-point)
      manaCost256: number;
      toHitBonusPct: number;
      physDamagePct: number;
      srcDam: number;            // 128 = 100% weapon damage
      minPhysDmg: number;
      maxPhysDmg: number;
      elemType: string;
      minElemDmg: number;        // human-readable elemental/magic/poison damage (and 256-fixed-point)
      maxElemDmg: number;
      minElemDmg256: number;
      maxElemDmg256: number;
      durationFrames: number;
      radiusSubtiles: number;
      missileA: string;
      auraState: string;
      curseType: number;
      summonMon: string;
      petMax: number;
      synergyBonusPct: number;
    }
    
    export interface SkillModule {
      readonly skillId: number;
      readonly name: string;
      readonly charClass: string; // 'uni' | 'ama' | 'sor' | 'nec' | 'pal' | 'bar' | 'dru' | 'ass'
      readonly srvStFunc: number;
      readonly srvDoFunc: number;
      evaluate?(ctx: SkillEvalContext): SkillEvalResult;
      executeDo?(ctx: SkillExecContext): SkillExecOutcome;
    }
    
  • src/data/gitea-skill-issues.json:
    • Maps stringified skillId ("0".."350") to { issueNumber: number, issueId: number, title: string, charClass: string, slug: string, milestoneId: number }.

Code Layout

  • src/game/engine/: Shared 1.13c skill engine (data-registry.ts, calc-ast.ts, stat-list.ts, state-bus.ts, combat-pipeline.ts, anim-dispatcher.ts, missile-engine.ts, aura-scanner.ts, summon-manager.ts, world-arena.ts).
  • src/render/unit-sprites.ts: Unified 7-class, monster/summon, missile .dcc, and overlay .dcc/.dc6 sprite loader & renderer.
  • src/game/skills/registry.ts & src/game/skills/types.ts: Skill module contract and import.meta.glob('./impl/**/*.ts', { eager: true }) auto-registry.
  • src/game/skills/impl/<class>/skill-<id3>-<slug>.ts: Per-skill isolated implementation modules (uni, ama, sor, nec, pal, bar, dru, ass).
  • tests/engine/: Unit tests for R1 shared engine modules.
  • tests/skills/<class>/skill-<id3>-<slug>.test.ts: Per-skill Vitest numerical & runtime effect test suites (slvl 1, 10, 20 + synergies).
  • scripts/verify-skill-browser.ts & scripts/gitea-skill-workflow.ts: Automated headless Chromium (chromium-1228) arena casting screenshot & Gitea issue upload/merge/worktree cleanup runners.