Skip to content

Commit

Permalink
Merge pull request #38 from napolitanod/1.2.4
Browse files Browse the repository at this point in the history
1.2.4
  • Loading branch information
napolitanod authored Nov 4, 2023
2 parents 70c196d + 3cb729b commit f981de1
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 7 deletions.
4 changes: 2 additions & 2 deletions module.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
"styles/napolitano-scripts.css"
],
"title": "_Napolitano Scripts",
"version": "1.2.3",
"version": "1.2.4",
"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.3/module.zip"
"download": "https://github.com/napolitanod/napolitano-scripts/releases/download/1.2.4/module.zip"
}
47 changes: 46 additions & 1 deletion scripts/constants.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
export async function getMonsterType(type, cr = 999){
const pack = game.packs.get("napolitano-compendium.napolitano-monsters");
const data = await pack.getDocuments(); //await pack.getData()
const monsters = data.filter(a => a.system.details?.type?.value === type && a.system.details?.cr <= cr)
return {list: monsters, options: monsters.map(c => [c.id, c.name + ' (CR ' + c.system.details?.cr + ')']).sort(([,a],[,b]) => a.localeCompare(b))}
}

export function setConfigs(){
DAMAGERESISTANTTYPES.push(...Object.entries(game.dnd5e.config.damageResistanceTypes).sort(([,a],[,b]) => a.localeCompare(b)))
DAMAGETYPES.push(...Object.entries(game.dnd5e.config.damageTypes).sort(([,a],[,b]) => a.localeCompare(b)))
Expand Down Expand Up @@ -534,6 +541,10 @@ export const NAPOLITANOCONFIG = {
name: "Magical Tinkering",
options: [`Light: External Object`, 'Light: On Self', 'Light: On Target', 'Other: External Object', 'Other'],
},
manifestEcho: {
effects:{pre: {file: 'modules/jb2a_patreon/Library/Generic/Smoke/SmokePuff01_02_Regular_Grey_400x400.webm', scale: 1.25}},
name: "Echo Knight"
},
melfsMinuteMeteors : {
item: {
compendium: "Napolitano Items",
Expand Down Expand Up @@ -579,6 +590,10 @@ export const NAPOLITANOCONFIG = {
name: "Pass without Trace",
effects: {pre: {file: 'modules/jb2a_patreon/Library/Generic/Smoke/SmokePuff01_03_Regular_Grey_400x400.webm', scale: 1}}
},
polymorph: {
name: "Polymorpth",
prompt: "Choose a beast to polymorph the target into."
},
potentSpellcasting: {
effects: {pre: {file: 'modules/jb2a_patreon/Library/Generic/Explosion/Explosion_03_Regular_GreenOrange_400x400.webm', scale: 1, wait: 100}},
name: "Potent Spellcasting"
Expand Down Expand Up @@ -832,6 +847,7 @@ export const CONFIGS = [
{id:"necrotic-shroud", name:"Necrotic Shroud"},
{id:"pack-tactics", name:"Pack Tactics"},
{id:"parry", name:"Parry"},
{id:"polymorph", name:"Polymorph"},
{id:"potent-spellcasting", name:"Potent Spellcasting"},
{id:"precision-attack", name:"Precision Attack"},
{id:"radiant-soul", name:"Radiant Soul"},
Expand Down Expand Up @@ -864,6 +880,8 @@ export const LINKDATA = [
{item: 'Channel Divinity: Radiance of the Dawn', resources: LINKDATACATEGORIES.divinity, matchOn: "feat", retrieve: "feat", amount: 1},
{item: 'Channel Divinity: Guided Strike', resources: LINKDATACATEGORIES.divinity, matchOn: "feat", retrieve: "feat", amount: 1},
{item: 'Channel Divinity: Turn Undead', resources: LINKDATACATEGORIES.divinity, matchOn: "feat", retrieve: "feat", amount: 1},
{item: 'Channel Divinity: Champion Challenge', resources: LINKDATACATEGORIES.divinity, matchOn: "feat", retrieve: "feat", amount: 1},
{item: 'Channel Divinity: Turn the Tide', resources: LINKDATACATEGORIES.divinity, matchOn: "feat", retrieve: "feat", amount: 1},
{item: 'Harness Divine Power', resources: LINKDATACATEGORIES.divinity, matchOn: "feat", retrieve: "feat", amount: 1},
{item: 'Maneuvers: Parry', resources: LINKDATACATEGORIES.superiority, matchOn: "feat", retrieve: "feat", amount: 1},
{item: 'Maneuvers: Precision Attack', resources: LINKDATACATEGORIES.superiority, matchOn: "feat", retrieve: "feat", amount: 1},
Expand All @@ -884,6 +902,15 @@ export const LINKDATA = [
]

export const SPIRITUALWEAPONS ={
greatAxe:{
green: 'GreatAxe01_02_Spectral_Green'
},
greatSword:{
green: 'GreatSword01_02_Spectral_Green'
},
greatClub:{
green: 'GreatClub01_02_Spectral_Green'
},
mace: {
blue: 'Mace01_01_Spectral_Blue',
orange: 'Mace01_01_Spectral_Orange',
Expand All @@ -898,18 +925,36 @@ export const SPIRITUALWEAPONS ={
green: 'Maul01_01_Spectral_Green',
red: 'Maul01_01_Spectral_Red'
},
quarterstaff: {
green: 'Quarterstaff02_02_Spectral_Green',
greenCrystal: 'Quarterstaff03_02_Spectral_Green',
greenRamsHead: 'Quarterstaff04_02_Spectral_Green'
},
rapier: {
green: 'Rapier01_02_Spectral_Green'
},
scythe: {
blue: 'Scythe01_02_Spectral_Blue',
orange: 'Scythe01_02_Spectral_Orange',
purple: 'Scythe01_02_Spectral_Purple',
green: 'Scythe01_02_Spectral_Green',
red: 'Scythe01_02_Spectral_Red'
red: 'Scythe01_02_Spectral_Red',
white: 'Scythe01_02_Spectral_White'
},
spear: {
green: 'Spear01_02_Spectral_Green'
},
sword: {
blue: 'Sword01_01_Spectral_Blue',
orange: 'Sword01_01_Spectral_Orange',
purple: 'Sword01_01_Spectral_Purple',
green: 'Sword01_01_Spectral_Green',
red: 'Sword01_01_Spectral_Red'
},
trident: {
green: 'Trident01_02_Spectral_Green'
},
warhammer : {
green: 'Warhammer01_02_Spectral_Green'
}
}
4 changes: 2 additions & 2 deletions scripts/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function chat(message, options = {}){
}

export async function choose(options = [], prompt = ``, title = 'Please choose', {img = '', gm = false, player = ''}={}){
let dialog, result, time = 20000, alteredTitle = title + (player ? ` (${player} Prompted)` : '');
let dialog, result, time = 50000, alteredTitle = title + (player ? ` (${player} Prompted)` : '');
const query = new Promise((resolve) => {
const dialog_options = (options[0] instanceof Array)
? options.map(o => `<option value="${o[0]}">${o[1]}</option>`).join(``)
Expand Down Expand Up @@ -250,7 +250,7 @@ export async function useItem(itemUuid, options = {}, config = {}){

export const wait = (delay) => new Promise((resolve) => setTimeout(resolve, delay));

export async function yesNo(title = '', prompt = 'Continue?', {img = '', gm = false, player = '', time = 20000}={}){
export async function yesNo(title = '', prompt = 'Continue?', {img = '', gm = false, player = '', time = 50000}={}){
let dialog, result, alteredPrompt = prompt + (player ? ` (${player} Prompted)` : '');
const finalPrompt = img ? `<div class="napolitano-yes-no-img"><img src="${img}"/><div>${alteredPrompt}</div></div>` : `<p>${alteredPrompt}</p>`
const query = new Promise((resolve, reject) => {
Expand Down
4 changes: 4 additions & 0 deletions scripts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ Hooks.once('ready', async function() {

HOOKIDS['dnd5e.useItem'] = Hooks.on("dnd5e.useItem", async (item, options, data) => {
const hook = "dnd5e.useItem";
switch(item.name){
case 'Polymorph':
if(game.settings.get("napolitano-scripts", "polymorph")){workflow.play('polymorph', {item: item}, {hook: hook})}; break;
}
if(['Counterspell', 'Dispell Magic'].includes(item.name)) workflow.play('powerSurge', {item: item}, {hook: hook})
});

Expand Down
24 changes: 23 additions & 1 deletion scripts/macros.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ game.napolitano.macros(args, 'createBonfire', _napOps)
case 'lesserRestoration': await macro._lesserRestoration(); break;
case 'lungingAttack': await macro._lungingAttack(); break;
case 'mageHand': await macro._mageHand(); break;
case 'manifestEcho': await macro.manifestEcho(); break;
case 'magicalTinkering': await macro._magicalTinkering(); break;
case 'melfsMinuteMeteors': await macro._melfsMinuteMeteors(); break;
case 'mirrorImage': await macro._mirrorImage(); break;
Expand Down Expand Up @@ -1230,6 +1231,27 @@ game.napolitano.macros(args, 'createBonfire', _napOps)
this.message(`${this.name} uses magical tinkering and imbues ${tinker}` , {title: 'Magical Tinkering'})
}

async manifestEcho(){
this.summonData.updates = {
actor: {
system:{
abilities: this.source.actor.system.abilities,
traits: {
size: this.getSize(this.source.actor)
},
details: {
cr: this.sourceData.level
}
}
},
token: {texture: {src: this.tokenData.img}},
embedded: {
Item: this.source.actor.items.filter(i => i.type === 'weapon')
}
}
await this.summon();
}

async _melfsMinuteMeteors(){
this.itemAddData.name = this.config.name
await this.addItemName()
Expand Down Expand Up @@ -1432,7 +1454,7 @@ game.napolitano.macros(args, 'createBonfire', _napOps)
async _spiritualWeapon(){//tested v10
const weapon = await this.choose([['sword', 'Sword'], ['mace', 'Mace'], ['scythe', 'Scythe'], ['maul', 'Maul']] , 'Choose the form the spectral weapon takes:', 'Weapon Type')
const color = await this.choose([['blue', 'Blue'], ['green', 'Green'], ['orange', 'Orange'], ['purple', 'Purple'], ['red', 'Red']], 'Choose the color of the weapon', 'Weapon Color')
const path = (weapon && color) ? `modules/jb2a_patreon/Library/2nd_Level/Spiritual_Weapon/SpiritualWeapon_${SPIRITUALWEAPONS[weapon][color]}_${weapon === 'scythe' ? '300x300' : '200x200'}.webm` : `modules/jb2a_patreon/Library/2nd_Level/Spiritual_Weapon/SpiritualWeapon_Mace01_01_Spectral_Blue_200x200.webm`;
const path = (weapon && color) ? `modules/jb2a_patreon/Library/2nd_Level/Spiritual_Weapon/SpiritualWeapon_${SPIRITUALWEAPONS[weapon][color]}_${weapon === 'scythe' ? '300x300' : (['greatAxe', 'greatSword', 'greatClub','rapier', 'scythe', 'spear', 'trident', 'warhammer'].includes(weapon)? '400x400' : '200x200')}.webm` : `modules/jb2a_patreon/Library/2nd_Level/Spiritual_Weapon/SpiritualWeapon_Mace01_01_Spectral_Blue_200x200.webm`;
this.summonData.updates = {
token: {texture: {src: path}},
embedded: {
Expand Down
26 changes: 25 additions & 1 deletion scripts/workflow.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {napolitano} from "./napolitano-scripts.js";
import {importActorIfNotExists, chat, choose, getActorOwner, promptTarget, getSpellData, isOwner, requestSkillCheck, useItem, wait, yesNo} from "./helpers.js";
import {CONFIGS, EVIL, INCAPACITATEDCONDITIONS, MULTIPLEDAMAGEROLLSPELLS, NAPOLITANOCONFIG, PCS, TEMPLATEMODIFICATION} from "./constants.js";
import {getMonsterType, CONFIGS, EVIL, INCAPACITATEDCONDITIONS, MULTIPLEDAMAGEROLLSPELLS, NAPOLITANOCONFIG, PCS, TEMPLATEMODIFICATION} from "./constants.js";
import {napolitanoScriptsSocket} from "./index.js";
import {macros} from "./macros.js";
import {contest} from './contest.js';
Expand Down Expand Up @@ -736,6 +736,10 @@ export class framework {
return actor.type === "character" ? actor.system.details.level : actor.system.details.spellLevel
}

getLevelElseCR(document = this.source.actor){
return this.getType(document) === 'character' ? this.getLevel(document) : this.getCR(document)
}

getLinkedTokenFromScene(actor = this.source.actor, scene = this.scene){
return scene.tokens.find(t => t.actor?.id === actor.id && t.isLinked)
}
Expand Down Expand Up @@ -803,6 +807,11 @@ export class framework {
return (document.actor ? document.actor.system?.attributes?.hp?.temp : document.system?.attributes?.hp?.temp) ?? 0
}

getType(document = this.source.actor){
const actor = document.actor ?? document
return actor.type
}

async halfRoll(roll = this.roll){
roll = await new Roll(`${Math.floor(roll.total/2)}`).evaluate({async: true})
return roll
Expand Down Expand Up @@ -1481,6 +1490,7 @@ export class workflow extends framework {
this.source.actor = this.source.token.actor ?? {};
break;
case 'dnd5e.useItem':
this.targets = this.convertToTokenDocument(game.user.targets);
this.item = this.data.item;
this.source.actor = this.item.actor
break;
Expand Down Expand Up @@ -1600,6 +1610,7 @@ export class workflow extends framework {
case 'packTactics': flow._packTactics(); break;
case 'pan': flow._pan(); break;
case 'passWithoutTrace': flow._passWithoutTrace(); break;
case 'polymorph': flow._polymorph(); break;
case 'powerSurge': flow._powerSurge(); break;
case 'produceFlame': flow._produceFlame(); break;
case 'relentless': flow._relentless(); break;
Expand Down Expand Up @@ -2771,6 +2782,19 @@ export class workflow extends framework {
return this.data.roll
}

async _polymorph(){
if(!this.firstTarget) return this.warn(`No tokens are targeted. Spell cast as theatre of the mind.`)
const cr = this.getLevelElseCR(this.firstTarget)
this.choices = await getMonsterType('beast', cr)
if(!this.choices.list.length) return console.log('No beasts found within the compendium for CR at this level or lower')
this.choice = await this.choose(this.choices.options, this.config.prompt, this.config.name)
this.beast = this.choices.list.find(b => b.id === this.choice)
if(!this.beast) return console.log('No beast returned from choice.')
const actor = this.firstTarget.actor ?? this.firstTarget
actor.transformInto(this.beast, CONFIG.DND5E.transformationPresets.polymorph.options)
this.message(`${this.firstTarget.name} polymorphed into a ${this.beast.name}`, {title: this.config.name})
}

async _potentSpellcasting(){
if(!this.hasItem() || !this.hasHitTargets || !this.damageTotal || !this.source.actor.id || !this.item.id || !(this.itemData.isSpell && this.itemData.baseSpellLevel === 0)) return
await this.appendRoll(this.data.damageRoll, false, {sign: 1, isDamage: true, mod: this.sourceData.wisdomMod})
Expand Down

0 comments on commit f981de1

Please sign in to comment.