Skip to content

Instantly share code, notes, and snippets.

@palikhov
Created May 21, 2021 19:37
Show Gist options
  • Save palikhov/81b221d01505156bc5e8e3d452ac743e to your computer and use it in GitHub Desktop.
Save palikhov/81b221d01505156bc5e8e3d452ac743e to your computer and use it in GitHub Desktop.
Foundry Animate objects attack macro
/*
* Animate Object Attacks.
* Initial version stolen from somewhere but I forgot from where
*/
const details = {
"e-blast" : { "size": 1, "atk": 11, "dmg": "1d10 + 5" },
};
// Use select token or some defaults if nothing is selected.
const actorData = actor || canvas.tokens.controlled[0] || game.user.character;
if (!actorData) {
ui.notifications.warn("No actor selected");
}
const targetId = game.user.targets.ids[0];
const targetToken = canvas.tokens.get(targetId);
const targetName = targetToken?.actor.name || "Enemy";
const count = parseInt(game.brMacro?.animate_objects_count, 4) || 4;
const rollState = BetterRolls.getRollState();
const content = `
<p><em>Your animated objects attack ${targetName}!</em></p>
<p>Enter the details for the Animated Objects...</p>
<form>
<div class="form-group">
<label for="size">Size:</label>
<select id="size" name="size">
<option value="e-blast">E-Blast</option>
</select>
</div>
<div class="form-group">
<label for="count">Number of Objects:</label>
<input id="count" name="count" type="number" min="0" value="${count}"></input>
</div>
<div class="form-group">
<label for="size">Roll Type:</label>
<select id="roll" name="roll">
<option value="first">Normal</option>
<option value="highest" ${rollState === "highest" ? "selected" : null}>Advantage</option>
<option value="lowest" ${rollState === "lowest" ? "selected" : null}>Disadvantage</option>
</select>
</div>
</form>
`;
const attackAction = async (html) => {
let size = html.find("#size")[0].value;
let count = html.find("#count")[0].value;
let rollState = html.find("#roll")[0].value;
const { atk, dmg } = details[size];
const rollTypes = {
"highest": "Advantage",
"lowest": "Disadvantage"
};
let rollExpr = `1d20 + ${atk}`;
const card = BetterRolls.rollItem(actorData);
card.addField(["header", {img: this.data.img, title: "E-Blast"}]);
for (let i = 0; i < count; i++) {
const rollTypeStr = rollState in rollTypes ? `(${rollTypes[rollState]})` : '';
const title = `Object Attacks #${i+1} (+${atk}) ${rollTypeStr}`;
card.addField(["attack", { formula: rollExpr, rollState, title}]);
card.addField(["damage", { formula: dmg }]);
}
await card.toMessage();
// Remember setting for next run
game.brMacro = game.brMacro ?? {};
game.brMacro.animate_objects_count = count;
};
new Dialog({
title: "Animated Object Attacks",
content: content,
buttons: {
attack: {
icon: '<i class="fas fa-check"></i>',
label: "Attack!",
callback: attackAction
},
cancel: { label: "Cancel" }
},
default: "attack",
}).render(true);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment