From 845328634496b5a487796b72849e0af569225df1 Mon Sep 17 00:00:00 2001 From: Chris Seieroe Date: Thu, 27 Jan 2022 02:21:38 -0800 Subject: [PATCH] resolves #3 New conditional message feature (#12) * add roll dialog template * add message check to the reminders * move message checks into their own classes instead of including them in the advantage reminder classes * add unit test for AttackMessage * show multiple messages instead of just one * remove sorting Sorting the effects by priority was an attempt to repurpose that to just show one message. Probably not a good idea to change what priority was meant for, which was for how to apply multiple effects on the same thing. Also not as necessary since showing them all anyways. * await the addMessage method Fixes the unit tests and changed it into the module code as well to make sure we wait for setting up the dialog hook before proceeding. It worked fine without it but better to be safe * add test for two messages and check that the hook was setup * add test cases for AbilityCheckMessage * add unit tests for AbilitySaveMessage * add unit tests for SkillMessage * add unit tests for DeathSaveMessage * add DamageMessage implementation and tests * add sorting back * remove roll dialog replacement template Was going to use this to completely replace the core dialog but went with adding to the existing one instead. Don't need this anymore * flip priority around to match the order Foundry applies active effect changes * small CSS tweaks Some changes inspired by #9. Increases the padding by 2px to get close to what it had. I still think the smaller sides is better. Increased the margin to 8px. While not as large, it's the size of the padding of the dialog box (window-content class) * use dialogOptions.id to get the message on the right roll dialog * add nested options in for Damage message * update readme and changelog * fix readme type in MRE section * add links to issues in changelog just a convenience * add MRE compatibility with damage rolls MRE configures it's damage wrapper with libWrapper as MIXED. That means it always runs after WRAPPED methods like this module uses. If we are using MRE, always process it so we can pass critical and messages down to MRE and then it can decide what to do with them. --- CHANGELOG.md | 17 +- README.md | 47 +- css/adv-reminder.css | 13 + screenshot2.png | Bin 0 -> 77706 bytes src/messages.js | 159 +++++ src/module.js | 62 +- templates/roll-dialog-messages.hbs | 5 + test/messages.test.js | 911 +++++++++++++++++++++++++++++ 8 files changed, 1188 insertions(+), 26 deletions(-) create mode 100644 screenshot2.png create mode 100644 src/messages.js create mode 100644 templates/roll-dialog-messages.hbs create mode 100644 test/messages.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index acce0a9..f40e273 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,17 +1,22 @@ +# 1.0 + +- feature: [#3](https://github.com/kaelad02/adv-reminder/issues/3) Messages that show up on the roll dialogs +- feature: improve MRE compatibility to skip when it fast-forwards rolls + # 0.4 -* feature: support armor that imposes stealth disadvantage +- feature: [#7](https://github.com/kaelad02/adv-reminder/issues/7) support armor that imposes stealth disadvantage # 0.3 -* bug fix: Active effects from unequipped items weren't being ignored -* documentation: Update readme with module compatibility info +- bug fix: [#2](https://github.com/kaelad02/adv-reminder/issues/2) Active effects from unequipped items weren't being ignored +- documentation: Update readme with module compatibility info # 0.2 -* feature: add Tool checks support -* mark compatible with v9 +- feature: add Tool checks support +- mark compatible with v9 # 0.1 -* Initial release +- Initial release diff --git a/README.md b/README.md index e811073..cddd4b7 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,13 @@ In addition to the active effects, this module supports armor that imposes steal Supports active effects on the following rolls: -* Attack rolls -* Ability checks -* Saving throws, including auto-fail (e.g. Stunned) -* Skill checks -* Tool checks -* Death saves -* Damage rolls +- Attack rolls +- Ability checks +- Saving throws, including auto-fail (e.g. Stunned) +- Skill checks +- Tool checks +- Death saves +- Damage rolls ## Auto-Fail Rolls @@ -26,6 +26,31 @@ There are active effect keys for automatically failing ability checks, saving th If the player holds down one of the Ctrl/Alt/Shift/Meta keys to fast-forward the die roll (e.g. hold Alt to roll with advantage, skipping the roll dialog) then this module WILL NOT do anything. Holding down one of those keys stops the roll dialog from popping up so it's interpreted as overriding what this module does. +## Messages + +In addition to active effects adding advantage or disadvantage, you can also add messages to remind you of conditional bonuses or advantage. For example, features like Dwarven Resilience give advantage on saving throws against poison don't work with the advantage flags since there isn't a way to limit it to poison. Now you can add a message to the dialog right above the buttons to remind you about Dwarven Resilience. + +![Saving Throw screenshot with message](screenshot2.png?raw=true) + +You have control over when the message appears and what it contains, including HTML formatting. In the screenshot above it just reminds you to roll with advantage on saving throws against poison. You are free to change it to just include `Dwarven Resilience` if that's all the reminder you need or `Advantage against poison` that doesn't mention saving throws since it only appears on CON saving throws. + +The active effects keys are listed below and should be set with the change mode of `Custom`. + +- `flags.adv-reminder.message.all` for all rolls +- `flags.adv-reminder.message.attack.all` for all Attack rolls +- `flags.adv-reminder.message.attack.mwak/rwak/msak/rsak` for Attack rolls of a specific action type +- `flags.adv-reminder.message.attack.str/dex/con/int/wis/cha` for Attack rolls using a specific ability +- `flags.adv-reminder.message.ability.all` for all Ability checks, Saving throws, Skill checks, and Death saves +- `flags.adv-reminder.message.ability.check.all` for all Ability checks and Skill checks +- `flags.adv-reminder.message.ability.check.str/dex/con/int/wis/cha` for specific Ability checks and Skill checks +- `flags.adv-reminder.message.ability.save.all` for all Saving throws and Death saves +- `flags.adv-reminder.message.ability.save.str/dex/con/int/wis/cha` for specific Saving throws +- `flags.adv-reminder.message.skill.all` for all Skill checks +- `flags.adv-reminder.message.skill.acr/ath/.../sur` for specific Skill checks +- `flags.adv-reminder.message.deathSave` for Death saves +- `flags.adv-reminder.message.damage.all` for all Damage rolls +- `flags.adv-reminder.message.damage.mwak/rwak/msak/rsak` for Damage rolls of a specific action type + ## Other Modules Notes about other modules. @@ -44,9 +69,11 @@ Notes about other modules. ### Compatibility Notes -[Better Rolls for 5e](https://foundryvtt.com/packages/betterrolls5e) This module works with Better Rolls, making rolls with advantage and disadvantage with some caviats. +[Better Rolls for 5e](https://foundryvtt.com/packages/betterrolls5e) This module works with Better Rolls, making rolls with advantage and disadvantage with the following known issue(s). -* Active effects for critical hits do not work. -* The "d20 Mode" Better Rolls setting of "Single Roll Upgradeable" does not give the hint in the pop-up asking what kind of roll to perform. It will still apply the active effects though possibly leading to some confusion, especially since advantage and disadvantage will not cancel each other out like they should. +- Active effects for critical hits do not work. +- The "d20 Mode" Better Rolls setting of "Single Roll Upgradeable" does not give the hint in the pop-up asking what kind of roll to perform. It will still apply the active effects though possibly leading to some confusion, especially since advantage and disadvantage will not cancel each other out like they should. [Midi QOL](https://foundryvtt.com/packages/midi-qol) This module is compatible with Midi QOL. However, if you've enabled Midi QOL's workflow then it is not necessary to use this module as well since Midi QOL will already do this for you. + +[Minimal Rolling Enhancements for D&D5e](https://foundryvtt.com/packages/mre-dnd5e) This module works with MRE, making rolls with advantage/disadvantage and showing messages if you hold the "Roll Dialog Modifier Key" (an MRE setting). diff --git a/css/adv-reminder.css b/css/adv-reminder.css index 19330fc..96aa2fb 100644 --- a/css/adv-reminder.css +++ b/css/adv-reminder.css @@ -9,3 +9,16 @@ .dialog .dialog-buttons button.default.critical { font-weight: bold; } + +.dialog .dialog-content .adv-reminder-messages { + background: rgba(0, 0, 0, 0.05); + padding: 3px 5px; + margin: 8px 0; + color: #191813; + border: 1px solid #7a7971; + border-radius: 3px; +} + +.adv-reminder-messages > div:not(:last-child) { + margin-bottom: 10px; +} diff --git a/screenshot2.png b/screenshot2.png new file mode 100644 index 0000000000000000000000000000000000000000..12e7f5404fbea192bceb623fa27df21d39c37fab GIT binary patch literal 77706 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 !effect.isSuppressed && !effect.data.disabled) + .flatMap((effect) => effect.data.changes) + .sort((a, b) => a.priority - b.priority); + } + + get messageKeys() { + return ["flags.adv-reminder.message.all"]; + } + + async addMessage(options) { + const keys = this.messageKeys; + const messages = this.changes + .filter((change) => keys.includes(change.key)) + .map((change) => change.value); + + if (messages.length > 0) { + // add id to dialogOptions to put the message on the correct roll dialog + const messageId = randomID(); + options.dialogOptions = options.dialogOptions || {}; + options.dialogOptions.id = messageId; + // build message + const message = await renderTemplate( + "modules/adv-reminder/templates/roll-dialog-messages.hbs", + { messages } + ); + debug("adding hook to renderDialog w/ ", message); + const hookId = Hooks.on("renderDialog", (dialog, html, data) => { + debug("called on hook for renderDialog"); + if (dialog.options.id !== messageId) return; + // add message at the end + const formGroups = html.find(".form-group:last"); + formGroups.after(message); + // reset dialog height + const position = dialog.position; + position.height = "auto"; + dialog.setPosition(position); + }); + setTimeout(() => { + Hooks.off("renderDialog", hookId); + }, 10_000); + } + + return messages; + } +} + +export class AttackMessage extends BaseMessage { + constructor(actor, item) { + super(actor); + + /** @type {string} */ + this.actionType = item.data.data.actionType; + /** @type {string} */ + this.abilityId = item.abilityMod; + } + + /** @override */ + get messageKeys() { + return super.messageKeys.concat( + "flags.adv-reminder.message.attack.all", + `flags.adv-reminder.message.attack.${this.actionType}`, + `flags.adv-reminder.message.attack.${this.abilityId}` + ); + } +} + +class AbilityBaseMessage extends BaseMessage { + constructor(actor, abilityId) { + super(actor); + + /** @type {string} */ + this.abilityId = abilityId; + } + + /** @override */ + get messageKeys() { + return super.messageKeys.concat("flags.adv-reminder.message.ability.all"); + } +} + +export class AbilityCheckMessage extends AbilityBaseMessage { + /** @override */ + get messageKeys() { + return super.messageKeys.concat( + "flags.adv-reminder.message.ability.check.all", + `flags.adv-reminder.message.ability.check.${this.abilityId}` + ); + } +} + +export class AbilitySaveMessage extends AbilityBaseMessage { + /** @override */ + get messageKeys() { + return super.messageKeys.concat( + "flags.adv-reminder.message.ability.save.all", + `flags.adv-reminder.message.ability.save.${this.abilityId}` + ); + } +} + +export class SkillMessage extends AbilityCheckMessage { + constructor(actor, skillId) { + super(actor, actor.data.data.skills[skillId].ability); + + /** @type {string} */ + this.skillId = skillId; + } + + /** @override */ + get messageKeys() { + return super.messageKeys.concat( + "flags.adv-reminder.message.skill.all", + `flags.adv-reminder.message.skill.${this.skillId}` + ); + } +} + +export class DeathSaveMessage extends AbilityBaseMessage { + constructor(actor) { + super(actor, null); + } + + /** @override */ + get messageKeys() { + return super.messageKeys.concat( + "flags.adv-reminder.message.ability.save.all", + "flags.adv-reminder.message.deathSave" + ); + } +} + +export class DamageMessage extends BaseMessage { + constructor(actor, item) { + super(actor); + + /** @type {string} */ + this.actionType = item.data.data.actionType; + } + + /** @override */ + get messageKeys() { + return super.messageKeys.concat( + "flags.adv-reminder.message.damage.all", + `flags.adv-reminder.message.damage.${this.actionType}` + ); + } + + async addMessage(options) { + // Damage options has a nested options variable, add that and pass it to super + options.options = options.options || {}; + return super.addMessage(options.options); + } +} diff --git a/src/module.js b/src/module.js index 77bcb1d..f0622a0 100644 --- a/src/module.js +++ b/src/module.js @@ -1,4 +1,12 @@ import { AbilitySaveFail } from "./fails.js"; +import { + AbilityCheckMessage, + AbilitySaveMessage, + AttackMessage, + DamageMessage, + DeathSaveMessage, + SkillMessage, +} from "./messages.js"; import { AttackReminder, AbilityCheckReminder, @@ -72,7 +80,7 @@ Hooks.once("init", () => { ); }); -function onRollAttack(wrapped, options) { +async function onRollAttack(wrapped, options) { debug("onRollAttack method called"); // check for adv/dis flags unless the user pressed a fast-forward key @@ -80,6 +88,8 @@ function onRollAttack(wrapped, options) { if (isFF) { debug("held down a fast-foward key, skip checking for adv/dis"); } else { + debug("checking for message effects on this attack roll"); + await new AttackMessage(this.actor, this).addMessage(options); debug("checking for adv/dis effects on this attack roll"); const reminder = new AttackReminder(this.actor, getTarget(), this); reminder.updateOptions(options); @@ -88,7 +98,7 @@ function onRollAttack(wrapped, options) { return wrapped(options); } -function onRollAbilitySave(wrapped, abilityId, options) { +async function onRollAbilitySave(wrapped, abilityId, options) { debug("onRollAbilitySave method called"); // check if an effect says to fail this roll @@ -102,6 +112,8 @@ function onRollAbilitySave(wrapped, abilityId, options) { if (isFF) { debug("held down a fast-foward key, skip checking for adv/dis"); } else { + debug("checking for message effects on this saving throw"); + await new AbilitySaveMessage(this, abilityId).addMessage(options); debug("checking for adv/dis effects on this saving throw"); const reminder = new AbilitySaveReminder(this, abilityId); reminder.updateOptions(options); @@ -110,7 +122,7 @@ function onRollAbilitySave(wrapped, abilityId, options) { return wrapped(abilityId, options); } -function onRollAbilityTest(wrapped, abilityId, options) { +async function onRollAbilityTest(wrapped, abilityId, options) { debug("onRollAbilityTest method called"); // check for adv/dis flags unless the user pressed a fast-forward key @@ -118,6 +130,8 @@ function onRollAbilityTest(wrapped, abilityId, options) { if (isFF) { debug("held down a fast-foward key, skip checking for adv/dis"); } else { + debug("checking for message effects on this ability check"); + await new AbilityCheckMessage(this, abilityId).addMessage(options); debug("checking for adv/dis effects on this ability check"); const reminder = new AbilityCheckReminder(this, abilityId); reminder.updateOptions(options); @@ -126,7 +140,7 @@ function onRollAbilityTest(wrapped, abilityId, options) { return wrapped(abilityId, options); } -function onRollSkill(wrapped, skillId, options) { +async function onRollSkill(wrapped, skillId, options) { debug("onRollSkill method called"); // check for adv/dis flags unless the user pressed a fast-forward key @@ -134,6 +148,8 @@ function onRollSkill(wrapped, skillId, options) { if (isFF) { debug("held down a fast-foward key, skip checking for adv/dis"); } else { + debug("checking for message effects on this skill check"); + await new SkillMessage(this, skillId).addMessage(options); debug("checking for adv/dis effects on this skill check"); const reminder = new SkillReminder(this, skillId); reminder.updateOptions(options); @@ -142,7 +158,7 @@ function onRollSkill(wrapped, skillId, options) { return wrapped(skillId, options); } -function onRollToolCheck(wrapped, options) { +async function onRollToolCheck(wrapped, options) { debug("onRollToolCheck method called"); // check for adv/dis flags unless the user pressed a fast-forward key @@ -150,6 +166,11 @@ function onRollToolCheck(wrapped, options) { if (isFF) { debug("held down a fast-foward key, skip checking for adv/dis"); } else { + debug("checking for message effects on this tool check"); + await new AbilityCheckMessage( + this.actor, + this.data.data.ability + ).addMessage(options); debug("checking for adv/dis effects on this tool check"); const reminder = new AbilityCheckReminder( this.actor, @@ -161,7 +182,7 @@ function onRollToolCheck(wrapped, options) { return wrapped(options); } -function onRollDeathSave(wrapped, options) { +async function onRollDeathSave(wrapped, options) { debug("onRollDeathSave method called"); // check for adv/dis flags unless the user pressed a fast-forward key @@ -169,6 +190,8 @@ function onRollDeathSave(wrapped, options) { if (isFF) { debug("held down a fast-foward key, skip checking for adv/dis"); } else { + debug("checking for message effects on this death save"); + await new DeathSaveMessage(this).addMessage(options); debug("checking for adv/dis effects on this death save"); const reminder = new DeathSaveReminder(this); reminder.updateOptions(options); @@ -177,14 +200,16 @@ function onRollDeathSave(wrapped, options) { return wrapped(options); } -function onRollDamage(wrapped, options) { +async function onRollDamage(wrapped, options) { debug("onRollDamage method called"); // check for critical flags unless the user pressed a fast-forward key - const isFF = isFastForwarding(options); + const isFF = isFastForwardingDamage(options.event); if (isFF) { debug("held down a fast-foward key, skip checking for adv/dis"); } else { + debug("checking for message effects on this damage roll"); + await new DamageMessage(this.actor, this).addMessage(options); debug("checking for critical/normal effects on this damage roll"); const reminder = new CriticalReminder(this.actor, getTarget(), this); reminder.updateOptions(options); @@ -195,11 +220,28 @@ function onRollDamage(wrapped, options) { /** * Check if the user is holding down a fast-forward key. - * @param {Event} event the event + * @param {object} options the options * @returns {Boolean} true if they are fast-forwarding, false otherwise */ function isFastForwarding(options) { - return !!(options.fastForward || options.event?.shiftKey || options.event?.altKey || options.event?.ctrlKey || options.event?.metaKey); + return !!( + options.fastForward || + options.event?.shiftKey || + options.event?.altKey || + options.event?.ctrlKey || + options.event?.metaKey + ); +} + +/** + * Check if the user is holding down a fast-forward key for a damage roll. + * @param {Event} event the event + * @returns {Boolean} true if they are fast-forwarding, false otherwise + */ +function isFastForwardingDamage(event) { + // special handling for MRE and damage rolls, always process since it will run after this module + if (game.modules.get("mre-dnd5e")?.active) return false; + return event?.shiftKey || event?.altKey || event?.ctrlKey || event?.metaKey; } /** diff --git a/templates/roll-dialog-messages.hbs b/templates/roll-dialog-messages.hbs new file mode 100644 index 0000000..714af89 --- /dev/null +++ b/templates/roll-dialog-messages.hbs @@ -0,0 +1,5 @@ +
+ {{#each messages}} +
{{{this}}}
+ {{/each}} +
diff --git a/test/messages.test.js b/test/messages.test.js new file mode 100644 index 0000000..4c4c9f2 --- /dev/null +++ b/test/messages.test.js @@ -0,0 +1,911 @@ +import { beforeEach, describe, expect, jest, test } from "@jest/globals"; +import { + AbilityCheckMessage, + AbilitySaveMessage, + AttackMessage, + DamageMessage, + DeathSaveMessage, + SkillMessage, +} from "../src/messages"; + +// fakes +globalThis.renderTemplate = () => {}; +globalThis.randomID = () => ""; +globalThis.Hooks = {}; +globalThis.Hooks.on = () => ""; +globalThis.Hooks.off = () => {}; + +function createActorWithEffects(...keyValuePairs) { + const effects = keyValuePairs.map(createEffect); + return { + data: { + data: { + skills: { + acr: { + ability: "dex", + }, + ani: { + ability: "wis", + }, + arc: { + ability: "int", + }, + ath: { + ability: "str", + }, + dec: { + ability: "cha", + }, + his: { + ability: "int", + }, + ins: { + ability: "wis", + }, + itm: { + ability: "cha", + }, + inv: { + ability: "int", + }, + med: { + ability: "wis", + }, + nat: { + ability: "int", + }, + prc: { + ability: "wis", + }, + prf: { + ability: "cha", + }, + per: { + ability: "cha", + }, + rel: { + ability: "int", + }, + slt: { + ability: "dex", + }, + ste: { + ability: "dex", + }, + sur: { + ability: "wis", + }, + }, + }, + }, + effects, + }; +} + +function createEffect([key, value]) { + return { + isSuppressed: false, + data: { + changes: [ + { + key, + value, + mode: 0, + priority: "0", + }, + ], + disabled: false, + }, + }; +} + +function createItem(actionType, abilityMod) { + return { + abilityMod, + data: { + data: { + actionType, + }, + }, + }; +} + +describe("AttackMessage no legit active effects", () => { + test("attack with no active effects should not add a message", async () => { + const actor = createActorWithEffects(); + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new AttackMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("attack with a suppressed active effect should not add a message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "some message", + ]); + actor.effects[0].isSuppressed = true; + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new AttackMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("attack with a disabled active effect should not add a message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "some message", + ]); + actor.effects[0].data.disabled = true; + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new AttackMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); +}); + +describe("AttackMessage message flags", () => { + test("attack with message.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "message.all message", + ]); + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new AttackMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual(["message.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("attack with message.attack.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.attack.all", + "message.attack.all message", + ]); + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new AttackMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual(["message.attack.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("attack with message.attack.mwak flag should add the message for Melee Weapon Attack", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.attack.mwak", + "message.attack.mwak message", + ]); + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new AttackMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual(["message.attack.mwak message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("attack with message.attack.mwak flag should not add the message for Ranged Weapon Attack", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.attack.mwak", + "message.attack.mwak message", + ]); + const item = createItem("rwak", "dex"); + const options = {}; + + const messages = await new AttackMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("attack with message.attack.cha flag should add the message for Charisma Attack", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.attack.cha", + "message.attack.cha message", + ]); + const item = createItem("rsak", "cha"); + const options = {}; + + const messages = await new AttackMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual(["message.attack.cha message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("attack with message.attack.cha flag should not add the message for Intelligence Attack", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.attack.cha", + "message.attack.cha", + ]); + const item = createItem("rsak", "int"); + const options = {}; + + const messages = await new AttackMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("attack with two messages should add both messages", async () => { + const actor = createActorWithEffects( + ["flags.adv-reminder.message.attack.all", "first"], + ["flags.adv-reminder.message.attack.mwak", "second"] + ); + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new AttackMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual(["first", "second"]); + expect(options.dialogOptions?.id).toBe(""); + }); +}); + +describe("AbilityCheckMessage no legit active effects", () => { + test("ability check with no active effects should not add a message", async () => { + const actor = createActorWithEffects(); + const options = {}; + + const messages = await new AbilityCheckMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("ability check with a suppressed active effect should not add a message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "some message", + ]); + actor.effects[0].isSuppressed = true; + const options = {}; + + const messages = await new AbilityCheckMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("ability check with a disabled active effect should not add a message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "some message", + ]); + actor.effects[0].data.disabled = true; + const options = {}; + + const messages = await new AbilityCheckMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); +}); + +describe("AbilityCheckMessage message flags", () => { + test("ability check with message.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "message.all message", + ]); + const options = {}; + + const messages = await new AbilityCheckMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual(["message.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("ability check with message.ability.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.all", + "message.ability.all message", + ]); + const options = {}; + + const messages = await new AbilityCheckMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual(["message.ability.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("ability check with message.ability.check.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.check.all", + "message.ability.check.all message", + ]); + const options = {}; + + const messages = await new AbilityCheckMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual(["message.ability.check.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("ability check with message.ability.check.int flag should add the message for Intelligence Check", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.check.int", + "message.ability.check.int message", + ]); + const options = {}; + + const messages = await new AbilityCheckMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual(["message.ability.check.int message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("ability check with message.ability.check.int flag should not add the message for Dexterity Check", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.check.int", + "message.ability.check.int", + ]); + const options = {}; + + const messages = await new AbilityCheckMessage(actor, "dex").addMessage( + options + ); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("ability check with two messages should add both messages", async () => { + const actor = createActorWithEffects( + ["flags.adv-reminder.message.ability.check.all", "first"], + ["flags.adv-reminder.message.ability.check.dex", "second"] + ); + const options = {}; + + const messages = await new AbilityCheckMessage(actor, "dex").addMessage( + options + ); + + expect(messages).toStrictEqual(["first", "second"]); + expect(options.dialogOptions?.id).toBe(""); + }); +}); + +describe("AbilitySaveMessage no legit active effects", () => { + test("saving throw with no active effects should not add a message", async () => { + const actor = createActorWithEffects(); + const options = {}; + + const messages = await new AbilitySaveMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("saving throw with a suppressed active effect should not add a message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "some message", + ]); + actor.effects[0].isSuppressed = true; + const options = {}; + + const messages = await new AbilitySaveMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("saving throw with a disabled active effect should not add a message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "some message", + ]); + actor.effects[0].data.disabled = true; + const options = {}; + + const messages = await new AbilitySaveMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); +}); + +describe("AbilitySaveMessage message flags", () => { + test("saving throw with message.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "message.all message", + ]); + const options = {}; + + const messages = await new AbilitySaveMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual(["message.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("saving throw with message.ability.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.all", + "message.ability.all message", + ]); + const options = {}; + + const messages = await new AbilitySaveMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual(["message.ability.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("saving throw with message.ability.save.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.save.all", + "message.ability.save.all message", + ]); + const options = {}; + + const messages = await new AbilitySaveMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual(["message.ability.save.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("saving throw with message.ability.save.int flag should add the message for Intelligence Check", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.save.int", + "message.ability.save.int message", + ]); + const options = {}; + + const messages = await new AbilitySaveMessage(actor, "int").addMessage( + options + ); + + expect(messages).toStrictEqual(["message.ability.save.int message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("saving throw with message.ability.save.int flag should not add the message for Dexterity Check", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.save.int", + "message.ability.save.int", + ]); + const options = {}; + + const messages = await new AbilitySaveMessage(actor, "dex").addMessage( + options + ); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("saving throw with two messages should add both messages", async () => { + const actor = createActorWithEffects( + ["flags.adv-reminder.message.ability.save.all", "first"], + ["flags.adv-reminder.message.ability.save.dex", "second"] + ); + const options = {}; + + const messages = await new AbilitySaveMessage(actor, "dex").addMessage( + options + ); + + expect(messages).toStrictEqual(["first", "second"]); + expect(options.dialogOptions?.id).toBe(""); + }); +}); + +describe("SkillMessage no legit active effects", () => { + test("skill check with no active effects should not add a message", async () => { + const actor = createActorWithEffects(); + const options = {}; + + const messages = await new SkillMessage(actor, "ath").addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("skill check with a suppressed active effect should not add a message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "some message", + ]); + actor.effects[0].isSuppressed = true; + const options = {}; + + const messages = await new SkillMessage(actor, "ath").addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("skill check with a disabled active effect should not add a message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "some message", + ]); + actor.effects[0].data.disabled = true; + const options = {}; + + const messages = await new SkillMessage(actor, "ath").addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); +}); + +describe("SkillMessage message flags", () => { + test("skill check with message.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "message.all message", + ]); + const options = {}; + + const messages = await new SkillMessage(actor, "prc").addMessage(options); + + expect(messages).toStrictEqual(["message.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("skill check with message.ability.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.all", + "message.ability.all message", + ]); + const options = {}; + + const messages = await new SkillMessage(actor, "prc").addMessage(options); + + expect(messages).toStrictEqual(["message.ability.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("skill check with message.ability.check.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.check.all", + "message.ability.check.all message", + ]); + const options = {}; + + const messages = await new SkillMessage(actor, "prc").addMessage(options); + + expect(messages).toStrictEqual(["message.ability.check.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("skill check with message.ability.check.wis flag should add the message for Perception Check", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.check.wis", + "message.ability.check.int message", + ]); + const options = {}; + + const messages = await new SkillMessage(actor, "prc").addMessage(options); + + expect(messages).toStrictEqual(["message.ability.check.int message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("skill check with message.ability.check.wis flag should not add the message for Acrobatics Check", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.check.wis", + "message.ability.check.int", + ]); + const options = {}; + + const messages = await new SkillMessage(actor, "acr").addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("skill check with message.skill.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.skill.all", + "message.skill.all message", + ]); + const options = {}; + + const messages = await new SkillMessage(actor, "prc").addMessage(options); + + expect(messages).toStrictEqual(["message.skill.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("skill check with message.skill.prc flag should add the message for Perception Check", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.skill.prc", + "message.skill.prc message", + ]); + const options = {}; + + const messages = await new SkillMessage(actor, "prc").addMessage(options); + + expect(messages).toStrictEqual(["message.skill.prc message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("skill check with message.skill.prc flag should not add the message for Nature Check", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.skill.prc", + "message.skill.prc message", + ]); + const options = {}; + + const messages = await new SkillMessage(actor, "nat").addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("skill check with two messages should add both messages", async () => { + const actor = createActorWithEffects( + ["flags.adv-reminder.message.ability.check.dex", "first"], + ["flags.adv-reminder.message.skill.ste", "second"] + ); + const options = {}; + + const messages = await new SkillMessage(actor, "ste").addMessage(options); + + expect(messages).toStrictEqual(["first", "second"]); + expect(options.dialogOptions?.id).toBe(""); + }); +}); + +describe("DeathSaveMessage no legit active effects", () => { + test("death save with no active effects should not add a message", async () => { + const actor = createActorWithEffects(); + const options = {}; + + const messages = await new DeathSaveMessage(actor).addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("death save with a suppressed active effect should not add a message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "some message", + ]); + actor.effects[0].isSuppressed = true; + const options = {}; + + const messages = await new DeathSaveMessage(actor).addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); + + test("death save with a disabled active effect should not add a message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "some message", + ]); + actor.effects[0].data.disabled = true; + const options = {}; + + const messages = await new DeathSaveMessage(actor).addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.dialogOptions).toBeUndefined(); + }); +}); + +describe("DeathSaveMessage message flags", () => { + test("death save with message.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "message.all message", + ]); + const options = {}; + + const messages = await new DeathSaveMessage(actor).addMessage(options); + + expect(messages).toStrictEqual(["message.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("death save with message.ability.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.all", + "message.ability.all message", + ]); + const options = {}; + + const messages = await new DeathSaveMessage(actor).addMessage(options); + + expect(messages).toStrictEqual(["message.ability.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("death save with message.ability.save.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.ability.save.all", + "message.ability.save.all message", + ]); + const options = {}; + + const messages = await new DeathSaveMessage(actor).addMessage(options); + + expect(messages).toStrictEqual(["message.ability.save.all message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("death save with message.deathSave flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.deathSave", + "message.deathSave message", + ]); + const options = {}; + + const messages = await new DeathSaveMessage(actor).addMessage(options); + + expect(messages).toStrictEqual(["message.deathSave message"]); + expect(options.dialogOptions?.id).toBe(""); + }); + + test("death save with two messages should add both messages", async () => { + const actor = createActorWithEffects( + ["flags.adv-reminder.message.ability.save.all", "first"], + ["flags.adv-reminder.message.deathSave", "second"] + ); + const options = {}; + + const messages = await new DeathSaveMessage(actor).addMessage(options); + + expect(messages).toStrictEqual(["first", "second"]); + expect(options.dialogOptions?.id).toBe(""); + }); +}); + +describe("DamageMessage no legit active effects", () => { + test("damage with no active effects should not add a message", async () => { + const actor = createActorWithEffects(); + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new DamageMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.options?.dialogOptions).toBeUndefined(); + }); + + test("damage with a suppressed active effect should not add a message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "some message", + ]); + actor.effects[0].isSuppressed = true; + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new DamageMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.options?.dialogOptions).toBeUndefined(); + }); + + test("damage with a disabled active effect should not add a message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "some message", + ]); + actor.effects[0].data.disabled = true; + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new DamageMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.options?.dialogOptions).toBeUndefined(); + }); +}); + +describe("DamageMessage message flags", () => { + test("damage with message.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.all", + "message.all message", + ]); + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new DamageMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual(["message.all message"]); + expect(options.options?.dialogOptions?.id).toBe(""); + }); + + test("damage with message.damage.all flag should add the message", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.damage.all", + "message.damage.all message", + ]); + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new DamageMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual(["message.damage.all message"]); + expect(options.options?.dialogOptions?.id).toBe(""); + }); + + test("damage with message.damage.mwak flag should add the message for Melee Weapon damage", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.damage.mwak", + "message.damage.mwak message", + ]); + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new DamageMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual(["message.damage.mwak message"]); + expect(options.options?.dialogOptions?.id).toBe(""); + }); + + test("damage with message.damage.mwak flag should not add the message for Ranged Weapon damage", async () => { + const actor = createActorWithEffects([ + "flags.adv-reminder.message.damage.mwak", + "message.damage.mwak message", + ]); + const item = createItem("rwak", "dex"); + const options = {}; + + const messages = await new DamageMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual([]); + expect(options.options?.dialogOptions).toBeUndefined(); + }); + + test("damage with two messages should add both messages", async () => { + const actor = createActorWithEffects( + ["flags.adv-reminder.message.damage.all", "first"], + ["flags.adv-reminder.message.damage.mwak", "second"] + ); + const item = createItem("mwak", "str"); + const options = {}; + + const messages = await new DamageMessage(actor, item).addMessage(options); + + expect(messages).toStrictEqual(["first", "second"]); + expect(options.options?.dialogOptions?.id).toBe(""); + }); +});