From 0312aa4ea53c3eaf035e9128beb2b13aabb89804 Mon Sep 17 00:00:00 2001 From: cadowtin Date: Tue, 8 Aug 2023 02:21:42 -0500 Subject: [PATCH] New Damage Splits - Can now choose split types in settings between `none`, `by-damage-type`, and `all` --- languages/en.json | 9 +++++ scripts/module.js | 99 +++++++++++++++++++++++++++++++++++++++++++-- scripts/settings.js | 14 +++++++ 3 files changed, 119 insertions(+), 3 deletions(-) diff --git a/languages/en.json b/languages/en.json index 086331b..88ac7c9 100644 --- a/languages/en.json +++ b/languages/en.json @@ -26,6 +26,15 @@ "percent-max-health": "% of Max HP", "none": "None" } + }, + "damage-split": { + "name": "Damage Split", + "hint": "How to split damage numbers from roll (None: total only, By Type: By damage type, All: Splits all terms)", + "choices": { + "none": "None", + "split-by-type": "By Type", + "split-all": "All" + } } } } diff --git a/scripts/module.js b/scripts/module.js index 4a8621d..8fe8e00 100644 --- a/scripts/module.js +++ b/scripts/module.js @@ -9,7 +9,7 @@ Hooks.on("ready", async () => { Hooks.on("createChatMessage", async function (msg, status, id) { //console.log({ msg }) if (!msg.isDamageRoll || !game.user.isGM) return; - const dmg_list = extractDamageInfoCombined(msg.rolls); + const dmg_list = getDamageList(msg.rolls); const targets = getTargetList(msg); //console.log({ targets, dmg_list }) generateDamageScroll(dmg_list, targets); @@ -23,6 +23,26 @@ export function getTargetList(msg) { } } +export function getDamageList(rolls) { + const split_type = game.settings.get("pf2e-rpg-numbers", 'damage-split'); + let dmg_list = []; + switch (split_type) { + case 'none': + dmg_list = extractDamageInfoSimple(rolls); + break; + case 'split-by-type': + dmg_list = extractDamageInfoCombined(rolls); + break; + case 'split-all': + dmg_list = extractDamageInfoAll(rolls); + break; + default: + dmg_list = extractDamageInfoSimple(rolls); + break; + } + return dmg_list; +} + //TODO settings on visuals (colors) //TODO settings on size etc. //TODO add scaling based on % health @@ -98,14 +118,87 @@ export function extractDamageInfoCombined(rolls) { for (const inp of rolls) { for (const term of inp.terms) { for (const roll of term.rolls) { - const dmg = { type: roll.type, value: roll.total }; - result.push(dmg); + result.push({ type: roll.type, value: roll.total }); } } } return result; } +export function extractDamageInfoAll(rolls) { + let result = []; + + for (const inp of rolls) { + for (const term of inp.terms) { + result = result.concat(extractTerm(term)) + } + } + console.log(result) + return result; +} + +export function extractDamageInfoSimple(rolls) { + return [{ type: '', value: rolls.total }] +} + +export function extractTerm(term, flavor = '') { + let result = []; + switch (term.class) { + case 'PoolTerm': + for (const roll of term.rolls) { + result = result.concat(extractTerm(roll, term.flavor || flavor)); + } + break; + case '_DamageInstance2': + for (const item of term.terms) { + result = result.concat(extractTerm(item, term.types || flavor)); + } + break; + case 'Grouping': + result = result.concat(extractTerm(term.term, term.flavor || flavor)); + break; + case '_ArithmeticExpression2': + switch (term.operator) { + case '+': + for (const op of term.operands) { + result = result.concat(extractTerm(op, term.flavor || flavor)); + } + break; + case '-': + result = result.concat(extractTerm(term.operands[0], term.flavor || flavor)); + result = result.concat(extractTerm(term.operands[1], term.flavor || flavor)).map(t => { return { value: -t.value, type: t.type } }); + case '*': + if (['NumericTerm', 'Die'].includes(term.operands[0].class)) { + result = result.concat(extractTerm(term.operands[1], term.flavor || flavor).flatMap(i => [i, i])); + } else if (['NumericTerm', 'Die'].includes(term.operands[1].class)) { + result = result.concat(extractTerm(term.operands[0], term.flavor || flavor).flatMap(i => [i, i])); + } else { + result.push({ value: term.total, type: term.flavor || flavor }) + } + + break; + default: + break; + } + break; + case 'Die': + for (const dice of term.results) { + result.push({ value: dice.result, type: term.flavor || flavor }) + } + break; + case 'NumericTerm': + result.push({ value: term.number, type: term.flavor || flavor }) + break; + + default: + console.error({ msg: "Unrecognized Term when extracting parts", term }) + result.push({ value: term.total, type: term.flavor || flavor }) + break; + } + + return result; +} + export function getFontScale(scaleType, dmg, tok) { const maxFontScale = game.settings.get("pf2e-rpg-numbers", 'max-font-scale'); let scale = maxFontScale - 1; diff --git a/scripts/settings.js b/scripts/settings.js index 1b2d64a..31f04bb 100644 --- a/scripts/settings.js +++ b/scripts/settings.js @@ -52,4 +52,18 @@ Hooks.on("init", () => { }, }); + game.settings.register("pf2e-rpg-numbers", "damage-split", { + name: game.i18n.localize("pf2e-rpg-numbers.module-settings.damage-split.name"), + hint: game.i18n.localize("pf2e-rpg-numbers.module-settings.damage-split.hint"), + scope: "world", + config: true, + default: "split-by-type", + type: String, + choices: { + ["none"]: game.i18n.localize("pf2e-rpg-numbers.module-settings.damage-split.choices.none"), + ["split-by-type"]: game.i18n.localize("pf2e-rpg-numbers.module-settings.damage-split.split-by-type"), + ["split-all"]: game.i18n.localize("pf2e-rpg-numbers.module-settings.damage-split.choices.split-all"), + }, + }); + }); \ No newline at end of file