add quick damage roll macro

This commit is contained in:
Mike Bloy 2023-12-18 15:34:29 -06:00
parent 952511b182
commit 66ee916572
52 changed files with 137 additions and 918 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- New macro: Quick Damage Roll
- New Vision mode: Low Light Vision
- Power Effect for Zombie
- Sample fixed request roll macro

View File

@ -1,45 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const tokenList = tokens.map(t => t.name).join(', ')
const menuOptions = {
title: 'Blind',
defaultButton: 'Cancel',
options: {}
}
const menuData = {
inputs: [
{ type: 'header', label: 'Blind' },
{ type: 'info', label: `Apply Blind to ${tokenList}` },
{ type: 'checkbox', label: 'Strong', options: false }
],
buttons: [
{ label: 'Apply', value: 'apply' },
{ label: 'Raise', value: 'raise' },
{ label: 'Cancel', value: 'cancel' }
]
}
const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)
if (buttons && buttons !== 'cancel') {
const options = {
raise: (buttons === 'raise'),
strong: (!!inputs[2])
}
await createEffect(tokens, options)
}
}
async function createEffect (tokens, options) {
const effectDetails = (options.raise ? '-4' : '-2')
const effectEnd = (options.strong ? 'Vigor -2' : 'Vigor')
const effectName = `Blind (${effectDetails}) ${effectEnd} ends`
const baseEffect = CONFIG.statusEffects.find(se => se.label === 'EFFECT.StatusBlind')
for (const token of tokens) {
const mutate = swadeMBHelpers.createMutationWithEffect(baseEffect.icon, effectName, 1, [])
mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }
const mutateOptions = swadeMBHelpers.defaultMutationOptions('Blind')
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
}
}

View File

@ -1,133 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
let traitOptions = [
'Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor'
]
const allSkills = []
const traits = {}
for (const traitName of traitOptions) {
const lower = traitName.toLowerCase()
traits[traitName] = {
name: traitName,
type: 'attribute',
modkey: `system.attributes.${lower}.die.modifier`,
diekey: `system.attributes.${lower}.die.sides`
}
}
const tokenList = tokens.map(t => t.name).join(', ')
for (const token of tokens) {
const skills = token.actor.items.filter(item => item.type === 'skill')
for (const skill of skills) {
const name = skill.name
traits[name] = {
type: 'skill',
name,
modkey: `@Skill{${name}}[system.die.modifier]`,
diekey: `@Skill{${name}}[system.die.sides]`
}
if (name !== 'Unskilled' && !allSkills.find(v => v === name)) {
allSkills.push(name)
}
}
}
traitOptions = traitOptions.concat(allSkills.sort())
const menuOptions = {
title: 'Boost/Lower Trait',
defaultButton: 'Cancel',
options: {}
}
const 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: ['isBoost', true] },
{ type: 'radio', label: 'Lower', options: ['isBoost', false] },
{ type: 'checkbox', label: 'Greater', options: false },
{ type: 'checkbox', label: 'Strong (lower only)', options: false }
],
buttons: [
{ label: 'Apply', value: 'apply' },
{ label: 'Apply with raise', value: 'raise' },
{ label: 'Cancel', value: 'cancel' }
]
}
const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)
if (buttons && buttons !== 'cancel') {
const options = {
action: buttons,
name: inputs[2],
trait: traits[inputs[2]],
direction: inputs[4] || inputs[5],
greater: inputs[6],
strong: inputs[7]
}
createEffect(tokens, options)
}
}
const UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'
const DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'
async function createEffect (tokens, options) {
const raise = (options.action === 'raise')
const icon = (options.direction === 'Boost' ? UPICON : DOWNICON)
let namePart = `${options.direction} ${options.trait.name}`
const mode = CONST.ACTIVE_EFFECT_MODES.ADD
const mods = []
if (options.strong && options.direction === 'Lower') {
mods.push('strong')
}
if (options.greater) {
mods.push('greater')
}
if (mods.length > 0) {
namePart = `${namePart} (${mods.join(', ')})`
}
const minorEffect = swadeMBHelpers.createEffectDocument(
icon, `minor ${namePart}`, 5, [
{
key: options.trait.diekey,
mode,
value: (options.direction === 'Boost' ? '+2' : '-2'),
priority: 0
}
]
)
const majorEffect = swadeMBHelpers.createEffectDocument(
icon, `major ${namePart}`, 5, [
{
key: options.trait.diekey,
mode,
value: (options.direction === 'Boost' ? '+2' : '-2'),
priority: 0
}
]
)
if (options.direction === 'Lower' && options.greater === 'Greater') {
minorEffect.changes.push({
key: options.trait.modkey,
mode,
value: '-2',
priority: 0
})
}
const mutate = {
embedded: {
ActiveEffect: {
}
}
}
mutate.embedded.ActiveEffect[minorEffect.id] = minorEffect
if (raise) {
mutate.embedded.ActiveEffect[majorEffect.id] = majorEffect
}
const mutateOptions = swadeMBHelpers.defaultMutationOptions(namePart)
for (const token of tokens) {
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
}
}

View File

@ -1,62 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const tokenList = tokens.map(t => t.name).join(', ')
const menuOptions = {
title: 'Confusion',
defaultButton: 'Cancel',
options: {}
}
const menuData = {
inputs: [
{ type: 'header', label: 'Confusion' },
{ type: 'info', label: `Apply Confusion to ${tokenList}` },
{ type: 'checkbox', label: 'Greater (adds shaken)', options: false }
],
buttons: [
{ label: 'Distracted', value: 'distracted' },
{ label: 'Vulnerable', value: 'vulnerable' },
{ label: 'Raise (both)', value: 'raise' },
{ label: 'Cancel', value: 'cancel' }
]
}
const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)
const greater = (inputs[2] === 'Greater (adds shaken)')
if (buttons && buttons !== 'cancel') {
await createEffect(tokens, buttons, greater)
}
}
function getStatus (label, name) {
const effect = JSON.parse(JSON.stringify(
CONFIG.statusEffects.find(se => se.label === label)))
effect.label = name
effect.flags.core = { statusId: effect.id }
effect.id = name
return effect
}
async function createEffect (tokens, choice, greater) {
const effects = []
if (choice === 'distracted' || choice === 'raise') {
effects.push(getStatus('SWADE.Distr', 'Distracted'))
}
if (choice === 'vulnerable' || choice === 'raise') {
effects.push(getStatus('SWADE.Vuln', 'Vulnerable'))
}
if (greater) {
effects.push(getStatus('SWADE.Shaken', 'Shaken'))
}
for (const token of tokens) {
const mutateOptions = swadeMBHelpers.defaultMutationOptions('Confusion')
const mutate = {
embedded: { ActiveEffect: {} }
}
for (const effect of effects) {
mutate.embedded.ActiveEffect[effect.id] = effect
}
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
}
}

View File

@ -1,37 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const tokenList = tokens.map(t => t.name).join(', ')
const 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' }
]
}
const choice = await warpgate.buttonDialog(dialogOptions)
if (choice && choice !== 'cancel') {
await createEffect(tokens, choice)
}
}
async function createEffect (tokens, choice) {
const icon = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'
let effectName = 'Deflection'
if (choice === 'raise') {
effectName = `${effectName} (all)`
} else {
effectName = `${effectName} (${choice})`
}
for (const token of tokens) {
const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])
const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
}
}

View File

@ -1,74 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const tokenList = tokens.map(t => t.name).join(', ')
const menuOptions = {
title: 'Entangle',
defaultButton: 'Cancel',
options: {}
}
const menuData = {
inputs: [
{ type: 'header', label: 'Entangle' },
{ type: 'info', label: `Apply Entangle to ${tokenList}` },
{ type: 'radio', label: 'Not Damaging', options: ['dmg', true] },
{ type: 'radio', label: 'Damaging', options: ['dmg', false] },
{ type: 'radio', label: 'Deadly', options: ['dmg', false] },
{ type: 'checkbox', label: 'Tough', options: false }
],
buttons: [
{ label: 'Entangled', value: 'apply' },
{ label: 'Bound (raise)', value: 'raise' },
{ label: 'Cancel', value: 'cancel' }
]
}
const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)
if (buttons && buttons !== 'cancel') {
const options = {
apply: (buttons === 'raise' ? 'bound' : 'entangled'),
damage: (inputs[3] ? '2d4' : (inputs[4] ? '2d6' : null)),
tough: (!!inputs[5])
}
await createEffect(tokens, options)
}
}
function getStatus (label, name) {
const effect = JSON.parse(JSON.stringify(
CONFIG.statusEffects.find(se => se.label === label)))
effect.label = name
if (!effect.flags) {
effect.flags = {}
}
effect.flags.core = { statusId: effect.id }
effect.id = name
return effect
}
async function createEffect (tokens, options) {
const effectSearch = (options.apply === 'bound' ? 'SWADE.Bound' : 'SWADE.Entangled')
const effectName = (options.apply === 'bound' ? 'Bound' : 'Entangled')
const effect = getStatus(effectSearch, effectName)
const extraIcon = 'icons/magic/nature/root-vine-barrier-wall-brown.webp'
const extraEffect = swadeMBHelpers.createEffectDocument(extraIcon, 'Entangle Modifier', 1, [])
if (options.damage) {
extraEffect.id = `${extraEffect.id} - ${options.damage} dmg`
extraEffect.label = `${extraEffect.label} - ${options.damage} dmg`
}
if (options.tough) {
extraEffect.id = `Tough ${extraEffect.id}`
extraEffect.label = `Tough ${extraEffect.label}`
}
for (const token of tokens) {
const mutateOptions = swadeMBHelpers.defaultMutationOptions('Entangle')
const mutate = { embedded: { ActiveEffect: {} } }
mutate.embedded.ActiveEffect[effect.id] = effect
if (options.damage || options.tough) {
mutate.embedded.ActiveEffect[extraEffect.id] = extraEffect
}
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
}
}

