Skip to content

Instantly share code, notes, and snippets.

@Adjective-Object
Last active February 13, 2022 20:15
Show Gist options
  • Save Adjective-Object/f32232552f2c91772f4ba9f9969b2087 to your computer and use it in GitHub Desktop.
Save Adjective-Object/f32232552f2c91772f4ba9f9969b2087 to your computer and use it in GitHub Desktop.
Foundry VTT Attack with Item Macro
if (!window.__lastKnownValuesForMaxMacro) {
window.__lastKnownValuesForMaxMacro = {}
}
lastKnown = window.__lastKnownValuesForMaxMacro
let additionalEffects = {
sneak: {
name: "Sneak Attack",
img: "icons/skills/melee/strike-dagger-arcane-pink.webp"
},
bless: {
name: "Blessed",
img: "systems/dnd5e/icons/spells/haste-sky-1.jpg"
},
advantage: {
name: "Advantage",
img: "icons/vtt-512.png"
},
}
let userActor = game.users.get(game.userId).character
if (!userActor) {
ChatMessage.create({whisper: [game.userId], content:"your user has no actor? something is busted.", speaker:{alias: "macro"}})
} else {
let userAttackItems = Array.from(userActor.items.entries()).filter(([_,item]) => item.hasAttack)
console.log(userActor, userAttackItems);
let d = new Dialog({
title: 'Basic Attack',
jQuery: false,
content: `
<form id="custom-attack-form">
<fieldset style="display:flex; flex-direction: column; align-items: stretch">
<legend>Weapon</legend>
${
userAttackItems.map(([itemId, item]) =>
`
<div style="max-height: 2em; margin: 0.2em; display:flex">
<input type="radio" id="mod_it_${itemId}" data-item-id="${itemId}" name="SelectedItemId" value=${itemId}${itemId == lastKnown.selectedItemId ? ' checked' : ''}/>
<label for="mod_it_${itemId}" style="display: block; flex-grow: 1">
<img style="height: 2em; max-width:2em" src="${item.img}"/>
${item.name}
</label>
</div>
`
).join('\n')
}
</fieldset>
<fieldset>
<legend>Additional Effects</legend>
${Object.entries(additionalEffects).map(([id, eff]) => {
return `<div style="display: flex; justify-content: stretch">
<input type="checkbox" id="mod_${id}" name="${id}" value="${id}" ${lastKnown[id] == true ? 'checked' : ''}>
<label for="mod_${id}" style="display:block; flex-grow: 1">
<img style="height: 2em; max-width:2em" src="${eff.img}"/>
${eff.name}
</label>
</div>`
}).join('\n')}
</fieldset>
<div style="display:flex">
<button class="maxsmod mod-attack">Hit</button>
<button class="maxsmod mod-damage">Damage</button>
</div>
</form>
`,
buttons: {},
render: ([renderedHtml]) => {
renderedHtml.addEventListener('change', (e) => {
lastKnown.selectedItemId = renderedHtml.querySelector('#custom-attack-form input[name="SelectedItemId"]:checked').getAttribute('data-item-id')
for ([id, eff] of Object.entries(additionalEffects)) {
lastKnown[id] = renderedHtml.querySelector(`#mod_${id}`).checked
}
})
function isEffect(id) {
return renderedHtml.querySelector(`#mod_${id}`).checked
}
renderedHtml.addEventListener('click', (e) => {
if (e.target.matches("button.maxsmod")) {
let checkedItemId = renderedHtml.querySelector('#custom-attack-form input[name="SelectedItemId"]:checked').getAttribute('data-item-id')
console.log('checkedItemId', checkedItemId)
let checkedItem = userActor.items.get(checkedItemId)
let messageDetails = checkedItem.name
let rollFormula;
let rollType
if (e.target.matches('.mod-attack')) {
rollType = "To Hit"
rollFormula = isEffect("advantage") ? "1d20kh" : "1d20" + (checkedItem.labels.toHit || '')
if (isEffect("bless")) {
rollFormula += " + 1d4"
messageDetails += " + Bless"
};
} else if (e.target.matches('.mod-damage')) {
rollType = "Damage"
rollFormula = checkedItem.labels.damage
if (isEffect("advantage") ) {
rollFormula = `{${rollFormula}}kh`
}
rollFormula = `(${rollFormula})`
if (isEffect("sneak")) {
rollFormula += " + (ceil(@classes.rogue.levels /2))d6"
messageDetails += " + Sneak Attack"
};
} else {
console.error("got weird click event",e )
}
let messageImg = `<img style="float:left; margin-right: 0.5em; height: 2em; max-width:2em" src="${checkedItem.img}"/> `
new Roll(rollFormula, userActor.data.data).toMessage({
flavor: messageImg + rollType + ': ' + messageDetails // + "<br>" + rollFormula
})
}
})
},
}).render(true, {
width: 150
})
}
@Adjective-Object
Copy link
Author

Adjective-Object commented Feb 13, 2022

Super insecure macro for foundry VTT to attack with an item

Vulnerable to html injection attacks just by writing a special name since it uses script templating, so don't run on any untrusted data

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment