6.9 KiB
6.9 KiB
Lethal Fantasy FoundryVTT System — Session Context
Current Goal
Fix Grit/Luck defense reaction dialog UX (stacking dialogs, multiple clicks, revert on close) and cross-client sync of defense bonuses. Fix monster defense mulligan reroll button missing cross-client.
Accomplished
Pass 1 — Critical Issues
- Telemetry removed from system.json
- globalThis side effects moved from top-level to
inithook - console.log → log() helper guarded by setting
- Stale Tenebris refs → LETHALFANTASY
Pass 2 — V1/V2 Mixing, Fire-and-Forget
- V1 sheet registrations, activateListeners/jQuery, FilePicker paths fixed
- Fire-and-forget Promises now awaited
- Misnamed
LethalFantasySkill→LethalFantasyWeapon
Pass 3 — Code Review Fixes
- Duplicated dialogs fixed via
_onRenderbindings - renderChatMessage reverted to HTML hook
- All review awaits confirmed
Pass 4 — D30 Dialog Removal & Dead Code Audit
- D30 choice dialog removed — auto-rolls bonus dice; special strike/defense reported as
specialEffect: "flag"(informational) - Spell calamity choice restored — catch-all for non-standard choices uses
specialEffect: "flag" - Dead
specialEffect === "auto"branches removed fromchat-reaction.mjs(×2),combat.mjs(×1),reaction-message.hbs - Deleted
d30-special-choice.hbsand_buildSpecialLabel() - Dead code audit — 2 runtime bugs fixed, ~20 dead exports/methods, 33 unused i18n keys, 2 unused templates
- 3 critical bugs fixed:
SYSTEM.ROLL_TYPE,SYSTEM.EQUIPMENT_CATEGORIES, missing imports inapplications/combat.mjs isPrimaryControllerconsolidated to local function- Aether/Grace deduction merged via
_deductResourceOnCast() nextDefenseDatadeduped via_storeNextDefenseData()buildDefenseReactionButtonsextracted fromcombat.mjs; fixes stale Grit/Luck snapshots- HP HUD toggling extracted to
helpers.mjs node --checkpasses all 55.mjsfiles
Pass 5 — Live Verification
- D30=30 auto-roll verified — Club attack shows D30=30 flag
- Defense request dialog verified — Monster defense dialog with weapon dropdown
- Defense reaction dialog verified — Luck spent, bonus die added, combat result correct
- AZA→Monster attack flow tested end-to-end: Club attack (D20=16, D30=6) → Monster defense (D20=1) → defense reactions (Continue) → D30 attack bonus processed (+2, total 18)
- BUG FOUND & FIXED:
d30ChangedAttackinfinite loop —chat-reaction.mjs:452-455do-while reset block missingd30ChangedAttack = false; added at line 456 - BUG FIX CONFIRMED: Re-tested full flow — AZA Club attack (13, D30=12) → defense dialog → Monster defense (2, D30=24) → reaction dialog (only 1 show!) → Continue → "AZA hits Monster!" combat result → damage roll (1d6=2, total 3) → Apply Damage button. No infinite loop. Full E2E success.
Pass 6 — Cross-Client Mulligan Reroll Fix
- BUG FIX:
handleAttackBoostedhardcodedcanRerollDefense: false—utils/combat.mjs:142now computescanRerollDefensefromdefenseD30messageviahasD30Reroll(). Also passesd30messageto dialog template (wasnull). - BUG FIX: Missing
defenseRerollContextin socket data — addeddefenseRerollContexttoattackBoostedsocket message atchat-reaction.mjs:773, and addedrerollDefensehandler inhandleAttackBoostedatutils/combat.mjs:203-240so the mulligan reroll works cross-client. - BUG FIX: Cross-client mulligan reroll now processes new D30 bonus dice — after reroll, calls
processD30BonusDiceon the new D30 message to apply bonus dice, flags, and DR multipliers (was silently ignored). - Import
hasD30Rerolladded toutils/combat.mjs bleedtop-level type handler added toprocessD30BonusDiceind30.mjs:79-81— returnsspecialEffect: "bleed"same as combo path, so ranged attack bleed (values 5,10,15) creates reaction message and sets damage button bleed flag.
Key Decisions
- Auto-roll bonus dice without dialog — matches existing D30=27 (d6E) flow
buildDefenseReactionButtonsextracts only button-building — defense while-loop structures differ between same-client and cross-client; merging loops risks behavioral divergence- Inline grit/luck deduction uses live actor values
- Aether/Grace helper uses
costFnparameter - Cross-client mulligan reroll sends full
defenseRerollContextvia socket so the defender can re-roll the same configured roll on their client
Next Steps
- Test defense request dialogs (character/monster/save) — more variants
- Test all reaction message variants (shield block/fail, d30Bonus/Flag, grit, luck, etc.)
- Create Player user in Foundry for cross-client socket testing (includes mulligan reroll)
- Prune dead code: unused exports (~20), unused i18n keys (33), unused templates (2)
Critical Context
- Chat buttons not interactive via DevTools snapshot — need JS fallback:
document.querySelectorAll('button').forEach(b => { if (...) b.click(); }) - Defense flow: Attack card → target button (
.request-defense-btn) → defense dialog → defense roll → defense reactions dialog → combat result card with Damage button → damage roll dialog → Apply Damage → HP application - Clicking "Damage" directly bypasses defense — rolls unapplied damage to chat
- Same-owner guard (
chat-reaction.mjs:180-182) — skips defense when GM owns both, unless!defenderIsMonster d30ChangedAttackinfinite loop — variable wasn't reset in do-while block; fix atchat-reaction.mjs:456- Cross-client mulligan fix:
handleAttackBoostednow shows reroll button and handles the reroll action. RequiresdefenseRerollContextin socket data (added). - Deserialized weapon object —
weapon.nameworks,weapon.idundefined,weapon._idworks - Fvtt server: port 31000, foundrydata-dev
- No player user configured — cannot test cross-client socket flow
Relevant Files
module/hooks/chat-reaction.mjs— all 7 hook registrations; defense do-while loop; d30ChangedAttack fix (line 456); socket data includesdefenseRerollContext(line 773)module/utils/combat.mjs—buildDefenseReactionButtons;handleAttackBoostedmulligan fix (lines 142, 154, 227-249); importshasD30Rerollmodule/utils/d30.mjs—processD30BonusDice: auto-roll, flag reporting, no dialog;hasD30Rerollcheckstype === "mulligan"module/utils/helpers.mjs—_toggleHudWraps/_disableHudWrapsmodule/utils.mjs— barrel re-exporting 23 static methodsmodule/models/equipment.mjs—EQUIPMENT_CATEGORYfixmodule/applications/combat.mjs— addedimport { SYSTEM }andimport { log }templates/chat/reaction-message.hbs—d30Flagtext changed;d30Autobranch removedtemplates/dialogs/d30-special-choice.hbs— deletedlang/en.json— 33 unused i18n keys remain