View File

@ -1,58 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const tokenList = tokens.map(t => t.name).join(', ')
const dialogOptions = {
title: 'Glow',
content: `Apply <em>Glow</em> to ${tokenList}`,
default: 'cancel',
buttons: [
{ label: 'OK', value: 'ok' },
{ label: 'Mutate token lighting', value: 'mutate' },
{ label: 'Cancel', value: 'cancel' }
]
}
const choice = await warpgate.buttonDialog(dialogOptions)
if (choice === 'ok' || choice === 'mutate') {
await createEffect(tokens, choice)
}
}
async function createEffect (tokens, choice) {
const icon = 'icons/magic/light/explosion-star-blue-large.webp'
const effectName = 'Glow'
for (const token of tokens) {
const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])
const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
if (choice === 'mutate') {
const mutate2 = {
token: {
light: {
alpha: 0.5,
angle: 360,
attenuation: 0.5,
animation: {
intensity: 5,
reverse: false,
speed: 5,
type: 'starlight'
},
bright: 0,
color: '#0f3fff',
coloration: 1,
contrast: 0,
dim: 0.5,
luminosity: 0.5,
saturation: 0,
shadows: 0
}
}
}
mutateOptions.permanent = false
await warpgate.mutate(token.document, mutate2, {}, mutateOptions)
}
}
}

View File

@ -1,38 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const tokenList = tokens.map(t => t.name).join(', ')
const dialogOptions = {
title: 'Hinder',
content: `Apply <em>Hinder</em> to ${tokenList}`,
default: 'cancel',
buttons: [
{ label: 'OK', value: 'ok' },
{ label: 'Cancel', value: 'cancel' }
]
}
const choice = await warpgate.buttonDialog(dialogOptions, 'column')
if (choice === 'ok') {
await createEffect(tokens, choice)
}
}
async function createEffect (tokens, choice) {
const icon = 'icons/magic/movement/abstract-ribbons-red-orange.webp'
const effectName = 'Hinder'
const changes = [
{
key: 'system.stats.speed.value',
mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,
value: -2,
priority: 0
}
]
for (const token of tokens) {
const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)
const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
}
}

View File

@ -1,38 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const tokenList = tokens.map(t => t.name).join(', ')
const dialogOptions = {
title: 'Hurry',
content: `Apply <em>Hurry</em> to ${tokenList}`,
default: 'cancel',
buttons: [
{ label: 'OK', value: 'ok' },
{ label: 'Cancel', value: 'cancel' }
]
}
const choice = await warpgate.buttonDialog(dialogOptions, 'column')
if (choice === 'ok') {
await createEffect(tokens, choice)
}
}
async function createEffect (tokens, choice) {
const icon = 'icons/skills/movement/feet-winged-boots-blue.webp'
const effectName = 'Hurry'
const changes = [
{
key: 'system.stats.speed.value',
mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,
value: 2,
priority: 0
}
]
for (const token of tokens) {
const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)
const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
}
}

View File

@ -1,41 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const tokenList = tokens.map(t => t.name).join(', ')
const menuOptions = {
title: 'Intangibility',
defaultButton: 'Cancel',
options: {}
}
const menuData = {
inputs: [
{ type: 'header', label: 'Intangibility' },
{ type: 'info', label: `Apply Intangibility to ${tokenList}` },
{ type: 'checkbox', label: 'Duration', options: false }
],
buttons: [
{ label: 'Apply', value: 'apply' },
{ label: 'Cancel', value: 'cancel' }
]
}
const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)
if (buttons && buttons !== 'cancel') {
const options = {
duration: (!!inputs[2])
}
await createEffect(tokens, options)
}
}
async function createEffect (tokens, options) {
const effectName = 'Intangibility'
const duration = (options.duration ? 5 * 6 * 60 : 5)
const icon = 'icons/magic/control/debuff-energy-hold-levitate-blue-yellow.webp'
for (const token of tokens) {
const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, duration, [])
const mutateOptions = swadeMBHelpers.defaultMutationOptions('Intangibility')
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
}
}

View File

