diff --git a/scripts/basePowers.js b/scripts/basePowers.js index 1e547e3..35df242 100644 --- a/scripts/basePowers.js +++ b/scripts/basePowers.js @@ -118,7 +118,7 @@ export class PowerEffect { } get menuInputs () { - const data = [ + const inputs = [ { type: 'header', label: `${this.name} Effect` }, { type: 'info', label: `Apply ${this.name} Effect` }, ] @@ -128,10 +128,10 @@ export class PowerEffect { label += ` (${this.targets.length - 1} additional recipients ` + `+${this.additionalRecipientCost} ea.)` } - data.push({ type: 'info', label: label }) + inputs.push({ type: 'info', label: label }) } for (const mod of this.modifiers) { - data.push({ + inputs.push({ type: 'checkbox', label: ( `${mod.epic ? '⭐ ' : ''}${mod.name} ` + @@ -140,7 +140,7 @@ export class PowerEffect { }) } if (this.isDamaging) { - data.push({ type: 'select', label: 'Armor Piercing', + inputs.push({ type: 'select', label: 'Armor Piercing', options: [ {html: 'None', value: 0, selected: true}, {html: 'AP 2 (+1)', value: 1, selected: false}, @@ -149,14 +149,14 @@ export class PowerEffect { ] }) } - data.push({type: 'select', label: 'Range', + inputs.push({type: 'select', label: 'Range', options: [ {html: 'Normal Range', value: 0, selected: true}, {html: 'Range ×2 (+1)', value: 1, selected: false}, {html: 'Range ×3 (+2)', value: 2, selected: false} ] }) - return data + return inputs } get menuButtons () { @@ -274,13 +274,15 @@ export class PowerEffect { const secondaryDocs = await this.createSecondaryEffects(maintId) const primaryDoc = await this.createPrimaryEffect(maintId) const maintainDoc = await this.createMaintainEffect(maintId) - for (const target of this.targets) { - const targetDocs = await this.secondaryDocsForTarget(secondaryDocs, target) - if (this.duration > 0 || this.usePrimaryEffect) { - targetDocs.push(await this.primaryDocForTarget(primaryDoc, target)) - } - if (targetDocs.length > 0) { - await this.applyActiveEffects(target, targetDocs) + if (this.isTargeted) { + for (const target of this.targets) { + const targetDocs = await this.secondaryDocsForTarget(secondaryDocs, target) + if (this.duration > 0 || this.usePrimaryEffect) { + targetDocs.push(await this.primaryDocForTarget(primaryDoc, target)) + } + if (targetDocs.length > 0) { + await this.applyActiveEffects(target, targetDocs) + } } } if (this.duration > 0) { @@ -289,7 +291,7 @@ export class PowerEffect { } async sideEffects () { - if (this.data.mods.has('fatigue')) { + if (this.data.mods.has('fatigue') && this.isTargeted) { for (const target of this.targets) { const actor = target.actor const update = { diff --git a/scripts/powers.js b/scripts/powers.js index 59a1850..8d28267 100644 --- a/scripts/powers.js +++ b/scripts/powers.js @@ -27,6 +27,99 @@ class ArcaneProtectionEffect extends PowerEffect { } } +class BanishEffect extends PowerEffect { + get name () { return 'Banish' } + get duration () { return 0 } + get basePowerPoints () { return 3 } + get usePrimaryEffect () { return false } + get isTargeted () { return true } + get menuInputs () { + const inputs = super.menuInputs + inputs.push + inputs.push({ type: 'select', label: '⭐ Area of Effect', + options: [ + {html: 'None', value: 0, selected: true}, + {html: 'Small Blast Template (+1)', value: 1, selected: false}, + {html: 'Medium Blast Template (+2)', value: 1, selected: false}, + {html: 'Large Blast Template (+3)', value: 1, selected: false}, + ]}) + return inputs + } + get powerPoints () { + let total = super.powerPoints + total += this.data.aoe + return total + } + get chatMessageEffects () { + const list = [] + switch (this.data.aoe) { + case 0: break + case 1: + list.push('SBT') + break + case 2: + list.push('MBT') + break + case 3: + list.push('LBT') + break + } + list.push("Opposed Roll: caster's arcane skill vs target's Spirit.") + list.push("Success: Shaken, Each Raise: 1 Wound") + list.push("If target incapacitated by this, banishment to home plane") + return list + } + + async parseValues () { + await super.parseValues() + this.data.aoe = this.data.values.shift() + } + +} + +class BarrierEffect extends PowerEffect { + get name () { return 'Barrier' } + get duration () { return 5 } + get icon () { return 'icons/environment/settlement/fence-stone-brick.webp' } + get isTargeted () { return false } + get basePowerPoints () { return 2 } + get usePrimaryEffect () { return false } + get modifiers () { + const mods = super.modifiers + mods.push({ name: 'Damage', id: 'damage', value: 1, epic: false, effect: false }) + mods.push({ name: 'Damage (immaterial trapping)', id: 'damage', value: 0, epic: false, effect: false }) + + mods.push({ name: 'Deadly', id: 'deadly', value: 2, epic: true, effect: false }) + mods.push({ name: 'Hardened', id: 'hardened', value: 1, epic: false, effect: false }) + mods.push({ name: 'Shaped', id: 'shaped', value: 1, epic: false, effect: false }) + mods.push({ name: 'Size', id: 'size', value: 1, epic: false, effect: false }) + return mods + } + get chatMessageEffects () { + const list = [] + const hardness = (this.data.raise ? 12 : 10) + (this.data.mods.has('hardened') ? 2 : 0) + list.push(`The Barrier is hardness ${hardness}`) + if (this.data.mods.has('damage')) { + list.push('Damage: 2d4 to anyone who contacts') + } + if (this.data.mods.has('deadly')) { + list.push('Deadly: 2d6 to anyone who contacts') + } + if (this.data.mods.has('shaped')) { + list.push('Shaped (circle, square, or rectangle)') + } + if (this.data.mods.has('size')) { + list.push('Size - length and height doubled') + } + return list + } + async createMaintainEffect (maintId) { + const doc = await super.createMaintainEffect(maintId) + doc.icon = this.icon + return doc + } +} + class BurrowEffect extends PowerEffect { get name () { return 'Burrow' } get duration () { return 5 } @@ -54,6 +147,8 @@ class BurrowEffect extends PowerEffect { const PowerClasses = { "arcane-protection": ArcaneProtectionEffect, + banish: BanishEffect, + barrier: BarrierEffect, burrow: BurrowEffect }