From 0d0257fb6e52a0348d7e1d714d508675ccb62441 Mon Sep 17 00:00:00 2001 From: Haxxer Date: Wed, 4 Oct 2023 22:47:48 +0100 Subject: [PATCH] Final fixes --- languages/en.json | 10 +++++++-- scripts/constants.js | 12 +++++++++++ scripts/minion.js | 49 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/languages/en.json b/languages/en.json index 684185d..cd558a8 100644 --- a/languages/en.json +++ b/languages/en.json @@ -7,8 +7,10 @@ }, "OverkillDamage": { "Title": "Overkill Damage!", - "Label1": "You can destroy a total of {targets} \"${name}\" minions within your weapon's range.", - "Label2": "Once you're happy with your targets, press OK." + "MeleeLabel1": "You can destroy a total of {max_targets} \"{name}\" minions within your attack's range.", + "RangedLabel1": "You can destroy a total of {max_targets} \"{name}\" minions directly behind the original target and within your attack's range.", + "Label2": "Total targets remaining: {total_targets}/{max_targets}", + "Label3": "Once you're happy with your targets, press OK." } }, "ActorContextMenu": { @@ -35,6 +37,10 @@ "Title": "Enable Overkill Damage", "Hint": "When enabled, if minion is hit by an attack that exceeds its hit points, the attacker is allowed to transfer the remaining damage to adjacent similar minions, repeating until the damage reaches 0." }, + "EnableRangedOverkill": { + "Title": "Enable Ranged Overkill Damage", + "Hint": "When enabled, ranged attacks also trigger overkill damage. The MDCM rules allow this, so long the subsequent targets are in a line directly behind the original target." + }, "EnableGroupAttacks": { "Title": "Enable Minion Group Attacks", "Hint": "When enabled, minion group attacks automatically prompt to ask how many minions are attacking the target." diff --git a/scripts/constants.js b/scripts/constants.js index d4f3dc8..7581197 100644 --- a/scripts/constants.js +++ b/scripts/constants.js @@ -14,6 +14,8 @@ const CONSTANTS = { } }], ATTACK_TYPES: ["mwak", "rwak", "msak", "rsak"], + MELEE_ATTACKS: ["mwak", "msak"], + RANGED_ATTACKS: ["rwak", "rsak"], FLAGS: { COMBATANTS: `${FLAG}.combatants`, GROUP_NUMBER: `${FLAG}.groupNumber`, @@ -25,6 +27,7 @@ const CONSTANTS = { CONSTANTS["SETTING_KEYS"] = { DEBUG: "debug", ENABLE_OVERKILL_DAMAGE: "enableOverkillDamage", + ENABLE_RANGED_OVERKILL: "enableRangedOverkill", ENABLE_GROUP_ATTACKS: "enableGroupAttacks", ENABLE_GROUP_ATTACK_BONUS: "enableGroupAttackBonus", ENABLE_MINION_SUPER_SAVE: "enableMinionSuperSave", @@ -51,6 +54,15 @@ CONSTANTS["SETTINGS"] = { type: Boolean }, + [CONSTANTS.SETTING_KEYS.ENABLE_RANGED_OVERKILL]: { + name: "MINIONMANAGER.Settings.EnableRangedOverkill.Title", + hint: "MINIONMANAGER.Settings.EnableRangedOverkill.Hint", + scope: "world", + config: true, + default: true, + type: Boolean + }, + [CONSTANTS.SETTING_KEYS.ENABLE_GROUP_ATTACKS]: { name: "MINIONMANAGER.Settings.EnableGroupAttacks.Title", hint: "MINIONMANAGER.Settings.EnableGroupAttacks.Hint", diff --git a/scripts/minion.js b/scripts/minion.js index 24da633..3b103b9 100644 --- a/scripts/minion.js +++ b/scripts/minion.js @@ -81,8 +81,10 @@ export function initializeMinions() { // Overkill management const actionType = workflow.item.system?.actionType; + const isRangedAttack = CONSTANTS.RANGED_ATTACKS.includes(actionType); - if (!actionType || !(actionType === "mwak" || actionType === "msak")) return true; + if (!actionType || !CONSTANTS.ATTACK_TYPES.includes(actionType)) return true; + if (!lib.getSetting(CONSTANTS.SETTING_KEYS.ENABLE_RANGED_OVERKILL) && isRangedAttack) return true; if (!workflow.hitTargets.size) return true; const hitTarget = Array.from(workflow.hitTargets)[0] @@ -98,26 +100,48 @@ export function initializeMinions() { damageTotal -= minionHP; const closestTokens = new Set(canvas.tokens.placeables - .filter(_token => hitTarget.actor.name === _token.actor.name && canvas.grid.measureDistance(workflow.token, _token) <= workflow.item.system.range.value + 2.5) + .filter(_token => { + const withinRange = canvas.grid.measureDistance(workflow.token, _token) <= workflow.item.system.range.value + 2.5; + return hitTarget.actor.name === _token.actor.name && withinRange; + }) .sort((a, b) => canvas.grid.measureDistance(workflow.token, b) - canvas.grid.measureDistance(workflow.token, a))); - closestTokens.delete(game.user.targets.first()) + closestTokens.delete(game.user.targets.first()); let maxAdditionalTargets = Math.ceil(damageTotal / minionHP); Array.from(closestTokens) .slice(0, maxAdditionalTargets) .forEach(_token => _token.setTarget(true, { releaseOthers: false })); - await Dialog.confirm({ + const label1Localization = "MINIONMANAGER.Dialogs.OverkillDamage." + (isRangedAttack ? "RangedLabel1" : "MeleeLabel1"); + const label1 = game.i18n.format(label1Localization, { + max_targets: maxAdditionalTargets + 1, + total_targets: game.user.targets.size, + name: hitTarget.actor.name + }); + + let label2 = game.i18n.format("MINIONMANAGER.Dialogs.OverkillDamage.Label2", { + max_targets: maxAdditionalTargets + 1, + total_targets: game.user.targets.size + }); + + let targetingHookId = false; + await Dialog.prompt({ "title": game.i18n.localize("MINIONMANAGER.Dialogs.OverkillDamage.Title"), "content": ` -

${game.i18n.format("MINIONMANAGER.Dialogs.OverkillDamage.Label1", { - targets: maxAdditionalTargets + 1, - name: hitTarget.actor.name - })}

-

${game.i18n.localize("MINIONMANAGER.Dialogs.OverkillDamage.Label2")}

+

${label1}

+

${label2}

+

${game.i18n.localize("MINIONMANAGER.Dialogs.OverkillDamage.Label3")}

`, "rejectClose": false, + render: (html) => { + targetingHookId = Hooks.on("targetToken", () => { + html.find(".minion-manager-targets").text(game.i18n.format("MINIONMANAGER.Dialogs.OverkillDamage.Label2", { + max_targets: maxAdditionalTargets + 1, + total_targets: game.user.targets.size + })) + }) + }, options: { top: 150 } }); @@ -127,7 +151,12 @@ export function initializeMinions() { userTargets.delete(hitTarget); - [...userTargets].slice(0, maxAdditionalTargets).forEach(target => workflow.hitTargets.add(target)); + await MidiQOL.applyTokenDamage( + workflow.damageDetail, + workflow.damageTotal, + new Set([...userTargets].slice(0, maxAdditionalTargets)), + workflow.item + ) return true;