From fe4ebcdb5ced2e5f9657669454fb82797f4a8ef6 Mon Sep 17 00:00:00 2001 From: Oliver-Akins Date: Sat, 21 Dec 2024 00:05:50 -0700 Subject: [PATCH] Add custom Die class for handling the ripping and crypting dice --- module/dice/CryptDie.mjs | 56 ++++++++++++++++++++++++++++++++++++++++ module/hooks/init.mjs | 7 +++++ 2 files changed, 63 insertions(+) create mode 100644 module/dice/CryptDie.mjs diff --git a/module/dice/CryptDie.mjs b/module/dice/CryptDie.mjs new file mode 100644 index 0000000..4b67ef0 --- /dev/null +++ b/module/dice/CryptDie.mjs @@ -0,0 +1,56 @@ +import { Logger } from "../utils/Logger.mjs"; + +const { Die } = foundry.dice.terms; + +export class CryptDie extends Die { + static get MODIFIERS() { + return { + ...super.MODIFIERS, + "rc": `ripOrCrypt`, + }; + }; + + ripCryptState = undefined; + async ripOrCrypt(modifier) { + + const rgx = /rc([0-9]+)/i; + const match = modifier.match(rgx); + if (!match) { return false }; + let [ target ] = match.slice(1); + + /* + Handle "Ripping" rolls, which is equivalent to re-rolling 8's and counting + it as a success. + */ + await this.explode(`x=8`, { recursive: true }); + if(this.results.some(result => result.exploded)) { + this.ripCryptState = `ripping`; + }; + + /* + Handles "Crypting" rolls, which is a single explosion that allows + */ + if (!this.ripCryptState) { + await this.explode(`xo=1`, { recursive: false }); + + let almostCrypted = false; + for (const result of this.results) { + if (result.result !== 1) { continue }; + if (almostCrypted) { + this.ripCryptState = `crypted`; + break; + } else { + almostCrypted = true; + } + } + }; + + // Count successes and deduct failures from total + await this.countSuccess(`cs>=${target}`); + await this.deductFailures(`df<${target}`); + }; + + get total() { + return Math.max(super.total, 0); + } +}; diff --git a/module/hooks/init.mjs b/module/hooks/init.mjs index 03f4c17..0519436 100644 --- a/module/hooks/init.mjs +++ b/module/hooks/init.mjs @@ -5,6 +5,9 @@ import { HeroSummaryCardV1 } from "../Apps/ActorSheets/HeroSummaryCardV1.mjs"; import { HeroData } from "../data/Actor/Hero.mjs"; import { registerDevSettings } from "../settings/devSettings.mjs"; +// Class Overrides +import { CryptDie } from "../dice/CryptDie.mjs"; + // Misc import { Logger } from "../utils/Logger.mjs"; @@ -19,6 +22,10 @@ Hooks.once(`init`, () => { CONFIG.Actor.dataModels.hero = HeroData; // #endregion + // #region Class Changes + CONFIG.Dice.terms.d = CryptDie; + // #endregion + // #region Sheets // #region Actors Actors.registerSheet(game.system.id, HeroSummaryCardV1, {