Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Miscellaneous Much-Mneeded Maintenance #110

Merged
merged 7 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ The `module/data/` directory is laid out as follows:

### Macros

Many facets of automation must be handled with macros. These are attached using [Item Macro](https://foundryvtt.com/packages/itemacro/), which appear as an escaped string in data. To add some human-readability, macros are handled separately and merged during the module build.
Many facets of automation must be handled with macros. These are attached using [DAE](https://foundryvtt.com/packages/dae)'s "DIME", and appear as an escaped string in data. To add some human-readability, macros are handled separately and merged during the module build.

In the [`macro-item/`](./macro-item) directory is a directory for each datatype. Save your (well-formatted, commented) macro code as a Javascript file in one of these directories, structured as an async function named `macro`, with filename `<sourceJson>_<item-name-lowercase-hyphenated>.js` (e.g. `XGE_toll-the-dead.js`). **Note that the first and last lines of the file**—the ones that turn the macro into an async function—**are stripped on compilation into the module's data**.

Expand Down
11 changes: 1 addition & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,8 @@

While the module is activated in your world, each time Plutonium would import a document, it will check if any automation data is available for that document. If so, it will import the document with the additional automation data included. If not, it will import the document as if *Plutonium Addon: Automation* were not enabled (although sometimes slightly and non-destructively tweaked for better compatibility with the modules below).

Some automations don't use effects directly, but rather call item macros. If you, as the GM, wish to allow players to view/edit macros on items they own, install [Item Macro](https://foundryvtt.com/packages/itemacro) and configure it to allow the _Player access_ option.

> [!TIP]
> **There's no need to import everything prematurely**, 'just in case'. As with Plutonium, all data is included in the module itself, and, if you use any [module integrations](#optional-integrations), you'll be missing out on updates from them.
> **There's no need to import everything prematurely**, 'just in case'. As with Plutonium, all data is included in the module itself, and, if you use any [module integrations](#optional-integrations), you'll be missing out on updates from them.

## Installation

Expand All @@ -47,7 +45,6 @@ Besides *Plutonium* itself, *Plutonium Addon: Automation* **requires**:
Some specific automations require one or more additional modules:
- [Active-Auras](https://foundryvtt.com/packages/ActiveAuras)
- [Active Token Effects](https://foundryvtt.com/packages/ATL)
- [Item Macro](https://foundryvtt.com/packages/itemacro)
- [Warp Gate](https://foundryvtt.com/packages/warpgate)

If you import a document which requires one of these modules, you will be prompted to install/activate it. The automation is highly unlikely to function as intended if you use it before activating the module.
Expand All @@ -62,12 +59,6 @@ You **must** configure some modules in a specific way, or the automations won't
- _**DFreds Convenient Effects** > Modify Status Effects_ — select either `Replace` (preferred) or `Add`.
- _**Midi QoL** > Midi QoL config > Workflow > Apply Convenient Effects_ — select `Apply Item effects, if absent apply CE`.

If you have [Item Macro](https://foundryvtt.com/packages/itemacro) activated, you also need to configure it as follows:

- _**Item Macro** > Override default macro execution_ — uncheck this.
- _**Item Macro** > Character Sheet Hook_ — uncheck this.
- (If installed) _**[Token Action HUD](https://foundryvtt.com/packages/token-action-hud)** > Item-Macro: item macro, original item, or both_ — select `Show the original item`. (Note this is a user setting, so either ensure that each user configures this or use a module such as [Force Client Settings](https://foundryvtt.com/packages/force-client-settings) to guarantee it. Also note that this is _not_ required if you use the system-specific [Token Action HUD Core](https://foundryvtt.com/packages/token-action-hud-core) and [Token Action HUD D&D 5e](https://foundryvtt.com/packages/token-action-hud-dnd5e) modules.)

### Optional integrations

*Plutonium Addon: Automation* can make use of data provided by other modules to provide better automations for more documents. An integration is available for:
Expand Down
54 changes: 25 additions & 29 deletions macro-item/spell/Generic_ddbi-aa-damage-on-entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,27 @@ async function macro (args) {
const saveAbility = ddbEffectFlags.save;
const casterToken = canvas.tokens.placeables.find((t) => t.actor?.uuid === caster.uuid);
const scalingDiceArray = item.system.scaling.formula.split("d");
const scalingDiceNumber = itemLevel - item.system.level;
const scalingDiceNumber = item.system.scaling.mode === "none"
? 0
: itemLevel - item.system.level;
const upscaledDamage = isCantrip
? `${game.modules.get("plutonium-addon-automation").api.DdbImporter.effects.getCantripDice(caster)}d${scalingDiceArray[1]}[${damageType}]`
: scalingDiceNumber > 0 ? `${scalingDiceNumber}d${scalingDiceArray[1]}[${damageType}] + ${damageDice}` : damageDice;

const workflowItemData = duplicate(item);
const workflowItemData = foundry.utils.duplicate(item);
workflowItemData.system.target = {value: 1, units: "", type: "creature"};
workflowItemData.system.save.ability = saveAbility;
workflowItemData.system.components.concentration = false;
workflowItemData.system.properties = game.modules.get("plutonium-addon-automation").api.DdbImporter.effects.removeFromProperties(workflowItemData.system.properties, "concentration") ?? [];
workflowItemData.system.level = itemLevel;
workflowItemData.system.duration = {value: null, units: "inst"};
workflowItemData.system.target = {value: null, width: null, units: "", type: "creature"};
workflowItemData.system.uses = {value: null, max: "", per: null, recovery: "", autoDestroy: false};
workflowItemData.system.consume = {"type": "", "target": null, "amount": null};

setProperty(workflowItemData, "flags.itemacro", {});
setProperty(workflowItemData, "flags.midi-qol", {});
setProperty(workflowItemData, "flags.dae", {});
setProperty(workflowItemData, "effects", []);
foundry.utils.setProperty(workflowItemData, "flags.itemacro", {});
foundry.utils.setProperty(workflowItemData, "flags.midi-qol", {});
foundry.utils.setProperty(workflowItemData, "flags.dae", {});
foundry.utils.setProperty(workflowItemData, "effects", []);
delete workflowItemData._id;

const saveOnEntry = ddbEffectFlags.saveOnEntry;
Expand All @@ -48,19 +52,11 @@ async function macro (args) {
// eslint-disable-next-line new-cap
const entryItem = new CONFIG.Item.documentClass(workflowItemData, {parent: caster});
// console.warn("Saving item on entry", {entryItem, targetToken});
const options = {
showFullCard: false,
createWorkflow: true,
targetUuids: [targetToken.document.uuid],
configureDialog: false,
versatile: false,
consumeResource: false,
consumeSlot: false,
};
await MidiQOL.completeItemUse(entryItem, {}, options);
const [config, options] = game.modules.get("plutonium-addon-automation").api.DdbImporter.effects.syntheticItemWorkflowOptions({targets: [targetToken.document.uuid]});
await MidiQOL.completeItemUse(entryItem, config, options);
} else {
const damageRoll = await new CONFIG.Dice.DamageRoll(upscaledDamage).evaluate({async: true});
if (game.dice3d) game.dice3d.showForRoll(damageRoll);
await MidiQOL.displayDSNForRoll(damageRoll, "damageRoll");

workflowItemData.name = `${workflowItemData.name}: Turn Entry Damage`;

Expand All @@ -72,7 +68,7 @@ async function macro (args) {
[targetToken],
damageRoll,
{
flavor: `(${CONFIG.DND5E.damageTypes[damageType]})`,
flavor: `(${CONFIG.DND5E.damageTypes[damageType].label})`,
itemCardId: "new",
itemData: workflowItemData,
isCritical: false,
Expand All @@ -84,18 +80,18 @@ async function macro (args) {
if (args[0].tag === "OnUse" && args[0].macroPass === "preActiveEffects") {
const safeName = lastArg.itemData.name.replace(/\s|'|\.|’/g, "_");
const dataTracker = {
randomId: randomID(),
randomId: foundry.utils.randomID(),
targetUuids: lastArg.targetUuids,
startRound: game.combat.round,
startTurn: game.combat.turn,
spellLevel: lastArg.spellLevel,
};

const item = await fromUuid(lastArg.itemUuid);
await DAE.unsetFlag(item, `${safeName}Tracker`);
await DAE.setFlag(item, `${safeName}Tracker`, dataTracker);
await DAE.unsetFlag(item.actor, `${safeName}Tracker`);
await DAE.setFlag(item.actor, `${safeName}Tracker`, dataTracker);

const ddbEffectFlags = lastArg.item.flags["plutonium-addon-automation"]?.effect;
const ddbEffectFlags = lastArg.item.flags.ddbimporter?.effect;

if (ddbEffectFlags) {
const sequencerFile = ddbEffectFlags.sequencerFile;
Expand All @@ -114,8 +110,8 @@ async function macro (args) {
});
return effect;
});
args[0].item.effects = duplicate(newEffects);
args[0].itemData.effects = duplicate(newEffects);
args[0].item.effects = foundry.utils.duplicate(newEffects);
args[0].itemData.effects = foundry.utils.duplicate(newEffects);
}
const template = await fromUuid(lastArg.templateUuid);
await template.update({"flags.effect": ddbEffectFlags});
Expand All @@ -128,7 +124,7 @@ async function macro (args) {
const targetItemTracker = DAE.getFlag(item.parent, `${safeName}Tracker`);
const originalTarget = targetItemTracker.targetUuids.includes(lastArg.tokenUuid);
const target = canvas.tokens.get(lastArg.tokenId);
const targetTokenTrackerFlag = DAE.getFlag(target, `${safeName}Tracker`);
const targetTokenTrackerFlag = DAE.getFlag(target.actor, `${safeName}Tracker`);
const targetedThisCombat = targetTokenTrackerFlag && targetItemTracker.randomId === targetTokenTrackerFlag.randomId;
const targetTokenTracker = targetedThisCombat
? targetTokenTrackerFlag
Expand All @@ -154,17 +150,17 @@ async function macro (args) {
targetTokenTracker.hasLeft = false;
await rollItemDamage(target, lastArg.efData.origin, targetItemTracker.spellLevel);
}
await DAE.setFlag(target, `${safeName}Tracker`, targetTokenTracker);
await DAE.setFlag(target.actor, `${safeName}Tracker`, targetTokenTracker);
} else if (args[0] === "off") {
const safeName = (lastArg.efData.name ?? lastArg.efData.label).replace(/\s|'|\.|’/g, "_");
const target = canvas.tokens.get(lastArg.tokenId);
const targetTokenTracker = DAE.getFlag(target, `${safeName}Tracker`);
const targetTokenTracker = DAE.getFlag(target.actor, `${safeName}Tracker`);

if (targetTokenTracker) {
targetTokenTracker.hasLeft = true;
targetTokenTracker.turn = game.combat.turn;
targetTokenTracker.round = game.combat.round;
await DAE.setFlag(target, `${safeName}Tracker`, targetTokenTracker);
await DAE.setFlag(target.actor, `${safeName}Tracker`, targetTokenTracker);
}
}
}
57 changes: 0 additions & 57 deletions macro-item/spell/PHB_branding-smite.js

This file was deleted.

15 changes: 4 additions & 11 deletions macro-item/spell/PHB_color-spray.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,8 @@
*/
async function macro (args) {
// based on @ccjmk and @crymic macro for sleep.
// uses convinient effects
// Midi-qol "On Use"

async function wait (ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

const blindHp = await args[0].damageTotal;
const immuneConditions = [game.i18n.localize("Blinded"), game.i18n.localize("Unconscious")];
console.log(`Color Spray Spell => Available HP Pool [${blindHp}] points`);
Expand All @@ -29,7 +22,7 @@ async function macro (args) {

if (remainingBlindHp >= targetHpValue) {
remainingBlindHp -= targetHpValue;
console.log(`Color Spray Results => Target: ${findTarget.name} | HP: ${targetHpValue} | HP Pool: ${remainingBlindHp} | Status: Blinded`);
console.log(`Color Spray Results => Target: ${findTarget.name} | HP: ${targetHpValue} | HP Pool: ${remainingBlindHp} | Status: Blinded`);
blindTarget.push(`<div class="midi-qol-flex-container"><div>Blinded</div><div class="midi-qol-target-npc midi-qol-target-name" id="${findTarget.id}"> ${findTarget.name}</div><div><img src="${targetImg}" width="30" height="30" style="border:0px"></div></div>`);
const gameRound = game.combat ? game.combat.round : 0;
const effectData = {
Expand All @@ -41,7 +34,7 @@ async function macro (args) {
duration: {startRound: gameRound, startTime: game.time.worldTime},
flags: {dae: {specialDuration: ["turnEndSource"]}},
changes: [
{key: "macro.CE", mode: CONST.ACTIVE_EFFECT_MODES.CUSTOM, value: game.i18n.localize("Blinded"), priority: 20},
game.modules.get("plutonium-addon-automation").api.DdbImporter.effects.generateStatusEffectChange(game.i18n.localize("Blinded"), 20),
],
};

Expand All @@ -51,10 +44,10 @@ async function macro (args) {
blindTarget.push(`<div class="midi-qol-flex-container"><div>misses</div><div class="midi-qol-target-npc midi-qol-target-name" id="${findTarget.id}"> ${findTarget.name}</div><div><img src="${targetImg}" width="30" height="30" style="border:0px"></div></div>`);
}
}
await wait(500);
await game.modules.get("plutonium-addon-automation").api.DdbImporter.effects.wait(500);
const blindResults = `<div><div class="midi-qol-nobox">${blindTarget.join("")}</div></div>`;
const chatMessage = game.messages.get(args[0].itemCardId);
let content = duplicate(chatMessage.content);
let content = foundry.utils.duplicate(chatMessage.content);
const searchString = /<div class="midi-qol-hits-display">[\s\S]*<div class="end-midi-qol-hits-display">/g;
const replaceString = `<div class="midi-qol-hits-display"><div class="end-midi-qol-hits-display">${blindResults}`;
content = await content.replace(searchString, replaceString);
Expand Down
Loading
Loading