add warpgate macros
This commit is contained in:
parent
757f98272a
commit
302785feb1
@ -1,69 +1,70 @@
|
|||||||
{
|
[
|
||||||
"id": "Smite",
|
{
|
||||||
"name": "Smite",
|
"id": "Smite",
|
||||||
"button_name": "Smite Bonus",
|
"name": "Smite",
|
||||||
"dmgMod": "+2",
|
"button_name": "Smite Bonus",
|
||||||
"defaultChecked": true,
|
"dmgMod": "+2",
|
||||||
"and_selector": [
|
"defaultChecked": true,
|
||||||
{
|
"and_selector": [
|
||||||
"not_selector": [
|
{
|
||||||
{
|
"not_selector": [
|
||||||
"selector_type": "actor_has_effect",
|
{
|
||||||
"selector_value": "Smite with raise"
|
"selector_type": "actor_has_effect",
|
||||||
}
|
"selector_value": "Smite with raise"
|
||||||
]
|
}
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"selector_type": "actor_has_effect",
|
{
|
||||||
"selector_value": "Smite"
|
"selector_type": "actor_has_effect",
|
||||||
},
|
"selector_value": "Smite"
|
||||||
{
|
},
|
||||||
"or_selector": [
|
{
|
||||||
{
|
"or_selector": [
|
||||||
"selector_type": "skill",
|
{
|
||||||
"selector_value": "Fighting"
|
"selector_type": "skill",
|
||||||
},
|
"selector_value": "Fighting"
|
||||||
{
|
},
|
||||||
"selector_type": "skill",
|
{
|
||||||
"selector_value": "Athletics"
|
"selector_type": "skill",
|
||||||
},
|
"selector_value": "Athletics"
|
||||||
{
|
},
|
||||||
"selector_type": "skill",
|
{
|
||||||
"selector_value": "Shooting"
|
"selector_type": "skill",
|
||||||
}
|
"selector_value": "Shooting"
|
||||||
]
|
}
|
||||||
}
|
]
|
||||||
],
|
}
|
||||||
"group": "Spell Effects"
|
],
|
||||||
}
|
"group": "Spell Effects"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "SmiteRaise",
|
"id": "SmiteRaise",
|
||||||
"name": "Smite with Raise",
|
"name": "Smite with Raise",
|
||||||
"button_name": "Smite Bonus",
|
"button_name": "Smite Bonus",
|
||||||
"dmgMod": "+4",
|
"dmgMod": "+4",
|
||||||
"defaultChecked": true,
|
"defaultChecked": true,
|
||||||
"and_selector": [
|
"and_selector": [
|
||||||
{
|
{
|
||||||
"selector_type": "actor_has_effect",
|
"selector_type": "actor_has_effect",
|
||||||
"selector_value": "Smite with raise",
|
"selector_value": "Smite with raise"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"or_selector": [
|
"or_selector": [
|
||||||
{
|
{
|
||||||
"selector_type": "skill",
|
"selector_type": "skill",
|
||||||
"selector_value": "Fighting"
|
"selector_value": "Fighting"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"selector_type": "skill",
|
"selector_type": "skill",
|
||||||
"selector_value": "Athletics"
|
"selector_value": "Athletics"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"selector_type": "skill",
|
"selector_type": "skill",
|
||||||
"selector_value": "Shooting"
|
"selector_value": "Shooting"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
"group": "Spell Effects"
|
"group": "Spell Effects"
|
||||||
}
|
}
|
||||||
|
]
|
||||||
224
macros/warpgate_spells/boost-lower-warpgate.js
Normal file
224
macros/warpgate_spells/boost-lower-warpgate.js
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
const UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'
|
||||||
|
const DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'
|
||||||
|
|
||||||
|
let tokens = [];
|
||||||
|
let targets = Array.from(game.user.targets);
|
||||||
|
if (targets.length > 0) {
|
||||||
|
tokens = targets;
|
||||||
|
} else if (canvas.tokens.controlled.length > 0) {
|
||||||
|
tokens = canvas.tokens.controlled;
|
||||||
|
}
|
||||||
|
if (tokens.length > 0) {
|
||||||
|
main(tokens);
|
||||||
|
} else {
|
||||||
|
ui.notifications.error("Please select or target a token");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main(tokens) {
|
||||||
|
let traitOptions = [
|
||||||
|
"Agility",
|
||||||
|
"Smarts",
|
||||||
|
"Spirit",
|
||||||
|
"Strength",
|
||||||
|
"Vigor"
|
||||||
|
];
|
||||||
|
let allSkills = [];
|
||||||
|
let traits = {
|
||||||
|
"Agility": {
|
||||||
|
type: "attribute",
|
||||||
|
name: "Agility",
|
||||||
|
modkey: "data.attributes.agility.die.modifier",
|
||||||
|
diekey: "data.attributes.agility.die.sides"
|
||||||
|
},
|
||||||
|
"Smarts": {
|
||||||
|
type: "attribute",
|
||||||
|
name: "Smarts",
|
||||||
|
modkey: "data.attributes.smarts.die.modifier",
|
||||||
|
diekey: "data.attributes.smarts.die.sides"
|
||||||
|
},
|
||||||
|
"Spirit": {
|
||||||
|
type: "attribute",
|
||||||
|
name: "Spirit",
|
||||||
|
modkey: "data.attributes.spirit.die.modifier",
|
||||||
|
diekey: "data.attributes.spirit.die.sides"
|
||||||
|
},
|
||||||
|
"Strength": {
|
||||||
|
type: "attribute",
|
||||||
|
name: "Strength",
|
||||||
|
modkey: "data.attributes.strength.die.modifier",
|
||||||
|
diekey: "data.attributes.strength.die.sides"
|
||||||
|
},
|
||||||
|
"Vigor": {
|
||||||
|
type: "attribute",
|
||||||
|
name: "Vigor",
|
||||||
|
modkey: "data.attributes.vigor.die.modifier",
|
||||||
|
diekey: "data.attributes.vigor.die.sides"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let tokenList = tokens.map(t => t.name).join(", ");
|
||||||
|
for (const token of tokens) {
|
||||||
|
let skills = token.actor.items.filter(e => e.type == "skill");
|
||||||
|
for (const skill of skills) {
|
||||||
|
let name = skill.data.name
|
||||||
|
traits[name] = {
|
||||||
|
type: "skill",
|
||||||
|
name: name,
|
||||||
|
modkey: `@Skill{${name}}[data.die.modifier]`,
|
||||||
|
diekey: `@Skill{${name}}[data.die.sides]`
|
||||||
|
};
|
||||||
|
if (name != 'Unskilled' && !allSkills.find(v => v == name)) {
|
||||||
|
allSkills.push(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
traitOptions = traitOptions.concat(allSkills.sort());
|
||||||
|
let menuOptions = {
|
||||||
|
title: 'Boost/Lower Trait',
|
||||||
|
defaultButton: "Cancel",
|
||||||
|
options: {}
|
||||||
|
};
|
||||||
|
let menuData = {
|
||||||
|
inputs: [
|
||||||
|
{type: 'header', label: 'Boost/Lower Trait'},
|
||||||
|
{type: 'info', label: `Affected Tokens: ${tokenList}`},
|
||||||
|
{type: 'select', label: 'Trait', options: traitOptions},
|
||||||
|
{type: 'info', label: "Boost or Lower?"},
|
||||||
|
{type: 'radio', label: 'Boost', options: ['boostlower', true]},
|
||||||
|
{type: 'radio', label: 'Lower', options: ['boostlower', false]},
|
||||||
|
],
|
||||||
|
buttons: [
|
||||||
|
{label: "Apply", value: "apply"},
|
||||||
|
{label: "Apply with raise", value: "raise"},
|
||||||
|
{label: "Cancel", value: "cancel"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let {buttons, inputs} = await warpgate.menu(menuData, menuOptions);
|
||||||
|
if (buttons != "cancel") {
|
||||||
|
let trait = inputs[2];
|
||||||
|
let direction = inputs[4] || inputs[5];
|
||||||
|
createEffect(tokens, traits[trait], direction, buttons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDottedPart(obj, key) {
|
||||||
|
let value = obj;
|
||||||
|
for (const part of key.split(".")) {
|
||||||
|
value = value[part];
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createEffect(tokens, trait, direction, buttons) {
|
||||||
|
const raise = buttons;
|
||||||
|
const effectName = `${raise == 'raise' ? "Major" : "Minor"} ${direction} ${trait.name}`;
|
||||||
|
const effectId = `${raise == 'raise' ? "Major" : "Minor"}${direction}${trait.name}`;
|
||||||
|
const effectIcon = (direction == 'Boost' ? UPICON : DOWNICON)
|
||||||
|
for (const token of tokens) {
|
||||||
|
let tokenDoc = token.document;
|
||||||
|
let currentDie = 0;
|
||||||
|
let currentMod = 0;
|
||||||
|
if (trait.type == 'attribute') {
|
||||||
|
currentDie = getDottedPart(token.actor.data, trait.diekey);
|
||||||
|
currentMod = getDottedPart(token.actor.data, trait.modkey);
|
||||||
|
} else {
|
||||||
|
let skill = token.actor.items.filter(s => s.type == 'skill').find(
|
||||||
|
s => s.data.name == trait.name)
|
||||||
|
if (skill) {
|
||||||
|
currentDie = skill.data.data.die.sides;
|
||||||
|
currentMod = skill.data.data.die.modifier;
|
||||||
|
} else {
|
||||||
|
currentDie = 4;
|
||||||
|
currentMod = -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentDie == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (currentDie == 4 && direction == "Lower") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let diemod = 2;
|
||||||
|
let modmod = 0;
|
||||||
|
if (direction == "Lower") {
|
||||||
|
diemod = -2;
|
||||||
|
}
|
||||||
|
if (currentDie == 6 && direction == "Lower" && raise) {
|
||||||
|
diemod = -1
|
||||||
|
} else if (currentDie == 12 && direction == "Boost") {
|
||||||
|
diemod = 0;
|
||||||
|
modmod = 1;
|
||||||
|
}
|
||||||
|
if (raise) {
|
||||||
|
diemod *= 2;
|
||||||
|
modmod *= 2;
|
||||||
|
}
|
||||||
|
if (currentDie == 10 && direction == "Boost" && raise) {
|
||||||
|
diemod = 2;
|
||||||
|
modmod = 1;
|
||||||
|
}
|
||||||
|
if (currentDie == 4 && currentMod == -2 && direction == "Boost") {
|
||||||
|
diemod = (raise ? 2 : 0);
|
||||||
|
modmod = 2;
|
||||||
|
}
|
||||||
|
let effectData = {
|
||||||
|
icon: effectIcon,
|
||||||
|
id: effectId,
|
||||||
|
label: effectName,
|
||||||
|
flags: {
|
||||||
|
swade: {
|
||||||
|
expiration: 3,
|
||||||
|
loseTurnOnHold: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
changes: []
|
||||||
|
};
|
||||||
|
let mode = foundry.CONST.ACTIVE_EFFECT_MODES.ADD;
|
||||||
|
if (diemod != 0) {
|
||||||
|
effectData.changes.push({key: trait.diekey, mode: mode, value: diemod, priority: 0});
|
||||||
|
}
|
||||||
|
if (modmod != 0) {
|
||||||
|
effectData.changes.push({key: trait.modkey, mode: mode, value: modmod, priority: 0});
|
||||||
|
}
|
||||||
|
if (direction == "Boost") {
|
||||||
|
effectData.duration = {rounds: 5};
|
||||||
|
}
|
||||||
|
let mutate = {
|
||||||
|
embedded: {
|
||||||
|
ActiveEffect: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mutate.embedded.ActiveEffect[effectName] = effectData;
|
||||||
|
let mutateOptions = {
|
||||||
|
comparisonKeys: {'ActiveEffect': 'label'},
|
||||||
|
name: effectName,
|
||||||
|
permanent: false,
|
||||||
|
description: effectName,
|
||||||
|
}
|
||||||
|
if (trait.type == 'skill' && direction == 'Boost' && !token.actor.items.getName(trait.name)) {
|
||||||
|
let itemmutate = { embedded: { Item: {} } }
|
||||||
|
itemmutate.embedded.Item[trait.name] = {
|
||||||
|
"name": trait.name,
|
||||||
|
"type": "skill",
|
||||||
|
"img": "systems/swade/assets/icons/skills/uncertainty.svg",
|
||||||
|
"data": {
|
||||||
|
"description": "See SWADE. Auto added as untrained for Boost Trait.",
|
||||||
|
"notes": "",
|
||||||
|
"additionalStats": {},
|
||||||
|
"attribute": trait.attribute,
|
||||||
|
"isCoreSkill": false,
|
||||||
|
"die": {
|
||||||
|
"sides": 4,
|
||||||
|
"modifier": -2
|
||||||
|
},
|
||||||
|
"wild-die": {
|
||||||
|
"sides": 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await warpgate.mutate(token.document, itemmutate, {}, mutateOptions);
|
||||||
|
}
|
||||||
|
mutateOptions.permanent = true;
|
||||||
|
await warpgate.mutate(token.document, mutate, {}, mutateOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
79
macros/warpgate_spells/deflection-warpgate.js
Normal file
79
macros/warpgate_spells/deflection-warpgate.js
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
const ICON = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'
|
||||||
|
|
||||||
|
let tokens = [];
|
||||||
|
let targets = Array.from(game.user.targets);
|
||||||
|
if (targets.length > 0) {
|
||||||
|
tokens = targets;
|
||||||
|
} else if (canvas.tokens.controlled.length > 0) {
|
||||||
|
tokens = canvas.tokens.controlled;
|
||||||
|
}
|
||||||
|
if (tokens.length > 0) {
|
||||||
|
main(tokens);
|
||||||
|
} else {
|
||||||
|
ui.notifications.error("Please select or target a token");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main(tokens) {
|
||||||
|
let tokenList = tokens.map(t => t.name).join(", ");
|
||||||
|
let dialogOptions = {
|
||||||
|
title: "Deflection",
|
||||||
|
content: `Apply <em>Deflection</em> to ${tokenList}`,
|
||||||
|
default: "cancel",
|
||||||
|
buttons: [
|
||||||
|
{label: "Apply (melee)", value: "melee"},
|
||||||
|
{label: "Apply (ranged)", value: "ranged"},
|
||||||
|
{label: "Apply with raise (both)", value: "raise"},
|
||||||
|
{label: "Cancel", value: "cancel"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let choice = await warpgate.buttonDialog(dialogOptions);
|
||||||
|
if (choice != "cancel") {
|
||||||
|
createEffect(tokens, choice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createEffect(tokens, choice) {
|
||||||
|
let effectName = 'Deflection';
|
||||||
|
let effectId = `deflection${choice}`;
|
||||||
|
let changes = []
|
||||||
|
switch (choice) {
|
||||||
|
case 'melee':
|
||||||
|
effectName = "Melee " + effectName;
|
||||||
|
break
|
||||||
|
case 'ranged':
|
||||||
|
effectName = "Ranged " + effectName;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
const effectIcon = ICON;
|
||||||
|
for (const token of tokens) {
|
||||||
|
let effectData = {
|
||||||
|
icon: effectIcon,
|
||||||
|
id: effectId,
|
||||||
|
label: effectName,
|
||||||
|
duration: {rounds: 5},
|
||||||
|
flags: {
|
||||||
|
swade: {
|
||||||
|
expiration: 3,
|
||||||
|
loseTurnOnHold: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
changes: [
|
||||||
|
{key: 'data.stats.parry.modifier', mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE, value: 0, priority: 0}
|
||||||
|
],
|
||||||
|
};
|
||||||
|
let mutate = {
|
||||||
|
embedded: {
|
||||||
|
ActiveEffect: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mutate.embedded.ActiveEffect[effectName] = effectData;
|
||||||
|
let mutateOptions = {
|
||||||
|
comparisonKeys: {'ActiveEffect': 'label'},
|
||||||
|
name: effectName,
|
||||||
|
permanent: true,
|
||||||
|
description: effectName,
|
||||||
|
}
|
||||||
|
await warpgate.mutate(token.document, mutate, {}, mutateOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
0
macros/warpgate_spells/protection-warpgate.js
Normal file
0
macros/warpgate_spells/protection-warpgate.js
Normal file
101
macros/warpgate_spells/smite-warpgate.js
Normal file
101
macros/warpgate_spells/smite-warpgate.js
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
const ICON = 'icons/weapons/swords/sword-flanged-lightning.webp'
|
||||||
|
|
||||||
|
let tokens = [];
|
||||||
|
let targets = Array.from(game.user.targets);
|
||||||
|
if (targets.length > 0) {
|
||||||
|
tokens = targets;
|
||||||
|
} else if (canvas.tokens.controlled.length > 0) {
|
||||||
|
tokens = canvas.tokens.controlled;
|
||||||
|
}
|
||||||
|
if (tokens.length > 0) {
|
||||||
|
main(tokens);
|
||||||
|
} else {
|
||||||
|
ui.notifications.error("Please select or target a token");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main(tokens) {
|
||||||
|
let tokenList = tokens.map(t => t.name).join(", ");
|
||||||
|
let menuOptions = {
|
||||||
|
title: 'Smite',
|
||||||
|
defaultButton: "cancel",
|
||||||
|
options: {}
|
||||||
|
}
|
||||||
|
let menuData = {
|
||||||
|
inputs: [
|
||||||
|
{type: 'header', label: 'Smite'},
|
||||||
|
{type: 'info', label: `Apply Smite to ${tokenList}`},
|
||||||
|
],
|
||||||
|
buttons: [
|
||||||
|
{label: "Apply", value: "apply"},
|
||||||
|
{label: "Apply with Raise", value: "raise"},
|
||||||
|
{label: "Cancel", value: "cancel"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
let tokenWeapons = {};
|
||||||
|
let index = 1;
|
||||||
|
for (const token of tokens) {
|
||||||
|
index += 2;
|
||||||
|
tokenWeapons[token.id] = index;
|
||||||
|
menuData.inputs.push({type: 'info', label: `<h2>${token.name}</h2>`});
|
||||||
|
let weapons = token.actor.items.filter(i => i.type == 'weapon').map(i => i.name);
|
||||||
|
weapons.unshift("");
|
||||||
|
menuData.inputs.push({type: 'select', label: token.name, options: weapons});
|
||||||
|
}
|
||||||
|
let {buttons, inputs} = await warpgate.menu(menuData, menuOptions);
|
||||||
|
for (tokenid in tokenWeapons) {
|
||||||
|
tokenWeapons[tokenid] = inputs[tokenWeapons[tokenid]];
|
||||||
|
}
|
||||||
|
if (buttons != "cancel") {
|
||||||
|
await createEffect(tokens, tokenWeapons, buttons);
|
||||||
|
}
|
||||||
|
console.log(buttons, tokenWeapons);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createEffect(tokens, tokenWeapons, choice) {
|
||||||
|
const effectIcon = ICON;
|
||||||
|
const changeValue = (choice == 'raise' ? "+4" : "+2");
|
||||||
|
for (const token of tokens) {
|
||||||
|
const weaponName = tokenWeapons[token.id];
|
||||||
|
const weaponId = token.actor.items.getName(weaponName)?.id
|
||||||
|
const changeKey = `@Weapon{${weaponName}}[data.damage]`
|
||||||
|
if (!weaponId) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const effectName = `Smite (${weaponName})`;
|
||||||
|
const effectId = `smite${choice}_${weaponId}`;
|
||||||
|
let effectData = {
|
||||||
|
icon: effectIcon,
|
||||||
|
id: effectId,
|
||||||
|
label: effectName,
|
||||||
|
duration: {rounds: 5},
|
||||||
|
flags: {
|
||||||
|
swade: {
|
||||||
|
expiration: 3,
|
||||||
|
loseTurnOnHold: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
changes: [
|
||||||
|
{
|
||||||
|
key: changeKey,
|
||||||
|
mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,
|
||||||
|
value: changeValue,
|
||||||
|
priority: 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
};
|
||||||
|
let mutate = {
|
||||||
|
embedded: {
|
||||||
|
ActiveEffect: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mutate.embedded.ActiveEffect[effectName] = effectData;
|
||||||
|
let mutateOptions = {
|
||||||
|
comparisonKeys: {'ActiveEffect': 'label'},
|
||||||
|
name: effectName,
|
||||||
|
permanent: true,
|
||||||
|
description: effectName,
|
||||||
|
}
|
||||||
|
await warpgate.mutate(token.document, mutate, {}, mutateOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user