@ -1,44 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const tokenList = tokens.map(t => t.name).join(', ')
const menuOptions = {
title: 'Invisibility',
defaultButton: 'Cancel',
options: {}
}
const menuData = {
inputs: [
{ type: 'header', label: 'Invisibility' },
{ type: 'info', label: `Apply Invisibility to ${tokenList}` },
{ type: 'checkbox', label: 'Duration', options: false }
],
buttons: [
{ label: 'Apply', value: 'apply' },
{ label: 'Raise', value: 'raise' },
{ label: 'Cancel', value: 'cancel' }
]
}
const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)
if (buttons && buttons !== 'cancel') {
const options = {
raise: (buttons === 'raise'),
duration: (!!inputs[2])
}
await createEffect(tokens, options)
}
}
async function createEffect (tokens, options) {
const effectName = `${options.raise ? 'major' : 'minor'} Invisibility`
const baseEffect = CONFIG.statusEffects.find(se => se.label === 'EFFECT.StatusInvisible')
const duration = (options.duration ? 5 * 6 * 60 : 5)
for (const token of tokens) {
const mutate = swadeMBHelpers.createMutationWithEffect(baseEffect.icon, effectName, duration, [])
mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }
const mutateOptions = swadeMBHelpers.defaultMutationOptions('Invisibility')
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
}
}

View File

@ -1,32 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const tokenList = tokens.map(t => t.name).join(', ')
const dialogOptions = {
title: 'Lingering Damage',
content: `Apply <em>Lingering Damage</em> to ${tokenList}`,
default: 'cancel',
buttons: [
{ label: 'Ok', value: 'ok' },
{ label: 'Cancel', value: 'cancel' }
]
}
const choice = await warpgate.buttonDialog(dialogOptions)
if (choice === 'ok') {
await createEffect(tokens)
}
}
async function createEffect (tokens) {
const icon = 'icons/magic/acid/dissolve-arm-flesh.webp'
const effectName = 'Lingering Damage'
for (const token of tokens) {
const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 1, [])
mutate.embedded.ActiveEffect['Lingering Damage'].flags.swade.expiration =
CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnPrompt
const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
}
}

View File

@ -1,45 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const tokenList = tokens.map(t => t.name).join(', ')
const dialogOptions = {
title: 'Protection',
content: `Apply <em>Protection</em> to ${tokenList}`,
default: 'cancel',
buttons: [
{ label: 'Apply (+2 armor)', value: 'apply' },
{ label: 'Apply with raise (+2 toughness)', value: 'raise' },
{ label: 'Cancel', value: 'cancel' }
]
}
const choice = await warpgate.buttonDialog(dialogOptions)
if (choice && choice !== 'cancel') {
await createEffect(tokens, choice)
}
}
async function createEffect (tokens, choice) {
const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Protection')
const changes = [
{
key: 'system.stats.toughness.armor',
mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE,
value: 2,
priority: 0
}
]
let effectName = 'minor Protection'
if (choice === 'raise') {
changes[0].key = 'system.stats.toughness.value'
effectName = 'major Protection'
}
for (const token of tokens) {
const mutate = swadeMBHelpers.createMutationWithEffect(
baseEffect.icon, effectName, 5, changes)
mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }
const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
}
}

39
macros/quickDamage.js Normal file
View File

@ -0,0 +1,39 @@
new Dialog({
title: 'Damage Roll Configuration',
content: `
<form>
<div class="form-group">
<label>Damage Roll:</label>
<input type="text" name="damageRoll" value="2d4x" />
</div>
<div class="form-group">
<label>AP:</label>
<input type="number" name="ap" value="0" />
</div>
<div class="form-group">
<label>Flavor:</label>
<input type="text" name="flavor" value="" />
</div>
</form>
`,
buttons: {
ok: {
label: 'Roll Damage',
callback: (html) => {
const damageRoll = html.find('input[name="damageRoll"]').val()
let flavor = html.find('input[name="flavor"]').val()
const ap = parseInt(html.find('input[name="ap"]').val()) || 0
const options = {}
if (ap > 0) {
flavor = `${flavor ? flavor + ' - ' : ''}AP: ${ap}`
options.ap = ap
}
// Perform the damage roll and send the message
new CONFIG.Dice.DamageRoll(damageRoll, null, options).toMessage({ flavor })
}
},
cancel: {
label: 'Cancel'
}
}
}).render(true)

View File

@ -1,58 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const tokenList = tokens.map(t => t.name).join(', ')
const dialogOptions = {
title: 'Shroud',
content: `Apply <em>Shroud</em> to ${tokenList}`,
default: 'cancel',
buttons: [
{ label: 'OK', value: 'ok' },
{ label: 'Mutate token lighting', value: 'mutate' },
{ label: 'Cancel', value: 'cancel' }
]
}
const choice = await warpgate.buttonDialog(dialogOptions)
if (choice === 'ok' || choice === 'mutate') {
await createEffect(tokens, choice)
}
}
async function createEffect (tokens, choice) {
const icon = 'icons/magic/perception/silhouette-stealth-shadow.webp'
const effectName = 'Shroud'
for (const token of tokens) {
const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])
const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
if (choice === 'mutate') {
const mutate2 = {
token: {
light: {
alpha: 0.5,
angle: 360,
attenuation: 0.1,
animation: {
intensity: 5,
reverse: false,
speed: 5,
type: 'roiling'
},
bright: 0,
color: null,
coloration: 0,
contrast: 0,
dim: 0.1,
luminosity: -0.15,
saturation: 0,
shadows: 0.25
}
}
}
mutateOptions.permanent = false
await warpgate.mutate(token.document, mutate2, {}, mutateOptions)
}
}
}

