From b96ef74b9a56b2fede4b77f0e6c47c1ce67d8fb2 Mon Sep 17 00:00:00 2001 From: PrototypeESBU <> Date: Wed, 23 Oct 2024 19:12:46 +1000 Subject: [PATCH 1/7] Initial working --- system/shadowdark.mjs | 2 ++ system/src/utils/ChecksSD.mjs | 57 +++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 system/src/utils/ChecksSD.mjs diff --git a/system/shadowdark.mjs b/system/shadowdark.mjs index 1723f33d..baeccfc0 100644 --- a/system/shadowdark.mjs +++ b/system/shadowdark.mjs @@ -7,6 +7,7 @@ import registerSystemSettings from "./src/settings.mjs"; import SHADOWDARK from "./src/config.mjs"; import ShadowdarkMacro from "./src/macro.mjs"; import UtilitySD from "./src/utils/UtilitySD.mjs"; +import ChecksSD from "./src/utils/ChecksSD.mjs"; import * as apps from "./src/apps/_module.mjs"; import * as chat from "./src/chat/_module.mjs"; @@ -75,6 +76,7 @@ Hooks.once("init", () => { registerSystemSettings(); loadTemplates(); + ChecksSD.registerEnrichers(); UtilitySD.loadLegacyArtMappings(); // Register sheet application classes diff --git a/system/src/utils/ChecksSD.mjs b/system/src/utils/ChecksSD.mjs new file mode 100644 index 00000000..e0fe0efc --- /dev/null +++ b/system/src/utils/ChecksSD.mjs @@ -0,0 +1,57 @@ +export default class ChecksSD { + + static async registerEnrichers() { + console.warn("enricher"); + // load custom text enrichers + // [[/check STAT DC]] + // [[/request STAT DC]] + CONFIG.TextEditor.enrichers.push({ + pattern: /\[\[\/(?check|request)\s(?\w{3})\s(?\d+)\]\]/g, + enricher: async (match, options) => { + let { command, stat, dc } = match.groups; + const link = document.createElement("a"); + link.dataset.command = command; + link.dataset.stat = stat; + link.dataset.dc = dc; + switch (command) { + case "check": + link.innerHTML = `DC ${dc} ${stat}`; + break; + case "request": + link.innerHTML = `DC ${dc} ${stat}`; + break; + } + return link; + }, + }); + + document.body.addEventListener("click", this.checkHandler); + } + + static async checkHandler(event) { + let data = event.target?.dataset; + if ( !data.command ) return; + + let options = {}; + if (event.shiftKey) { + options.fastForward = true; + } + + switch (data.command) { + case "check": + let actor = game.user.character; + if (actor) { + actor.rollAbility(data.stat, options); + } + else { + ui.notification.error("You do not have a character selected!"); + } + + break; + case "request": + console.log("Request Check"); + break; + } + } + +} From f7770ec30ecfade011d0154123e31269a02d4fc8 Mon Sep 17 00:00:00 2001 From: PrototypeESBU <> Date: Sun, 27 Oct 2024 21:15:43 +1000 Subject: [PATCH 2/7] Working. needs clean up --- system/shadowdark.mjs | 1 + system/src/utils/ChecksSD.mjs | 63 +++++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/system/shadowdark.mjs b/system/shadowdark.mjs index baeccfc0..5caae811 100644 --- a/system/shadowdark.mjs +++ b/system/shadowdark.mjs @@ -39,6 +39,7 @@ globalThis.shadowdark = { log: Logger.log, macro: ShadowdarkMacro, sheets, + checks: ChecksSD, utils: UtilitySD, warn: Logger.warn, }; diff --git a/system/src/utils/ChecksSD.mjs b/system/src/utils/ChecksSD.mjs index e0fe0efc..13a4b28a 100644 --- a/system/src/utils/ChecksSD.mjs +++ b/system/src/utils/ChecksSD.mjs @@ -1,24 +1,31 @@ export default class ChecksSD { static async registerEnrichers() { - console.warn("enricher"); // load custom text enrichers - // [[/check STAT DC]] - // [[/request STAT DC]] + // [[check DC STAT]] + // [[request DC STAT]] CONFIG.TextEditor.enrichers.push({ - pattern: /\[\[\/(?check|request)\s(?\w{3})\s(?\d+)\]\]/g, + pattern: /\[\[(?check|request)\s(?\d+)\s(?\w{3})\]\]/g, enricher: async (match, options) => { - let { command, stat, dc } = match.groups; + let { command, dc, stat } = match.groups; + + // Check for invalid data + if (!parseInt(dc)) return; + if (!CONFIG.SHADOWDARK.ABILITY_KEYS.includes(stat.toLowerCase())) return; + + // create replacement html const link = document.createElement("a"); + link.className = "content-link"; link.dataset.command = command; - link.dataset.stat = stat; link.dataset.dc = dc; + link.dataset.stat = stat; + const linkText = `DC ${dc} ${stat.toUpperCase()}`; switch (command) { case "check": - link.innerHTML = `DC ${dc} ${stat}`; + link.innerHTML = `${linkText}`; break; case "request": - link.innerHTML = `DC ${dc} ${stat}`; + link.innerHTML = `${linkText}`; break; } return link; @@ -32,26 +39,40 @@ export default class ChecksSD { let data = event.target?.dataset; if ( !data.command ) return; - let options = {}; - if (event.shiftKey) { - options.fastForward = true; - } - switch (data.command) { case "check": - let actor = game.user.character; - if (actor) { - actor.rollAbility(data.stat, options); + let options = {}; + if (event.shiftKey) { + options.fastForward = true; } - else { - ui.notification.error("You do not have a character selected!"); - } - + shadowdark.checks.rollCheck(data.dc, data.stat, options); break; case "request": - console.log("Request Check"); + shadowdark.checks.displayRequest(data.dc, data.stat); break; } } + static async rollCheck(dc, stat, options={}) { + let actor = game.user.character; + if (!actor) { + ui.notification.error("You do not have a character selected!"); + } + if (dc) { + options.target = dc; + } + actor.rollAbility(stat, options); + } + + + static async displayRequest(dc, stat) { + const HTML = `
[[check ${dc} ${stat}]]
`; + const chatData = { + user: game.user._id, + flavor: "Requesting a check", + content: HTML, + }; + ChatMessage.create(chatData, {}); + } + } From 2bb0d8aef32a06a3a18f1f602878e9f2cd57d5c4 Mon Sep 17 00:00:00 2001 From: PrototypeESBU <> Date: Mon, 28 Oct 2024 08:59:25 +1000 Subject: [PATCH 3/7] prevented error when using uppercase --- system/src/utils/ChecksSD.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/utils/ChecksSD.mjs b/system/src/utils/ChecksSD.mjs index 13a4b28a..840e17c0 100644 --- a/system/src/utils/ChecksSD.mjs +++ b/system/src/utils/ChecksSD.mjs @@ -61,7 +61,7 @@ export default class ChecksSD { if (dc) { options.target = dc; } - actor.rollAbility(stat, options); + actor.rollAbility(stat.toLowerCase(), options); } From ef452872968b5d88c09f717ce779f909dee274bd Mon Sep 17 00:00:00 2001 From: PrototypeESBU <> Date: Fri, 1 Nov 2024 14:27:06 +1000 Subject: [PATCH 4/7] added localization --- i18n/en.yaml | 2 ++ system/src/utils/ChecksSD.mjs | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/i18n/en.yaml b/i18n/en.yaml index d3ecd870..8f73f4c7 100644 --- a/i18n/en.yaml +++ b/i18n/en.yaml @@ -185,6 +185,7 @@ SHADOWDARK.chat.welcome_message.title_text: Welceome to Shadowdark RPG. Here are SHADOWDARK.chat.welcome_message.title: Shadowdark RPG for Foundry SHADOWDARK.chat.welcome_message.watch: Watch the Video Tutorial SHADOWDARK.chatcard.default: Roll +SHADOWDARK.check.requesting: Requesting a check SHADOWDARK.class-ability.ability.check: Ability Check SHADOWDARK.class-ability.ability.label: Ability SHADOWDARK.class-ability.available.label: Available @@ -333,6 +334,7 @@ SHADOWDARK.effect.unavailable: Disabled Effects SHADOWDARK.error.class_ability.no-uses-remaining: No uses remaining SHADOWDARK.error.general.gm_required: You must have the Game Master role to do that. SHADOWDARK.error.general.no_character_class: No character class has been selected +SHADOWDARK.error.general.no_character_selected: No character selected SHADOWDARK.error.source.source_missing: Source missing or unknown... SHADOWDARK.error.spells.no_spellcasting_ability_set: No character spellcasting ability has been configured SHADOWDARK.form.section_header.equipment.label: Equipment diff --git a/system/src/utils/ChecksSD.mjs b/system/src/utils/ChecksSD.mjs index 840e17c0..1df2deb3 100644 --- a/system/src/utils/ChecksSD.mjs +++ b/system/src/utils/ChecksSD.mjs @@ -19,7 +19,7 @@ export default class ChecksSD { link.dataset.command = command; link.dataset.dc = dc; link.dataset.stat = stat; - const linkText = `DC ${dc} ${stat.toUpperCase()}`; + const linkText = `${game.i18n.localize("SHADOWDARK.class-ability.dc.label")} ${dc} ${game.i18n.localize(`SHADOWDARK.ability_${stat}`)}`.toUpperCase(); switch (command) { case "check": link.innerHTML = `${linkText}`; @@ -56,7 +56,9 @@ export default class ChecksSD { static async rollCheck(dc, stat, options={}) { let actor = game.user.character; if (!actor) { - ui.notification.error("You do not have a character selected!"); + ui.notification.error( + game.i18n.localize("SHADOWDARK.error.general.no_character_selected") + ); } if (dc) { options.target = dc; @@ -69,7 +71,7 @@ export default class ChecksSD { const HTML = `
[[check ${dc} ${stat}]]
`; const chatData = { user: game.user._id, - flavor: "Requesting a check", + flavor: game.i18n.localize("SHADOWDARK.check.requesting"), content: HTML, }; ChatMessage.create(chatData, {}); From 801d6f179f841125850ad82b356f9ae1fd0cc51e Mon Sep 17 00:00:00 2001 From: PrototypeESBU <> Date: Thu, 31 Oct 2024 22:19:57 -0700 Subject: [PATCH 5/7] added flexibility when matching stat --- system/src/utils/ChecksSD.mjs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/system/src/utils/ChecksSD.mjs b/system/src/utils/ChecksSD.mjs index 1df2deb3..ee36dedc 100644 --- a/system/src/utils/ChecksSD.mjs +++ b/system/src/utils/ChecksSD.mjs @@ -11,7 +11,12 @@ export default class ChecksSD { // Check for invalid data if (!parseInt(dc)) return; - if (!CONFIG.SHADOWDARK.ABILITY_KEYS.includes(stat.toLowerCase())) return; + if (CONFIG.SHADOWDARK.ABILITY_KEYS.includes(stat.toLowerCase())) { + stat = stat.toLowerCase(); + } + else { + return; + } // create replacement html const link = document.createElement("a"); From 27b2a7cfe5ece18c61ac5ac6c161c0f485f9b159 Mon Sep 17 00:00:00 2001 From: Prototype Date: Wed, 13 Nov 2024 22:42:40 -0800 Subject: [PATCH 6/7] Fully working --- i18n/en.yaml | 8 ++++ scss/shadowdark.scss | 8 ++++ system/src/apps/RequestCheckSD.mjs | 59 +++++++++++++++++++++++++ system/src/apps/_module.mjs | 1 + system/templates/apps/request-check.hbs | 32 ++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 system/src/apps/RequestCheckSD.mjs create mode 100644 system/templates/apps/request-check.hbs diff --git a/i18n/en.yaml b/i18n/en.yaml index 8f73f4c7..b724ded2 100644 --- a/i18n/en.yaml +++ b/i18n/en.yaml @@ -103,6 +103,14 @@ SHADOWDARK.apps.monster-importer.instruction2d: Main stat block SHADOWDARK.apps.monster-importer.instruction2e: Feature SHADOWDARK.apps.monster-importer.instruction3: 3. Click Import Monster. SHADOWDARK.apps.monster-importer.title: Import Monster +SHADOWDARK.apps.request-check.copied: Copied to Clipboard +SHADOWDARK.apps.request-check.copy_to_clipboard: Copy to Clipboard +SHADOWDARK.apps.request-check.custom: Custom +SHADOWDARK.apps.request-check.easy: Easy +SHADOWDARK.apps.request-check.hard: Hard +SHADOWDARK.apps.request-check.extreme: Extreme +SHADOWDARK.apps.request-check.normal: Normal +SHADOWDARK.apps.request-check.title: Request Check SHADOWDARK.apps.shadowdarkling-importer.errors: Items Not Found SHADOWDARK.apps.shadowdarkling-importer.header: Shadowdarkling Importer SHADOWDARK.apps.shadowdarkling-importer.import_button: Import diff --git a/scss/shadowdark.scss b/scss/shadowdark.scss index 752f9d9f..37219d9d 100644 --- a/scss/shadowdark.scss +++ b/scss/shadowdark.scss @@ -20,6 +20,10 @@ width: 100%; } + input[type=radio] { + width: auto; + } + hr { border: none; border-top: solid 1px #{$primary-color}; @@ -79,4 +83,8 @@ } } + .checkbox { + font-size:14px; + }; + } diff --git a/system/src/apps/RequestCheckSD.mjs b/system/src/apps/RequestCheckSD.mjs new file mode 100644 index 00000000..b32e93af --- /dev/null +++ b/system/src/apps/RequestCheckSD.mjs @@ -0,0 +1,59 @@ +export default class RequestCheckSD extends FormApplication { + + static get defaultOptions() { + return foundry.utils.mergeObject(super.defaultOptions, { + classes: ["shadowdark"], + template: "systems/shadowdark/templates/apps/request-check.hbs", + width: 400, + title: game.i18n.localize("SHADOWDARK.apps.request-check.title"), + closeOnSubmit: false, + }); + } + + activateListeners(html) { + super.activateListeners(html); + + html.find(".custom-dc").click( + event => { + $(event.target).siblings()[0].checked=true; + } + ); + } + + /** @override */ + async getData() { + return { + stats: CONFIG.SHADOWDARK.ABILITIES_LONG, + difficulty: { + 9: `9 (${game.i18n.localize("SHADOWDARK.apps.request-check.easy")})`, + 12: `12 (${game.i18n.localize("SHADOWDARK.apps.request-check.normal")})`, + 15: `15 (${game.i18n.localize("SHADOWDARK.apps.request-check.hard")})`, + 18: `18 (${game.i18n.localize("SHADOWDARK.apps.request-check.extreme")})`, + }, + }; + } + + /** @inheritdoc */ + async _updateObject(event, data) { + + if (data.custom) { + data.difficulty = data.custom; + } + data.difficulty = parseInt(data.difficulty); + + switch (event.submitter.name) { + case "request-copy": + let linkText = `[[request ${data.difficulty} ${data.stat}]]`; + await navigator.clipboard.writeText(linkText); + ui.notifications.info(game.i18n.localize("SHADOWDARK.apps.request-check.copied")); + break; + case "request-check": + shadowdark.checks.displayRequest(data.difficulty, data.stat); + this.close(); + break; + default: + shadowdark.log("Request Check Error"); + } + } + +} diff --git a/system/src/apps/_module.mjs b/system/src/apps/_module.mjs index d474c5c6..ee8f4533 100644 --- a/system/src/apps/_module.mjs +++ b/system/src/apps/_module.mjs @@ -8,6 +8,7 @@ export {default as LightSourceTrackerSD} from "./LightSourceTrackerSD.mjs"; export {default as LoadingSD} from "./LoadingSD.mjs"; export {default as MonsterImporterSD} from "./MonsterImporterSD.mjs"; export {default as NpcAttackRangesSD} from "./NpcAttackRangesSD.mjs"; +export {default as RequestCheckSD} from "./RequestCheckSD.mjs"; export {default as ShadowdarklingImporterSD} from "./ShadowdarklingImporterSD.mjs"; export {default as SpellBookSD} from "./SpellBookSD.mjs"; export {default as SpellImporterSD} from "./SpellImporterSD.mjs"; diff --git a/system/templates/apps/request-check.hbs b/system/templates/apps/request-check.hbs new file mode 100644 index 00000000..8a2816f9 --- /dev/null +++ b/system/templates/apps/request-check.hbs @@ -0,0 +1,32 @@ +
+
+ {{#> ui/sd-box + header-label="Difficulty" + }} +
+ {{radioBoxes "difficulty" difficulty checked="12"}} +
+ +
+ {{/ui/sd-box}} + + {{#> ui/sd-box + header-label="Stat" + }} +
+ {{radioBoxes "stat" stats checked="str"}} +
+ {{/ui/sd-box}} + +
+ + + +
+
From abe904e88750c5a52b19ec0c73f52f25fa56b637 Mon Sep 17 00:00:00 2001 From: Prototype Date: Wed, 13 Nov 2024 22:54:36 -0800 Subject: [PATCH 7/7] Added a launch macro --- data/macros/request-a-check.js | 6 ++++++ .../macros.db/request_a_check__YOZcP9WGwie1dLIu.json | 11 +++++++++++ 2 files changed, 17 insertions(+) create mode 100644 data/macros/request-a-check.js create mode 100644 data/packs/macros.db/request_a_check__YOZcP9WGwie1dLIu.json diff --git a/data/macros/request-a-check.js b/data/macros/request-a-check.js new file mode 100644 index 00000000..f930ba26 --- /dev/null +++ b/data/macros/request-a-check.js @@ -0,0 +1,6 @@ +/** + ************************************************ + * This macro opens the request check dialog box + ************************************************/ + +new shadowdark.apps.RequestCheckSD().render(true); diff --git a/data/packs/macros.db/request_a_check__YOZcP9WGwie1dLIu.json b/data/packs/macros.db/request_a_check__YOZcP9WGwie1dLIu.json new file mode 100644 index 00000000..fb8efc00 --- /dev/null +++ b/data/packs/macros.db/request_a_check__YOZcP9WGwie1dLIu.json @@ -0,0 +1,11 @@ +{ + "_id": "YOZcP9WGwie1dLIu", + "_key": "!macros!YOZcP9WGwie1dLIu", + "author": "XOge3YaW9qcUJnuq", + "command": "/**\n ************************************************\n * This macro opens the request check dialog box\n ************************************************/\n\nnew shadowdark.apps.RequestCheckSD().render(true);", + "folder": null, + "img": "icons/sundries/gaming/dice-runed-brown.webp", + "name": "Request a Check", + "scope": "global", + "type": "script" +}