From c68c55bfc7950ac8d8f76ecca1532affd4232924 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sat, 8 Jun 2024 23:36:15 -0500 Subject: [PATCH] add lock/unlock, magic jar, shield other --- src/module/powers/lockUnlock.js | 71 +++++++++++++++++++++++++++++++++ src/module/powers/magicJar.js | 38 ++++++++++++++++++ src/module/powers/powers.js | 7 ++++ src/module/powers/protection.js | 21 ++++++++++ 4 files changed, 137 insertions(+) create mode 100644 src/module/powers/lockUnlock.js create mode 100644 src/module/powers/magicJar.js diff --git a/src/module/powers/lockUnlock.js b/src/module/powers/lockUnlock.js new file mode 100644 index 0000000..386736c --- /dev/null +++ b/src/module/powers/lockUnlock.js @@ -0,0 +1,71 @@ +import { PowerEffect } from './basePowers.js'; + +export class LockUnlockEffect extends PowerEffect { + get name() { + return 'Lock/Unlock'; + } + + get duration() { + return 0; + } + + get icon() { + return 'icons/sundries/misc/lock-open-yellow.webp'; + } + + get isTargeted() { + return false; + } + + get basePowerPoints() { + return 1; + } + + get usePrimaryEffect() { + return false; + } + + get modifiers() { + return [ + ...super.modifiers, + { + sortOrder: -2, + name: 'Lock or Unlock?', + id: 'direction', + type: 'radio', + default: 'Lock', + epic: false, + choices: { Lock: 'Lock', Unlock: 'Unlock' }, + effects: { Lock: null, Unlock: null }, + values: { Lock: 0, Unlock: 0 }, + }, + ]; + } + + get effectName() { + return this.data.direction; + } + + get description() { + let text = super.description; + if (this.data.direction === 'Lock') { + text += `

Magically seal a door, window, container, envelope, etc. Any + attempt to open it suffers a -4 penalty, with a failure meaning that + character can't try again until they update their skill level.

`; + if (this.data.raise) { + text += `

With the raise, the item can only be opwned with the unlock + version of this power (with the above -4 penalty.

`; + } + text += `

The caster may set a passphrase. The portal opens for anyone + who speaks the passphrase, until the passphrase is spoken again.

`; + } else { + text += `

Unlock in place of Repair or Thievery, ignoring up to 4 + points of penalties. `; + if (this.data.raise) { + text += `With a raise, it disarms any traps or alarms as well.`; + } + text += '

'; + } + return text; + } +} diff --git a/src/module/powers/magicJar.js b/src/module/powers/magicJar.js new file mode 100644 index 0000000..45cfdb8 --- /dev/null +++ b/src/module/powers/magicJar.js @@ -0,0 +1,38 @@ +import { PowerEffect } from './basePowers.js'; + +export class MagicJarEffect extends PowerEffect { + get name() { + return 'MagicJar'; + } + + get duration() { + return 3000; + } + + get icon() { + return 'icons/consumables/drinks/clay-jar-glowing-orange-blue.webp'; + } + + get isTargeted() { + return false; + } + + get isDamaging() { + return false; + } + + get basePowerPoints() { + return 5; + } + + get usePrimaryEffect() { + return false; + } + + get description() { + let text = super.description; + text += `

Transfer the caster's soul into an enchanted vessel. They may + move back and forth from the body to the jar if the body is within range.

`; + return text; + } +} diff --git a/src/module/powers/powers.js b/src/module/powers/powers.js index db6a76a..98816e1 100644 --- a/src/module/powers/powers.js +++ b/src/module/powers/powers.js @@ -38,6 +38,8 @@ import { IntangibilityEffect } from './intangibility.js'; import { InvisibliltyEffect } from './invisibility.js'; import { LightDarknessEffect } from './lightdarkness.js'; import { LocateEffect } from './locate.js'; +import { LockUnlockEffect } from './lockUnlock.js'; +import { MagicJarEffect } from './magicJar.js'; import { MindLinkEffect } from './mindLink.js'; import { MindReadingEffect } from './mindReading.js'; import { MindWipeEffect } from './mindWipe.js'; @@ -115,7 +117,11 @@ const PowerClasses = { lightdarkness: LightDarknessEffect, light: LightDarknessEffect, locate: LocateEffect, + lock: LockUnlockEffect, + lockunlock: LockUnlockEffect, + 'lock-unlock': LockUnlockEffect, 'lower-trait': BoostLowerTraitEffect, + 'magic-jar': MagicJarEffect, 'mind-link': MindLinkEffect, 'mind-reading': MindReadingEffect, 'mind-wipe': MindWipeEffect, @@ -146,6 +152,7 @@ const PowerClasses = { telekinesis: TelekinesisEffect, teleport: TeleportEffect, 'time-stop': TimeStopEffect, + unlock: LockUnlockEffect, 'wall-walker': WallWalkerEffect, 'warriors-gift': WarriorsGiftEffect, wish: WishEffect, diff --git a/src/module/powers/protection.js b/src/module/powers/protection.js index 625e8ba..29b2f44 100644 --- a/src/module/powers/protection.js +++ b/src/module/powers/protection.js @@ -37,6 +37,22 @@ export class ProtectionEffect extends PowerEffect { this.data.effect = doc; } + get modifiers() { + return [ + ...super.modifiers, + { + type: 'checkbox', + name: 'Shield Other', + id: 'other', + value: 1, + effect: true, + epic: false, + icon: 'icons/magic/defensive/shield-barrier-flaming-diamond-blue-yellow.webp', + changes: '', + }, + ]; + } + get basePrimaryEffect() { this.data.effect.changes = this.getPrimaryEffectChanges(); return this.data.effect; @@ -55,6 +71,11 @@ export class ProtectionEffect extends PowerEffect {

Grant the recipients 2 points of ${this.data.raise ? 'toughness' : 'armor'}

`; + if (this.data.other) { + text += `

If the protected creature is not the caster, and the protected + creature suffers wounds, the caster can take those wounds instead. If the + caster does this, they get a free reroll on the Soak roll, if one is attempted.

`; + } return text; } }