Skip to content

Commit

Permalink
Update the system-defined status effects to include advantage/disadva…
Browse files Browse the repository at this point in the history
…ntage flags (#62)

* add updateStatusEffects

* add hooks to add changes to Exhaustion active effect

* add updateStatusEffects setting to control feature

* update changelog

* fix VSCode warnings about testing empty objects

* bit of cleanup
  • Loading branch information
kaelad02 authored Feb 26, 2024
1 parent 85d89e8 commit e623498
Show file tree
Hide file tree
Showing 7 changed files with 314 additions and 14 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 3.4.0

- feature: Update the system-defined status effects to include advantage/disadvantage flags. Controlled by a setting.

# 3.3.2

- bug fix: [#60](https://github.com/kaelad02/adv-reminder/issues/60) Fix tool checks to show advantage and messages again after the check was moved from the item to the actor
Expand Down
4 changes: 4 additions & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,9 @@
"Dis": "Disadvantage from {sources}",
"Crit": "Critical Hit from {sources}",
"Norm": "Normal from {sources}"
},
"adv-reminder.UpdateStatusEffects": {
"Name": "Update Status Effects",
"Hint": "Update the status effects that the system adds to include the appropriate advantage/disadvantage flags. Not recommended if you are using another module to modify or replace them."
}
}
2 changes: 1 addition & 1 deletion module.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"id": "dnd5e",
"compatibility": {
"minimum": "3.0.0",
"verified": "3.0.0"
"verified": "3.0.3"
}
},
{
Expand Down
291 changes: 282 additions & 9 deletions src/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,285 @@ function applyMidiCustom(actor, change) {
}
}

Hooks.once("setup", () => {
if (game.settings.get("adv-reminder", "updateStatusEffects")) {
updateStatusEffects();
Hooks.on("preCreateActiveEffect", addExhaustionEffects);
Hooks.on("preUpdateActiveEffect", addExhaustionEffects);
}
});

