diff --git a/scripts/constants.js b/scripts/constants.js index 3d4151d..a8644f8 100644 --- a/scripts/constants.js +++ b/scripts/constants.js @@ -37,6 +37,7 @@ CONSTANTS["SETTING_KEYS"] = { ENABLE_MINION_SUPER_SAVE: "enableMinionSuperSave", MINION_FEATURE_NAME: "minionFeatureName", MINION_FEATURE_DESCRIPTION: "minionFeatureDescription", + ENABLE_MINION_FEATURE_AUTOMATION: "enableMinionFeatureAutomation" } CONSTANTS["SETTINGS"] = { diff --git a/scripts/minion.js b/scripts/minion.js index 4d65f04..95c8909 100644 --- a/scripts/minion.js +++ b/scripts/minion.js @@ -20,4 +20,58 @@ export function initializeMinions() { return true; }); + Hooks.on("updateActor", (doc) => { + const actorIsMinion = api.isMinion(doc); + if (!doc.token || !actorIsMinion || getProperty(doc, "system.attributes.hp.value") > 0) return true; + const groupNumber = getProperty(doc.token, CONSTANTS.FLAGS.GROUP_NUMBER); + if (!groupNumber || !game.combats.viewed) return true; + const existingCombatant = game.combats.viewed.combatants.find(combatant => getProperty(combatant.token, CONSTANTS.FLAGS.GROUP_NUMBER) === groupNumber); + if (!existingCombatant) return true; + const existingSubCombatants = foundry.utils.deepClone(getProperty(existingCombatant, CONSTANTS.FLAGS.COMBATANTS)); + if (!existingSubCombatants?.length) return true; + const newToken = existingSubCombatants.map(uuid => fromUuidSync(uuid)).filter(foundToken => { + return foundToken?.actor?.id && getProperty(foundToken?.actor, "system.attributes.hp.value") > 0; + }); + if (!newToken.length) return true; + existingCombatant.update({ + actorId: newToken[0].actor.id, + tokenId: newToken[0].id + }); + }); + + /*Hooks.on("updateActor", (doc) => { + if(!game.user.isGM || !game.combats.viewed) return; + + const actorIsMinion = api.isMinion(doc); + if(!actorIsMinion) return; + + const groupNumber = getProperty(doc.token, CONSTANTS.FLAGS.GROUP_NUMBER); + if (!groupNumber) return; + + const existingCombatant = game.combats.viewed.combatants.find(combatant => getProperty(combatant.token, CONSTANTS.FLAGS.GROUP_NUMBER) === groupNumber); + if (!existingCombatant) return; + + const subCombatants = foundry.utils.deepClone(getProperty(existingCombatant, CONSTANTS.FLAGS.COMBATANTS) ?? []) + if (!subCombatants.length) return; + + const documents = subCombatants.map((uuid) => fromUuidSync(uuid)).filter(Boolean); + const everyMinionDefeated = documents.every(tokenDocument => tokenDocument.actor.system.attributes.hp.value === 0); + if(!everyMinionDefeated) return; + + setTimeout(() => { + canvas.scene.deleteEmbeddedDocuments("Token", documents.map(tokenDocument => tokenDocument.id)); + }, 500); + + Dialog.confirm({ + title: 'Group Defeated', + content: ` +

Would you like to delete group number ${groupNumber}?

+ `, + yes: () => { + canvas.scene.deleteEmbeddedDocuments("Token", documents.map(tokenDocument => tokenDocument.id)); + }, + options: { height: "100%" } + }); + });*/ + } diff --git a/scripts/plugins/midiqol.js b/scripts/plugins/midiqol.js index 9db3c4f..0d167ea 100644 --- a/scripts/plugins/midiqol.js +++ b/scripts/plugins/midiqol.js @@ -14,7 +14,7 @@ export default { const isGroupAttack = getProperty(workflow.item, CONSTANTS.FLAGS.MIDI_GROUP_ATTACK) ?? false; - if (!api.isMinion(workflow.actor) || !isGroupAttack) return true; + if (!workflow?.actor || !api.isMinion(workflow?.actor) || !isGroupAttack) return true; const result = await Dialog.confirm({ title: game.i18n.localize("MINIONMANAGER.Dialogs.MinionAttack.Title"), @@ -105,11 +105,11 @@ export default { const hitTarget = Array.from(workflow.hitTargets)[0] - if (!api.isMinion(hitTarget.actor)) return true; + if (!hitTarget?.actor || !api.isMinion(hitTarget?.actor)) return true; let damageTotal = workflow.damageTotal; - const minionHP = getProperty(hitTarget.actor, "system.attributes.hp.value"); + const minionHP = getProperty(hitTarget?.actor, "system.attributes.hp.value"); if ((minionHP - damageTotal) > 0) return true; @@ -118,9 +118,9 @@ export default { const closestTokens = new Set(canvas.tokens.placeables .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; + return hitTarget?.actor && _token?.actor && hitTarget?.actor?.name === _token?.actor?.name && withinRange; }) - .sort((a, b) => canvas.grid.measureDistance(workflow.token, b) - canvas.grid.measureDistance(workflow.token, a))); + .sort((a, b) => canvas.grid.measureDistance(workflow.token, a) - canvas.grid.measureDistance(workflow.token, b))); closestTokens.delete(game.user.targets.first()); diff --git a/scripts/plugins/vanilla.js b/scripts/plugins/vanilla.js index 0c4970d..7476d57 100644 --- a/scripts/plugins/vanilla.js +++ b/scripts/plugins/vanilla.js @@ -113,7 +113,7 @@ export default { const hitTarget = hitTargets[0]; - if (!api.isMinion(hitTarget) || api.isMinion(item.parent)) return true; + if (!hitTarget?.actor || !api.isMinion(hitTarget?.actor) || api.isMinion(item.parent)) return true; let damageTotal = damageRoll.total; @@ -129,7 +129,7 @@ export default { const label1 = game.i18n.format(label1Localization, { max_targets: maxAdditionalTargets + 1, total_targets: game.user.targets.size, - name: hitTarget.actor.name + name: hitTarget?.actor?.name ?? "unknown" }); if (lib.getSetting(CONSTANTS.SETTING_KEYS.ENABLE_OVERKILL_MESSAGE)) {