diff --git a/TODO b/TODO index d4c68eb..4640904 100644 --- a/TODO +++ b/TODO @@ -1,2 +1 @@ # TODO -- Add Character shake on taking damage diff --git a/module.json b/module.json index e4229b9..6e55bc1 100644 --- a/module.json +++ b/module.json @@ -29,8 +29,8 @@ "type": "module", "manifest": "https://github.com/fantasycalendar/FoundryVTT-Sequencer/releases/latest/download/manifest.json", "compatibility": { - "minimum": "3.0.0", - "verified": "3.2.0" + "minimum": "3.2.0", + "verified": "3.2.17" } } ], @@ -52,6 +52,18 @@ "path": "languages/en.json" } ], + "packs": [ + { + "name": "pf2e-rpg-numbers-macros", + "label": "PF2e RPG Numbers Macros", + "path": "packs/pf2e-rpg-numbers-macros", + "type": "Macro", + "ownership": { + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" + } + } + ], "url": "#{URL}#", "manifest": "#{MANIFEST}#", "download": "#{DOWNLOAD}#", diff --git a/packs/pf2e-rpg-numbers-macros/000004.log b/packs/pf2e-rpg-numbers-macros/000004.log new file mode 100644 index 0000000..e69de29 diff --git a/packs/pf2e-rpg-numbers-macros/000005.ldb b/packs/pf2e-rpg-numbers-macros/000005.ldb new file mode 100644 index 0000000..15710fc Binary files /dev/null and b/packs/pf2e-rpg-numbers-macros/000005.ldb differ diff --git a/packs/pf2e-rpg-numbers-macros/CURRENT b/packs/pf2e-rpg-numbers-macros/CURRENT new file mode 100644 index 0000000..1a84852 --- /dev/null +++ b/packs/pf2e-rpg-numbers-macros/CURRENT @@ -0,0 +1 @@ +MANIFEST-000002 diff --git a/packs/pf2e-rpg-numbers-macros/LOCK b/packs/pf2e-rpg-numbers-macros/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/packs/pf2e-rpg-numbers-macros/LOG b/packs/pf2e-rpg-numbers-macros/LOG new file mode 100644 index 0000000..37b3d3d --- /dev/null +++ b/packs/pf2e-rpg-numbers-macros/LOG @@ -0,0 +1,5 @@ +2024/09/14-03:13:29.106469 ffffa5323160 Delete type=3 #1 +2024/09/14-05:59:35.270026 fffd76be6160 Level-0 table #5: started +2024/09/14-05:59:35.272124 fffd76be6160 Level-0 table #5: 7490 bytes OK +2024/09/14-05:59:35.273677 fffd76be6160 Delete type=0 #3 +2024/09/14-05:59:35.275404 fffd76be6160 Manual compaction at level-0 from '!folders!rngZJOfNPRnS74nx' @ 72057594037927935 : 1 .. '!macros!meCWcoIxCOajKyBy' @ 0 : 0; will stop at (end) diff --git a/packs/pf2e-rpg-numbers-macros/MANIFEST-000002 b/packs/pf2e-rpg-numbers-macros/MANIFEST-000002 new file mode 100644 index 0000000..c81f245 Binary files /dev/null and b/packs/pf2e-rpg-numbers-macros/MANIFEST-000002 differ diff --git a/resources/sounds/eldenRingDeath.ogg b/resources/sounds/eldenRingDeath.ogg new file mode 100644 index 0000000..3c17861 Binary files /dev/null and b/resources/sounds/eldenRingDeath.ogg differ diff --git a/resources/sounds/eldenRingVictory.ogg b/resources/sounds/eldenRingVictory.ogg new file mode 100644 index 0000000..40f5dbe Binary files /dev/null and b/resources/sounds/eldenRingVictory.ogg differ diff --git a/resources/sounds/eldenRingVictoryReverb.ogg b/resources/sounds/eldenRingVictoryReverb.ogg new file mode 100644 index 0000000..a5dc390 Binary files /dev/null and b/resources/sounds/eldenRingVictoryReverb.ogg differ diff --git a/scripts/helpers/animation/crit/critAnimation.js b/scripts/helpers/animation/crit/critAnimation.js index 81c4d9d..d8a8fab 100644 --- a/scripts/helpers/animation/crit/critAnimation.js +++ b/scripts/helpers/animation/crit/critAnimation.js @@ -10,12 +10,42 @@ import { personaCrit } from "./personaCrit.js"; * @returns {void} */ export function createCritAnimation(rollDeets, critType = getSetting("critical.type")) { - //TODO add option for default color - if (cancelCriticalHit(rollDeets)) return; + if (shouldCancelCriticalHit(rollDeets)) return; + const imgData = getImageData(rollDeets); + if (!imgData) return; + + const config = getAnimationConfig(); + const users = getEligibleUsers(rollDeets); + + displayCritAnimation(critType, rollDeets.token, users, imgData, config); +} + +/** + * Determines if the critical hit animation should be canceled. + * @param {object} rollDeets - The details of the roll. + * @returns {boolean} True if the animation should be canceled, false otherwise. + */ +function shouldCancelCriticalHit(rollDeets) { + const isAttack = rollDeets.type === "attack-roll"; + const showOn = getSetting("critical.show-on"); + return rollDeets.type !== "custom" && ((showOn === "checks" && isAttack) || (showOn === "attacks" && !isAttack)); +} + +/** + * Retrieves the image data for the animation. + * @param {object} rollDeets - The details of the roll. + * @returns {object|null} The image data object or null if not applicable. + */ +function getImageData(rollDeets) { const enabledTokenType = getSetting("critical.show-on-token-type"); const defaultImgType = getSetting("critical.default-img"); const actorType = rollDeets.token.actor.type; + + if (!shouldDisplayForTokenType(rollDeets, enabledTokenType, actorType)) { + return null; + } + const imgData = { img: "icons/svg/cowled.svg", xScale: 1, @@ -25,47 +55,83 @@ export function createCritAnimation(rollDeets, critType = getSetting("critical.t isToken: true, }; - if ( + if (shouldUseTokenImage(actorType, defaultImgType)) { + imgData.img = rollDeets?.token?.texture?.src; + imgData.xScale = rollDeets?.token?.texture?.scaleX ?? 1; + imgData.yScale = rollDeets?.token?.texture?.scaleY ?? 1; + } else { + imgData.img = rollDeets?.token?.actor?.img; + imgData.isToken = false; + } + + return imgData; +} + +/** + * Determines if the animation should be displayed for the given token type. + * @param {object} rollDeets - The details of the roll. + * @param {string} enabledTokenType - The enabled token type setting. + * @param {string} actorType - The type of the actor. + * @returns {boolean} True if the animation should be displayed, false otherwise. + */ +function shouldDisplayForTokenType(rollDeets, enabledTokenType, actorType) { + return ( rollDeets.type === "custom" || (actorType === "character" && enabledTokenType !== "npc") || (actorType !== "character" && enabledTokenType !== "pc") - ) { - if (actorType === "character" ? defaultImgType?.startsWith("pc-tok") : defaultImgType?.includes("npc-tok")) { - // Token - imgData.img = rollDeets?.token?.texture?.src; - imgData.xScale = rollDeets?.token?.texture?.scaleX ?? 1; - imgData.yScale = rollDeets?.token?.texture?.scaleY ?? 1; - } else { - // actor - imgData.img = rollDeets?.token?.actor?.img; - imgData.isToken = false; - } - } else { - return; - } - const config = { + ); +} + +/** + * Determines if the token image should be used. + * @param {string} actorType - The type of the actor. + * @param {string} defaultImgType - The default image type setting. + * @returns {boolean} True if the token image should be used, false otherwise. + */ +function shouldUseTokenImage(actorType, defaultImgType) { + return actorType === "character" ? defaultImgType?.startsWith("pc-tok") : defaultImgType?.includes("npc-tok"); +} + +/** + * Retrieves the animation configuration. + * @returns {object} The animation configuration object. + */ +function getAnimationConfig() { + return { delay: getSetting("critical.delay") * 1000, - sfx: rollDeets?.token?.flags?.["pf2e-rpg-numbers"]?.["critSFX"] || getSetting("critical.sound"), + sfx: getSetting("critical.sound"), volume: getSetting("critical.volume") / 100, }; +} - const users = getVisibleAndMsgVisibleUsers(rollDeets).filter( +/** + * Retrieves the list of eligible users for the animation. + * @param {object} rollDeets - The details of the roll. + * @returns {string[]} An array of eligible user IDs. + */ +function getEligibleUsers(rollDeets) { + return getVisibleAndMsgVisibleUsers(rollDeets).filter( (uID) => game.users.get(uID).getFlag(MODULE_ID, "critEnabled") !== false ); +} + +/** + * Displays the critical hit animation based on the specified type. + * @param {string} critType - The type of critical animation to display. + * @param {object} token - The token object. + * @param {string[]} users - The list of eligible user IDs. + * @param {object} imgData - The image data for the animation. + * @param {object} config - The animation configuration. + */ +function displayCritAnimation(critType, token, users, imgData, config) { switch (critType) { case "persona": - personaCrit(rollDeets.token, users, imgData, config); + personaCrit(token, users, imgData, config); break; case "fire-emblem": - fireEmblemCrit(rollDeets.token, users, imgData, config); + fireEmblemCrit(token, users, imgData, config); break; default: - return; + break; } -} - -function cancelCriticalHit(rollDeets) { - const isAttack = rollDeets.type === "attack-roll"; - const showOn = getSetting("critical.show-on"); - return rollDeets.type !== "custom" && ((showOn === "checks" && isAttack) || (showOn === "attacks" && !isAttack)); -} +} \ No newline at end of file diff --git a/scripts/helpers/api.js b/scripts/helpers/api.js index 5e52ac1..97f4f8a 100644 --- a/scripts/helpers/api.js +++ b/scripts/helpers/api.js @@ -4,12 +4,13 @@ import { generateDamageScroll } from "./animation/generateDamageScroll.js"; import { generateRollScroll } from "./animation/generateRollScroll.js"; import { getDamageList } from "./rollTerms.js"; import { eldenRingDeath, eldenRingNounVerbed } from "./animation/text/fromSoftwareText.js"; +import { turnTokenOnAttack } from "./animation/turnTokenOnAttack.js"; export function createAPI() { game.pf2eRPGNumbers = { damageNumbers: { generate: async function (dmgList, targetIDs) { - return generateDamageScroll(dmgList, targetIDs); + return generateDamageScroll(dmgList, targetIDs, { whisper: game.users.map(u => u.id) }); }, getDamageList: function (msg) { return getDamageList(msg.rolls); @@ -32,7 +33,7 @@ export function createAPI() { }, turnTokenAttack: { generate: function (tokenObject, targetTokenObject) { - turnTokenAttack(tokenObject, targetTokenObject); + turnTokenOnAttack(tokenObject, targetTokenObject); }, }, fromSoftware: { diff --git a/scripts/settings.js b/scripts/settings.js index 462b794..50aa678 100644 --- a/scripts/settings.js +++ b/scripts/settings.js @@ -692,7 +692,7 @@ Hooks.on("init", () => { scope: "world", config: true, type: String, - default: "", //TODO replace with options for each type + default: option === 'death' ? "modules/pf2e-rpg-numbers/resources/sounds/eldenRingDeath.ogg" : "modules/pf2e-rpg-numbers/resources/sounds/eldenRingVictoryReverb.ogg", filePicker: "audio", });