function updateStatusEffects() {
debug("updateStatusEffects");

const effectChanges = {
blinded: {
changes: [
{
key: "flags.midi-qol.disadvantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.grants.advantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
],
},
dodging: {
flags: {
dae: {
specialDuration: ["turnStart"],
},
},
changes: [
{
key: "flags.midi-qol.grants.disadvantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.advantage.ability.save.dex",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
],
},
frightened: {
changes: [
{
key: "flags.midi-qol.disadvantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.disadvantage.ability.check.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
],
},
hidden: {
changes: [
{
key: "flags.midi-qol.advantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.grants.disadvantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
],
},
invisible: {
changes: [
{
key: "flags.midi-qol.advantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.grants.disadvantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
],
},
paralyzed: {
changes: [
{
key: "flags.midi-qol.fail.ability.save.dex",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.fail.ability.save.str",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.grants.advantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.grants.critical.range",
mode: CONST.ACTIVE_EFFECT_MODES.OVERRIDE,
value: "5",
},
],
},
petrified: {
changes: [
{
key: "flags.midi-qol.grants.advantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.fail.ability.save.dex",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.fail.ability.save.str",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
],
},
poisoned: {
changes: [
{
key: "flags.midi-qol.disadvantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.disadvantage.ability.check.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
],
},
prone: {
changes: [
{
key: "flags.midi-qol.grants.advantage.attack.mwak",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.grants.advantage.attack.msak",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.grants.disadvantage.attack.rwak",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.grants.disadvantage.attack.rsak",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.disadvantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
],
},
restrained: {
changes: [
{
key: "flags.midi-qol.disadvantage.ability.save.dex",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.disadvantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.grants.advantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
],
},
stunned: {
changes: [
{
key: "flags.midi-qol.fail.ability.save.dex",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.fail.ability.save.str",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.grants.advantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
],
},
unconscious: {
changes: [
{
key: "flags.midi-qol.fail.ability.save.dex",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.fail.ability.save.str",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.grants.advantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.grants.critical.range",
mode: CONST.ACTIVE_EFFECT_MODES.OVERRIDE,
value: "5",
},
],
},
};

Object.entries(effectChanges).forEach(([id, data]) => {
const effect = CONFIG.statusEffects.find((e) => e.id === id);
if (effect) foundry.utils.mergeObject(effect, data);
});
}

function addExhaustionEffects(effect, updates) {
debug("addExhaustionEffects");

if (effect.id !== dnd5e.documents.ActiveEffect5e.ID.EXHAUSTION) return;
const level = foundry.utils.getProperty(updates, "flags.dnd5e.exhaustionLevel");
if (!level) return;
// build the changes based on exhaustion level
const changes = [
{
key: "flags.midi-qol.disadvantage.ability.check.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.dnd5e.initiativeDisadv",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
];
if (level >= 3)
changes.push(
{
key: "flags.midi-qol.disadvantage.attack.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
},
{
key: "flags.midi-qol.disadvantage.ability.save.all",
mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM,
value: "1",
}
);
// add changes to the active effect
effect.updateSource({ changes });
}

// Add message flags to DAE so it shows them in the AE editor
Hooks.once("DAE.setupComplete", () => {
debug("adding Advantage Reminder flags to DAE");
Expand All @@ -53,8 +332,7 @@ Hooks.once("DAE.setupComplete", () => {
fields.push("flags.adv-reminder.message.deathSave");
fields.push("flags.adv-reminder.message.damage.all");

const actionTypes =
game.system.id === "sw5e" ? ["mwak", "rwak", "mpak", "rpak"] : ["mwak", "rwak", "msak", "rsak"];
const actionTypes = game.system.id === "sw5e" ? ["mwak", "rwak", "mpak", "rpak"] : ["mwak", "rwak", "msak", "rsak"];
actionTypes.forEach((actionType) => fields.push(`flags.adv-reminder.message.attack.${actionType}`));

Object.keys(CONFIG.DND5E.itemActionTypes).forEach((actionType) =>
Expand All @@ -67,9 +345,7 @@ Hooks.once("DAE.setupComplete", () => {
fields.push(`flags.adv-reminder.message.ability.save.${abilityId}`);
});

Object.keys(CONFIG.DND5E.skills).forEach((skillId) =>
fields.push(`flags.adv-reminder.message.skill.${skillId}`)
);
Object.keys(CONFIG.DND5E.skills).forEach((skillId) => fields.push(`flags.adv-reminder.message.skill.${skillId}`));

window.DAE.addAutoFields(fields);
});
Expand Down Expand Up @@ -132,10 +408,7 @@ async function prepareMessage(dialogOptions) {

if (messages.length) {
// build message
const message = await renderTemplate(
"modules/adv-reminder/templates/roll-dialog-messages.hbs",
{ messages }
);
const message = await renderTemplate("modules/adv-reminder/templates/roll-dialog-messages.hbs", { messages });
// enrich message, specifically replacing rolls
const enriched = await TextEditor.enrichHTML(message, {
secrets: true,
Expand Down
8 changes: 4 additions & 4 deletions src/reminders.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { debug } from "./util.js";
import { debug, isEmpty } from "./util.js";

class BaseReminder {
constructor(actor) {
Expand Down Expand Up @@ -61,7 +61,7 @@ export class AttackReminder extends BaseReminder {
this._message();

// quick return if there are no flags
if (this.actorFlags === {} && this.targetFlags === {}) return;
if (isEmpty(this.actorFlags) && isEmpty(this.targetFlags)) return;

// build the active effect keys applicable for this roll
const advKeys = [
Expand Down Expand Up @@ -113,7 +113,7 @@ class AbilityBaseReminder extends BaseReminder {
this._message();

// quick return if there are no flags
if (this.actorFlags === {}) return;
if (isEmpty(this.actorFlags)) return;

// get the active effect keys applicable for this roll
const advKeys = this.advantageKeys;
Expand Down Expand Up @@ -254,7 +254,7 @@ export class CriticalReminder extends BaseReminder {
this._message();

// quick return if there are no flags
if (this.actorFlags === {} && this.targetFlags === {}) return;
if (isEmpty(this.actorFlags) && isEmpty(this.targetFlags)) return;

// build the active effect keys applicable for this roll
const critKeys = ["critical.all", `critical.${this.actionType}`];
Expand Down
10 changes: 10 additions & 0 deletions src/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ Hooks.once("init", () => {
default: true,
onChange: (value) => (showSources = value),
});

game.settings.register("adv-reminder", "updateStatusEffects", {
name: "adv-reminder.UpdateStatusEffects.Name",
hint: "adv-reminder.UpdateStatusEffects.Hint",
scope: "world",
config: true,
requiresReload: true,
type: Boolean,
default: false,
});
});

Hooks.once("ready", () => {
Expand Down
Loading

0 comments on commit e623498

Please sign in to comment.