From d166be4f13b2cc95f454b0cfe6ef7360e894b9c6 Mon Sep 17 00:00:00 2001 From: napolitanod Date: Fri, 7 Jul 2023 20:54:01 -0700 Subject: [PATCH] 1.2.3 --- module.json | 4 +-- scripts/constants.js | 1 + scripts/index.js | 6 +++-- scripts/workflow.js | 61 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 66 insertions(+), 6 deletions(-) diff --git a/module.json b/module.json index 70dd6b8..11b631d 100644 --- a/module.json +++ b/module.json @@ -30,8 +30,8 @@ "styles/napolitano-scripts.css" ], "title": "_Napolitano Scripts", - "version": "1.2.2", + "version": "1.2.3", "url": "https://github.com/napolitanod/napolitano-scripts", "manifest": "https://raw.githubusercontent.com/napolitanod/napolitano-scripts/master/module.json", - "download": "https://github.com/napolitanod/napolitano-scripts/releases/download/1.2.2/module.zip" + "download": "https://github.com/napolitanod/napolitano-scripts/releases/download/1.2.3/module.zip" } \ No newline at end of file diff --git a/scripts/constants.js b/scripts/constants.js index 5949c31..e9b0b8c 100644 --- a/scripts/constants.js +++ b/scripts/constants.js @@ -824,6 +824,7 @@ export const CONFIGS = [ {id:"hex", name:"Hex"}, {id:"hexblades-curse", name:"Hexblade's Curse"}, {id:"hungry-jaws", name:"Hungry Jaws"}, + {id:"interception", name:"Interception"}, {id:"intrusive-echoes", name:"Intrusive Echoes"}, {id:"mirror-image", name:"Mirror Image"}, {id:"motivational-speech", name:"Motivational Speech"}, diff --git a/scripts/index.js b/scripts/index.js index a21c601..6d80f5c 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -112,7 +112,6 @@ Hooks.once('ready', async function() { HOOKIDS['renderTokenActionHud'] = Hooks.on('renderTokenActionHud', async function(hud, html, options = {}){ //const token = canvas.scene.tokens.find(t => t.id === options.actions?.tokenId) const token = hud?.token?.document - console.log(token) if(!token) return html = setHudHelp(html, token) html = buildHud(html, token) @@ -222,7 +221,8 @@ Hooks.once("midi-qol.midiReady", () => { //wraps damage, do last if(game.settings.get("napolitano-scripts", "rayOfEnfeeblement")) results.push(workflow.playAsync('rayOfEnfeeblement', data, {hook: hook})) if(game.settings.get("napolitano-scripts", "cutting-words")) results.push(workflow.playAsync('cuttingWords', data, {hook: hook})) - if(game.settings.get("napolitano-scripts", "parry")) results.push(workflow.playAsync('parry', data, {hook: hook})) + if(game.settings.get("napolitano-scripts", "parry")) results.push(workflow.playAsync('parry', data, {hook: hook})) + if(game.settings.get("napolitano-scripts", "interception")) results.push(workflow.playAsync('interception', data, {hook: hook})) await Promise.all(results) }); @@ -422,6 +422,7 @@ HOOKIDS['createActiveEffect'] = Hooks.on("createActiveEffect", async (data, chan switch(data.name){ case "Cloak of Flies": workflow.play('cloakOfFlies', data, {hook: hook, activeEffectDelete: false}); break; case "Spirit Guardians": workflow.play('spiritGuardians', data, {hook: hook, activeEffectDelete: false}); break; + case "Rage": workflow.play('totemSpiritBear', data, {hook: hook, activeEffectDelete: false}); break; } } } @@ -448,6 +449,7 @@ HOOKIDS['deleteActiveEffect'] = Hooks.on("deleteActiveEffect", async (data, opti case "Dragon's Breath": workflow.play('dragonsBreath', data, {hook: hook, activeEffectDelete: true}); break; case "Mirror Image": workflow.playAsync('mirrorImage', data, {hook: hook, activeEffectDelete: true}); break; case "Spirit Guardians": workflow.play('spiritGuardians', data, {hook: hook, activeEffectDelete: true}); break; + case "Rage": workflow.play('totemSpiritBear', data, {hook: hook, activeEffectDelete: true}); break; case 'Torch': workflow.play('torch', data, {hook: hook, activeEffectDelete: true}); break; } } diff --git a/scripts/workflow.js b/scripts/workflow.js index d8f1796..91f6c04 100644 --- a/scripts/workflow.js +++ b/scripts/workflow.js @@ -1528,6 +1528,7 @@ export class workflow extends framework { case 'counterspell': await flow._counterspell(); break; case 'cuttingWords': await flow._cuttingWords(); break; case 'eldritchBlast': await flow._eldritchBlast(); break; + case 'interception': await flow._interception(); break; case 'geniesWrath': await flow._geniesWrath(); break; case 'guidedStrike': await flow._guidedStrike(); break; case 'magicMissile': await flow._magicMissile(); break; @@ -1612,6 +1613,7 @@ export class workflow extends framework { case 'toggleEffectEffects': flow._toggleEffectEffects(); break; case 'tokenMovement': flow._tokenMovement(); break; case 'torch': flow._torch(); break; + case 'totemSpiritBear': flow._totemSpiritBear(); break; case 'whisperingAura': flow._whisperingAura(); break; case 'wildSurgeRetribution': flow._wildSurgeRetribution(); break; case 'witchBolt': flow._witchBolt(); break; @@ -2481,6 +2483,47 @@ export class workflow extends framework { } } + async _interception(){ + const originalRollTotal = this.data.damageRoll?.total ?? 0 + if(!this.itemData.isAttack || !originalRollTotal) return + const results = [] + for(const pl of canvas.tokens.placeables) { + this.hasItem({document: pl, itemName: 'Fighting Style: Interception'}) + , this.isResponsive(pl) + , this.hasEffect(pl, 'Fighting Style: Interception') + , !this.hasEffect(pl, 'Reaction') + , !this.source.token.id === pl.id + } + this.interceptors = canvas.tokens.placeables.filter(t => + this.hasItem({document: t, itemName: 'Fighting Style: Interception'}) + && this.isResponsive(t) + && this.hasEffect(t, 'Fighting Style: Interception') + && !this.hasEffect(t, 'Reaction') + && !this.source.token.id === t.id + ) + if(!this.interceptors.length) return + for(const token of this.interceptors) { + this.tokensInProximity(token, 5) + if(this.proximityTokens.find(h => h.id !== token.id && this.firstHitTarget.id === h.id && h.disposition === token.disposition)){ + results.push(this.yesNo({title: 'Interception', prompt: `The damage is ${originalRollTotal}. Will ${token.name} use Interception to roll a superiority die and reduce the amount by that roll (you must be able to see the attacker)?`, owner: getActorOwner(token), document: token, img: this.getItem('Fighting Style: Interception', token)?.img})) + } + } + if(results.length){ + await Promise.all(results).then(async (values)=>{ + for (const value of values){ + if(value.yes){ + const roll = await this.rollDice(`1d10`) + const mod = value.document.actor.system.attributes.prof + await this.appendRoll(this.data.damageRoll, roll, {sign: -1, isDamage: true, mod: mod}) + this.message(`${value.document.name} uses Interception, reducing the damage dealt of ${originalRollTotal} by ${roll.total + mod}.`, {title: "Interception"}) + this.appendMessageMQ(`-${roll.total + mod} to damage due to Interception.`) + this.addActiveEffect({effectName: 'Reaction', uuid: value.document.actor.uuid, origin: value.document.actor.uuid}) + } + } + }) + } + } + /** * Tested: v10 * Rolls Intrusive Echoes table (on 1) @@ -2782,8 +2825,8 @@ export class workflow extends framework { const useRadiantSoul = await this.yesNo({img: item.img}) if(useRadiantSoul){ await this.setFlag(this.source.actor, {'radiantSoul': this.now}) - await this.damage({type: 'radiant', dice: `${this.sourceData.prof}d1`, targets: [this.firstTarget], show: false}) - this.message( `${this.name} uses Radiant Soul to deal ${this.sourceData.prof} radiant damage`, {title: 'Radiant Soul'}) + await this.damage({type: 'radiant', dice: `${this.sourceData.level}d1`, targets: [this.firstTarget], show: false}) + this.message( `${this.name} uses Radiant Soul to deal ${this.sourceData.level} radiant damage`, {title: 'Radiant Soul'}) this.generateEffect(this.firstTarget) } } @@ -2989,6 +3032,20 @@ export class workflow extends framework { break; } } + + async _totemSpiritBear(){ + const eff = "Totem Spirit: Bear" + if(this.hasItem({itemName: eff, document: this.source.actor})){ + switch(this.hook){ + case 'deleteActiveEffect': + if(this.hasEffect(this.source.actor, eff)) await this.deleteEffect(this.source.actor, eff) + break; + case 'createActiveEffect': + if(!this.hasEffect(this.source.actor, eff)) await this.addActiveEffect({effectName: eff, uuid: this.source.actor.uuid, origin: this.source.actor.uuid}) + break; + } + } + } /** * Tested: v10