View File

@ -1,74 +0,0 @@
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const tokenList = tokens.map(t => t.name).join(', ')
const menuOptions = {
title: 'Smite',
defaultButton: 'Cancel',
options: {}
}
const menuData = {
inputs: [
{ type: 'header', label: 'Smite' },
{ type: 'info', label: `Apply Smite to ${tokenList}` },
{ type: 'checkbox', label: 'Greater', options: false }
],
buttons: [
{ label: 'Apply', value: 'apply' },
{ label: 'Apply with Raise', value: 'raise' },
{ label: 'Cancel', value: 'cancel' }
]
}
const tokenWeapons = {}
let index = 2
for (const token of tokens) {
index += 2
tokenWeapons[token.id] = index
menuData.inputs.push({ type: 'info', label: `<h2>${token.name}</h2>` })
const weapons = token.actor.items.filter(i => i.type === 'weapon').map(
i => { return { value: i.name, html: i.name } })
weapons.unshift({ value: '', html: '<i>None</i>' })
menuData.inputs.push({ type: 'select', label: token.name, options: weapons })
}
const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)
for (const tokenId in tokenWeapons) {
tokenWeapons[tokenId] = inputs[tokenWeapons[tokenId]]
}
const greater = (inputs[2] === 'Greater')
if (buttons && buttons !== 'cancel') {
await createEffect(tokens, tokenWeapons, buttons, greater)
}
}
async function createEffect (tokens, tokenWeapons, choice, greater) {
const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Smite')
const effectIcon = baseEffect.icon
let changeValue = (choice === 'raise' ? '+4' : '+2')
if (greater) {
changeValue = (choice === 'raise' ? '+6' : '+4')
}
for (const token of tokens) {
const weaponName = tokenWeapons[token.id]
const weaponId = token.actor.items.getName(weaponName)?.id
const changeKey = `@Weapon{${weaponName}}[system.damage]`
if (!weaponId) {
continue
}
const effectName = `${choice === 'raise' ? 'major' : 'minor'} Smite${greater ? '(greater)' : ''} (${weaponName})`
const changes = [
{
key: changeKey,
mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,
value: changeValue,
priority: 0
}
]
const mutate = swadeMBHelpers.createMutationWithEffect(
effectIcon, effectName, 5, changes)
mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }
const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)
await warpgate.mutate(token.document, mutate, {}, mutateOptions)
}
}

View File

@ -1,74 +0,0 @@
const ACTORFOLDER = 'Summonables'
const SUMMONICON = 'icons/magic/symbols/runes-star-orange.webp'
swadeMBHelpers.runOnTargetOrSelectedTokens(main)
async function main (tokens) {
const token = tokens[0]
const tokenList = token.name
const folder = swadeMBHelpers.getActorFolderByPath(ACTORFOLDER)
const actors = swadeMBHelpers.getActorsInFolder(folder)
const menuOptions = {
title: 'Summon Creature',
defaultButton: 'cancel',
options: {}
}
const menuData = {
inputs: [
{ type: 'header', label: 'Summon Creature' },
{ type: 'info', label: `${tokenList} is summoning` },
{
type: 'select',
label: 'Ally to summon',
options: Object.keys(actors).sort().map(k => { return { value: actors[k].id, html: k } })
},
{ type: 'number', label: 'Number to spawn (+half base cost per)', options: 1 }
],
buttons: [
{ label: 'Apply', value: 'apply' },
{ label: 'Apply with raise', value: 'raise' },
{ label: 'Cancel', value: 'cancel' }
]
}
const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)
if (buttons && buttons !== 'cancel') {
const summonData = {
raise: (buttons === 'raise'),
actorId: inputs[2],
number: inputs[3]
}
summonData.actor = game.actors.get(summonData.actorId)
summonData.actorName = summonData.actor.name
summonData.icon = summonData.actor.prototypeToken.texture.src
summonData.token = summonData.actor.prototypeToken
doWork(summonData, token)
}
}
async function doWork (summonData, token) {
console.log('Summon ', token, summonData)
const effectName = `Summoned ${summonData.actorName} (${summonData.number})`
const tokenEffectMutation = swadeMBHelpers.createMutationWithEffect(SUMMONICON, effectName, 5, [])
const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)
await warpgate.mutate(token.document, tokenEffectMutation, {}, mutateOptions)
const spawnOptions = {
controllingActor: token.actor,
duplicates: summonData.number,
comparisonKeys: { ActiveEffect: 'label' },
crosshairs: {
icon: summonData.icon,
label: `Summon ${summonData.actorName}`,
drawOutline: false,
rememberControlled: true
}
}
const spawnMutation = {
token: {
actorLink: false,
name: `${token.name}'s ${summonData.token.name}`
}
}
await warpgate.spawn(summonData.actorName, spawnMutation, {}, spawnOptions)
}

