180 lines
6.0 KiB
JavaScript
180 lines
6.0 KiB
JavaScript
const ICON = 'icons/magic/symbols/circle-ouroboros.webp';
|
|
const ACTORFOLDER = "Summon Ally";
|
|
|
|
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[0]);
|
|
} else {
|
|
ui.notifications.error("Please select or target a token");
|
|
}
|
|
|
|
async function main(token) {
|
|
let tokenList = token.name;
|
|
let folder = game.folders.find(f => f.data.type == 'Actor' && f.data.name == ACTORFOLDER)
|
|
let menuOptions = {
|
|
title: "Summon Ally",
|
|
defaultButton: "cancel",
|
|
options: {}
|
|
}
|
|
let menuData = {
|
|
inputs: [
|
|
{ type: 'header', label: 'Summon Ally' },
|
|
{ type: 'info', label: `${tokenList} is summoning an ally` },
|
|
{
|
|
type: 'info',
|
|
label: `<table><thead>
|
|
<tr><th>Rank</th><th>Cost</th><th>Servant</th></tr>
|
|
</thead><tbody>
|
|
<tr><td>Novice</td><td>2</td><td>Attendant</td></tr>
|
|
<tr><td>Seasoned</td><td>4</td><td>Bodyguard</td></tr>
|
|
<tr><td>Veteran</td><td>6*</td><td>Mirror Self*</td></tr>
|
|
<tr><td>Heroic</td><td>8</td><td>Sentinel</td></tr>
|
|
</tbody></table>
|
|
`
|
|
},
|
|
{
|
|
type: 'select',
|
|
label: "Ally to summon",
|
|
options: folder.contents.map(a => a.data.name)
|
|
},
|
|
{
|
|
type: 'number',
|
|
label: 'Number to spawn (+half total cost per addtl.)',
|
|
options: 1
|
|
},
|
|
{ type: 'checkbox', label: 'Bite/Claw (+1)', options: false }
|
|
],
|
|
buttons: [
|
|
{ label: "Apply", value: "apply" },
|
|
{ label: "Apply with Raise", value: "raise" },
|
|
{ label: "Cancel", value: "cancel" }
|
|
]
|
|
}
|
|
|
|
let {buttons, inputs} = await warpgate.menu(menuData, menuOptions);
|
|
let summonData = {
|
|
raise: (buttons == "raise"),
|
|
actorName: (inputs[3]),
|
|
number: inputs[4],
|
|
addBiteClaw: inputs[5],
|
|
}
|
|
summonData.actor = folder.contents.find(a => a.data.name == summonData.actorName);
|
|
summonData.icon = summonData.actor.data.token.img;
|
|
doWork(summonData, token);
|
|
}
|
|
|
|
async function doWork(summonData, token) {
|
|
console.log("Summon Ally", token, summonData);
|
|
let effectData = {
|
|
icon: ICON,
|
|
id: "summonally",
|
|
label: "Summoned Ally",
|
|
duration: { rounds: 5 },
|
|
flags: {
|
|
swade: {
|
|
expiration: 3,
|
|
loseTurnOnHold: true
|
|
}
|
|
},
|
|
changes: [],
|
|
};
|
|
let mutateOptions = {
|
|
comparisonKeys: { 'ActiveEffect': 'label' },
|
|
name: "Summoned Ally",
|
|
permanent: true,
|
|
description: "Summoned Ally",
|
|
}
|
|
let mutate = {
|
|
embedded: {
|
|
ActiveEffect: {
|
|
"Summoned Ally": effectData,
|
|
}
|
|
}
|
|
};
|
|
await warpgate.mutate(token.document, mutate, {}, mutateOptions);
|
|
let spawnOptions = {
|
|
controllingActor: token.actor,
|
|
duplicates: summonData.number,
|
|
comparisonKeys: {'ActiveEffect': 'label'},
|
|
crosshairs: {
|
|
size: 1,
|
|
icon: summonData.icon,
|
|
label: `Summon ${summonData.actorName}`,
|
|
drawOutline: false,
|
|
rememberControlled: true
|
|
}
|
|
}
|
|
let mutateData = {
|
|
token: {
|
|
actorLink: false,
|
|
name: `${token.name}'s ${summonData.actor.data.token.name}`,
|
|
},
|
|
embedded: {
|
|
Item: {}
|
|
}
|
|
}
|
|
if (summonData.raise) {
|
|
mutateData.embedded.Item.Resilient = {
|
|
"name": "Resilient",
|
|
"type": "ability",
|
|
"img": "systems/swade/assets/icons/ability.svg",
|
|
"data": {
|
|
"description": "<div class=\"swpf-core\">\n<p>Some creatures, such as ogres or dire versions of common animals on Golarion, are tough to put down.</p>\n<p>Resilient Extras can take one @Compendium[swpf-core-rules.swpf-rules.Wounds]{Wound} before they’re @Compendium[swpf-core-rules.swpf-rules.Incapacitation]{Incapacitated}, Very Resilient Extras can take two. @Compendium[swpf-core-rules.swpf-rules.Wild Cards and Extras]{Wild Cards} can’t be Resilient or Very Resilient. The abilities exist to bring select Extras a little closer to the heroes and villains who lead them.</p>\n</div>",
|
|
"notes": "",
|
|
"additionalStats": {},
|
|
"subtype": "special",
|
|
"grantsPowers": false
|
|
},
|
|
"effects": {},
|
|
"flags": {
|
|
"core": {
|
|
"sourceId": "Compendium.swpf-core-rules.swpf-abilities.kiu5yk2aQkUGwlHN"
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
if (summonData.addBiteClaw) {
|
|
mutateData.embedded.Item["Bite/Claw"] = {
|
|
"name": "Bite/Claw",
|
|
"type": "weapon",
|
|
"img": "icons/creatures/claws/claw-hooked-curved.webp",
|
|
"data": {
|
|
"description": "",
|
|
"notes": "",
|
|
"additionalStats": {},
|
|
"quantity": 1,
|
|
"weight": 0,
|
|
"price": 0,
|
|
"equippable": true,
|
|
"equipped": true,
|
|
"isVehicular": false,
|
|
"actions": {
|
|
"skill": "Fighting",
|
|
"skillMod": "",
|
|
"dmgMod": "",
|
|
"additional": {}
|
|
},
|
|
"bonusDamageDie": 6,
|
|
"damage": "@str+d6",
|
|
"range": "",
|
|
"rof": "1",
|
|
"ap": 0,
|
|
"parry": 0,
|
|
"minStr": "",
|
|
"shots": 0,
|
|
"currentShots": 0,
|
|
"ammo": "",
|
|
"autoReload": false
|
|
},
|
|
"effects": {},
|
|
}
|
|
}
|
|
await warpgate.spawn(summonData.actorName, mutateData, {}, spawnOptions)
|
|
} |