Binary file not shown.

Binary file not shown.

View File

@ -1 +1 @@
MANIFEST-000356
MANIFEST-000002

View File

@ -1,3 +1,5 @@
2023/12/18-12:05:43.940479 7fce577fe700 Recovering log #354
2023/12/18-12:05:43.960190 7fce577fe700 Delete type=0 #354
2023/12/18-12:05:43.960210 7fce577fe700 Delete type=3 #352
2023/12/18-15:37:09.644182 7f63a67bd700 Delete type=3 #1
2023/12/18-15:37:09.646809 7f63a5542700 Level-0 table #5: started
2023/12/18-15:37:09.654066 7f63a5542700 Level-0 table #5: 11401 bytes OK
2023/12/18-15:37:09.663437 7f63a5542700 Delete type=0 #3
2023/12/18-15:37:09.663538 7f63a5542700 Manual compaction at level-0 from '!folders!0nDRFmMBs5DBJU9M' @ 72057594037927935 : 1 .. '!items!xA7qKMmugJv7z6j1' @ 0 : 0; will stop at (end)

View File

@ -1,8 +0,0 @@
2023/12/17-21:54:41.311951 7fa92bfff700 Recovering log #350
2023/12/17-21:54:41.319557 7fa92bfff700 Delete type=3 #348
2023/12/17-21:54:41.319574 7fa92bfff700 Delete type=0 #350
2023/12/18-00:47:25.700106 7fa92a3f0700 Level-0 table #355: started
2023/12/18-00:47:25.700130 7fa92a3f0700 Level-0 table #355: 0 bytes OK
2023/12/18-00:47:25.708833 7fa92a3f0700 Delete type=0 #353
2023/12/18-00:47:25.718045 7fa92a3f0700 Manual compaction at level-0 from '!folders!0nDRFmMBs5DBJU9M' @ 72057594037927935 : 1 .. '!items!xA7qKMmugJv7z6j1' @ 0 : 0; will stop at (end)
2023/12/18-00:47:25.733637 7fa92a3f0700 Manual compaction at level-1 from '!folders!0nDRFmMBs5DBJU9M' @ 72057594037927935 : 1 .. '!items!xA7qKMmugJv7z6j1' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

View File

@ -1 +1 @@
MANIFEST-000006
MANIFEST-000002

View File

@ -1,3 +1,5 @@
2023/12/18-12:05:44.063624 7f8a68cfb700 Recovering log #4
2023/12/18-12:05:44.092055 7f8a68cfb700 Delete type=3 #2
2023/12/18-12:05:44.092083 7f8a68cfb700 Delete type=0 #4
2023/12/18-15:37:12.778941 7fed4efbf700 Delete type=3 #1
2023/12/18-15:37:12.781115 7fed4cfbb700 Level-0 table #5: started
2023/12/18-15:37:12.803917 7fed4cfbb700 Level-0 table #5: 6787 bytes OK
2023/12/18-15:37:12.812861 7fed4cfbb700 Delete type=0 #3
2023/12/18-15:37:12.812959 7fed4cfbb700 Manual compaction at level-0 from '!items!JWyBQe4tnOYljFAF' @ 72057594037927935 : 1 .. '!items!tWWSfEMmLmws6Yb1' @ 0 : 0; will stop at (end)

View File

@ -1,5 +0,0 @@
2023/12/18-11:55:17.263220 7f822affd700 Delete type=3 #1
2023/12/18-11:55:17.265600 7f822a583700 Level-0 table #5: started
2023/12/18-11:55:17.272736 7f822a583700 Level-0 table #5: 6787 bytes OK
2023/12/18-11:55:17.281677 7f822a583700 Delete type=0 #3
2023/12/18-11:55:17.281771 7f822a583700 Manual compaction at level-0 from '!items!JWyBQe4tnOYljFAF' @ 72057594037927935 : 1 .. '!items!tWWSfEMmLmws6Yb1' @ 0 : 0; will stop at (end)

BIN
packs/gear/MANIFEST-000002 Normal file

Binary file not shown.

Binary file not shown.

View File

@ -1 +1 @@
MANIFEST-000251
MANIFEST-000002

View File

@ -1,3 +1,5 @@
2023/12/18-12:05:44.190837 7f21c2ffd700 Recovering log #249
2023/12/18-12:05:44.212114 7f21c2ffd700 Delete type=3 #247
2023/12/18-12:05:44.212136 7f21c2ffd700 Delete type=0 #249
2023/12/18-15:37:14.322677 7f3e267fc700 Delete type=3 #1
2023/12/18-15:37:14.324789 7f3e25ffb700 Level-0 table #5: started
2023/12/18-15:37:14.331866 7f3e25ffb700 Level-0 table #5: 1751 bytes OK
2023/12/18-15:37:14.340858 7f3e25ffb700 Delete type=0 #3
2023/12/18-15:37:14.340981 7f3e25ffb700 Manual compaction at level-0 from '!actors!U5v4gFHquo0Y1SAq' @ 72057594037927935 : 1 .. '!actors!U5v4gFHquo0Y1SAq' @ 0 : 0; will stop at (end)

View File

@ -1,8 +0,0 @@
2023/12/17-21:54:41.321169 7fa92affd700 Recovering log #245
2023/12/17-21:54:41.329240 7fa92affd700 Delete type=0 #245
2023/12/17-21:54:41.329262 7fa92affd700 Delete type=3 #243
2023/12/18-00:47:25.708908 7fa92a3f0700 Level-0 table #250: started
2023/12/18-00:47:25.709018 7fa92a3f0700 Level-0 table #250: 0 bytes OK
2023/12/18-00:47:25.717936 7fa92a3f0700 Delete type=0 #248
2023/12/18-00:47:25.718070 7fa92a3f0700 Manual compaction at level-0 from '!actors!U5v4gFHquo0Y1SAq' @ 72057594037927935 : 1 .. '!actors!U5v4gFHquo0Y1SAq' @ 0 : 0; will stop at (end)
2023/12/18-00:47:25.733666 7fa92a3f0700 Manual compaction at level-1 from '!actors!U5v4gFHquo0Y1SAq' @ 72057594037927935 : 1 .. '!actors!U5v4gFHquo0Y1SAq' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1 +1 @@
MANIFEST-000382
MANIFEST-000002

View File

@ -1,3 +1,5 @@
2023/12/18-12:05:44.309941 7f35927fc700 Recovering log #380
2023/12/18-12:05:44.330564 7f35927fc700 Delete type=3 #378
2023/12/18-12:05:44.330586 7f35927fc700 Delete type=0 #380
2023/12/18-15:37:18.058346 7f04d3fff700 Delete type=3 #1
2023/12/18-15:37:18.060818 7f04d1d82700 Level-0 table #5: started
2023/12/18-15:37:18.070119 7f04d1d82700 Level-0 table #5: 10218 bytes OK
2023/12/18-15:37:18.078948 7f04d1d82700 Delete type=0 #3
2023/12/18-15:37:18.079042 7f04d1d82700 Manual compaction at level-0 from '!folders!hIbrWxg1nDutCSwt' @ 72057594037927935 : 1 .. '!macros!wU2mAUnw3RW9qMT8' @ 0 : 0; will stop at (end)

View File

@ -1,8 +0,0 @@
2023/12/17-21:54:41.302864 7fa92affd700 Recovering log #376
2023/12/17-21:54:41.310384 7fa92affd700 Delete type=3 #374
2023/12/17-21:54:41.310412 7fa92affd700 Delete type=0 #376
2023/12/18-00:47:25.690528 7fa92a3f0700 Level-0 table #381: started
2023/12/18-00:47:25.690551 7fa92a3f0700 Level-0 table #381: 0 bytes OK
2023/12/18-00:47:25.700027 7fa92a3f0700 Delete type=0 #379
2023/12/18-00:47:25.718020 7fa92a3f0700 Manual compaction at level-0 from '!folders!hIbrWxg1nDutCSwt' @ 72057594037927935 : 1 .. '!macros!wU2mAUnw3RW9qMT8' @ 0 : 0; will stop at (end)
2023/12/18-00:47:25.733607 7fa92a3f0700 Manual compaction at level-1 from '!folders!hIbrWxg1nDutCSwt' @ 72057594037927935 : 1 .. '!macros!wU2mAUnw3RW9qMT8' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View File

@ -1 +1 @@
MANIFEST-000380
MANIFEST-000002

View File

@ -1,3 +1,5 @@
2023/12/18-12:05:44.432285 7f8c15fbf700 Recovering log #377
2023/12/18-12:05:44.452354 7f8c15fbf700 Delete type=3 #375
2023/12/18-12:05:44.452375 7f8c15fbf700 Delete type=0 #377
2023/12/18-15:37:20.266975 7f00037bf700 Delete type=3 #1
2023/12/18-15:37:20.269045 7f0001542700 Level-0 table #5: started
2023/12/18-15:37:20.276064 7f0001542700 Level-0 table #5: 9796 bytes OK
2023/12/18-15:37:20.285028 7f0001542700 Delete type=0 #3
2023/12/18-15:37:20.285119 7f0001542700 Manual compaction at level-0 from '!journal!HbtPlHNFO1L6RVj0' @ 72057594037927935 : 1 .. '!journal.pages!YSuk1v59tLaL9XUK.BlDoYgdTxhyCBP3Y' @ 0 : 0; will stop at (end)

View File

@ -1,15 +0,0 @@
2023/12/17-21:54:41.293906 7fa92bfff700 Recovering log #373
2023/12/17-21:54:41.301255 7fa92bfff700 Delete type=0 #373
2023/12/17-21:54:41.301270 7fa92bfff700 Delete type=3 #371
2023/12/18-00:47:25.674406 7fa92a3f0700 Level-0 table #378: started
2023/12/18-00:47:25.681673 7fa92a3f0700 Level-0 table #378: 1126 bytes OK
2023/12/18-00:47:25.690462 7fa92a3f0700 Delete type=0 #376
2023/12/18-00:47:25.717980 7fa92a3f0700 Manual compaction at level-0 from '!journal!HbtPlHNFO1L6RVj0' @ 72057594037927935 : 1 .. '!journal.pages!YSuk1v59tLaL9XUK.BlDoYgdTxhyCBP3Y' @ 0 : 0; will stop at (end)
2023/12/18-00:47:25.718095 7fa92a3f0700 Manual compaction at level-1 from '!journal!HbtPlHNFO1L6RVj0' @ 72057594037927935 : 1 .. '!journal.pages!YSuk1v59tLaL9XUK.BlDoYgdTxhyCBP3Y' @ 0 : 0; will stop at '!journal.pages!YSuk1v59tLaL9XUK.BlDoYgdTxhyCBP3Y' @ 237 : 1
2023/12/18-00:47:25.718101 7fa92a3f0700 Compacting 1@1 + 1@2 files
2023/12/18-00:47:25.724568 7fa92a3f0700 Generated table #379@1: 14 keys, 9134 bytes
2023/12/18-00:47:25.724576 7fa92a3f0700 Compacted 1@1 + 1@2 files => 9134 bytes
2023/12/18-00:47:25.733464 7fa92a3f0700 compacted to: files[ 0 0 1 0 0 0 0 ]
2023/12/18-00:47:25.733517 7fa92a3f0700 Delete type=2 #370
2023/12/18-00:47:25.733560 7fa92a3f0700 Delete type=2 #378
2023/12/18-00:47:25.733678 7fa92a3f0700 Manual compaction at level-1 from '!journal.pages!YSuk1v59tLaL9XUK.BlDoYgdTxhyCBP3Y' @ 237 : 1 .. '!journal.pages!YSuk1v59tLaL9XUK.BlDoYgdTxhyCBP3Y' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

View File

@ -175,6 +175,45 @@
"lastModifiedBy": "sVoCvBU1knmXzoYe"
},
"_key": "!journal.pages!Mw1g2Fx5dp4SoqVP.NgwdcyoMzYFc8VOM"
},
{
"sort": -100000,
"name": "Quick Damage Roll",
"type": "text",
"title": {
"show": true,
"level": 1
},
"image": {},
"text": {
"format": 1,
"content": "<p>The Quick Damage Roll macro will a dialog to configure a damage roll, with its chat card and Apply Damage button, for cases where it's not worth creating an actor, token, and action for a single roll.</p>"
},
"video": {
"controls": true,
"volume": 0.5
},
"src": null,
"system": {},
"ownership": {
"default": -1,
"sVoCvBU1knmXzoYe": 3
},
"flags": {
"core": {
"sourceId": "Compendium.swade-mb-helpers.module-docs.JournalEntry.Mw1g2Fx5dp4SoqVP.JournalEntryPage.8OcZYeZTJWqJpeBs"
}
},
"_stats": {
"systemId": "swade",
"systemVersion": "3.2.5",
"coreVersion": "11.315",
"createdTime": 1702934117575,
"modifiedTime": 1702934796555,
"lastModifiedBy": "sVoCvBU1knmXzoYe"
},
"_id": "ruuxf72hwlcRzymt",
"_key": "!journal.pages!Mw1g2Fx5dp4SoqVP.ruuxf72hwlcRzymt"
}
],
"flags": {
@ -187,7 +226,7 @@
"systemVersion": "3.2.5",
"coreVersion": "11.315",
"createdTime": 1678169291843,
"modifiedTime": 1702859968781,
"modifiedTime": 1702934832358,
"lastModifiedBy": "sVoCvBU1knmXzoYe"
},
"_id": "Mw1g2Fx5dp4SoqVP",