From 1cb7abb7f58c0eb892bd4e68dbfd7f907cc8f924 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Fri, 7 Jun 2024 00:25:42 -0500 Subject: [PATCH] add warrior's gift --- src/module/helpers.js | 10 +++ src/module/powers/basePowers.js | 3 +- src/module/powers/powers.js | 10 ++- src/module/powers/warriorsGift.js | 137 ++++++++++++++++++++++++++++++ src/module/swade-mb-helpers.js | 4 + 5 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 src/module/powers/warriorsGift.js diff --git a/src/module/helpers.js b/src/module/helpers.js index da115a0..f2a29ff 100644 --- a/src/module/helpers.js +++ b/src/module/helpers.js @@ -163,6 +163,16 @@ export async function deleteActiveEffectsFromToken(sceneId, tokenId, effectIds) await token.actor.deleteEmbeddedDocuments('ActiveEffect', effectIds); } +export async function addItemsToToken(sceneId, tokenId, itemDocuments) { + const token = _getSceneToken(sceneId, tokenId); + await token.actor.createEmbeddedDocuments('Item', itemDocuments, { renderSheet: false }); +} + +export async function deleteItemsFromActor(actorUuid, itemIds) { + const actor = await fromUuid(actorUuid); + await actor.deleteEmbeddedDocuments('Item', itemIds); +} + export async function updateOwnedToken(sceneId, tokenId, updates, options = {}) { const token = _getSceneToken(sceneId, tokenId); return token.update(updates, options); diff --git a/src/module/powers/basePowers.js b/src/module/powers/basePowers.js index 4ce379a..33e8aa6 100644 --- a/src/module/powers/basePowers.js +++ b/src/module/powers/basePowers.js @@ -443,6 +443,7 @@ export class PowerEffect { async parseValues() { this.data.raise = this.formData.submit === 'raise'; this.data.button = this.formData.submit; + this.data.maintId = foundry.utils.randomID(); for (const mod of this.modifiers) { this.data[mod.id] = this.formData[mod.id]; } @@ -608,7 +609,7 @@ export class PowerEffect { } async apply() { - const maintId = foundry.utils.randomID(); + const maintId = this.data.maintId; const secondaryDocs = await this.createSecondaryEffects(maintId); const primaryDoc = await this.createPrimaryEffect(maintId); const maintainDoc = await this.createMaintainEffect(maintId); diff --git a/src/module/powers/powers.js b/src/module/powers/powers.js index edd59f2..9d888d7 100644 --- a/src/module/powers/powers.js +++ b/src/module/powers/powers.js @@ -1,5 +1,5 @@ import { moduleName, moduleHelpers } from '../globals.js'; -import { firstOwner, deleteActiveEffectsFromToken, deleteToken } from '../helpers.js'; +import { firstOwner, deleteActiveEffectsFromToken, deleteToken, deleteItemsFromActor } from '../helpers.js'; import { ArcaneProtectionEffect } from './arcaneProtection.js'; import { BalefulPolymorphEffect } from './balefulPolymorph.js'; import { BanishEffect } from './banish.js'; @@ -61,6 +61,7 @@ import { TelekinesisEffect } from './telekinesis.js'; import { TeleportEffect } from './teleport.js'; import { TimeStopEffect } from './timeStop.js'; import { WallWalkerEffect } from './wallWalker.js'; +import { WarriorsGiftEffect } from './warriorsGift.js'; const PowerClasses = { 'arcane-protection': ArcaneProtectionEffect, @@ -142,6 +143,7 @@ const PowerClasses = { teleport: TeleportEffect, 'time-stop': TimeStopEffect, 'wall-walker': WallWalkerEffect, + 'warriors-gift': WarriorsGiftEffect, }; /* ---------------------------------------------------------------- */ @@ -217,6 +219,12 @@ export async function powerEffectManagementHook(effect, data, userId) { if (!maintId) { return; } + if (effect.getFlag(moduleName, 'attachedItems') ?? false) { + const itemIds = effect.parent.items.filter((i) => i.flags?.[moduleName]?.maintId === maintId).map((i) => i.id); + if (itemIds.length > 0) { + await moduleHelpers.socket.executeAsGM(deleteItemsFromActor, effect.parent.uuid, itemIds); + } + } const isSpawned = effect.getFlag(moduleName, 'spawnedTempToken') ?? false; if (isSpawned) { const token = effect.parent.token; diff --git a/src/module/powers/warriorsGift.js b/src/module/powers/warriorsGift.js new file mode 100644 index 0000000..a3ef69f --- /dev/null +++ b/src/module/powers/warriorsGift.js @@ -0,0 +1,137 @@ +import { moduleHelpers, moduleName } from '../globals.js'; +import { addItemsToToken } from '../helpers.js'; +import { PowerEffect } from './basePowers.js'; + +export class WarriorsGiftEffect extends PowerEffect { + constructor(token, targets) { + super(token, targets); + const template = game.actors.getName('warriors-edge_template'); + this.edges = template.items.filter((i) => i.type === 'edge').map((i) => template.getEmbeddedDocument('Item', i.id)); + } + + get name() { + return "Warrior's Gift"; + } + + get duration() { + return 5; + } + + get icon() { + return 'icons/magic/control/buff-strength-muscle-damage-orange.webp'; + } + + get hasAdditionalRecipients() { + return true; + } + + get additionalRecipientCost() { + return 1; + } + + get basePowerPoints() { + return 4; + } + + get isTargeted() { + return true; + } + + get modifiers() { + const mods = super.modifiers; + const choices = {}; + const powerChoices = {}; + const effects = {}; + const powerValues = {}; + const values = {}; + for (const edge of this.edges) { + powerChoices[edge.id] = edge.name; + choices[edge.id] = edge.name; + powerValues[edge.id] = 4; + values[edge.id] = 0; + effects[edge.id] = null; + } + powerChoices.none = 'None'; + powerValues.none = 0; + effects.none = null; + mods.push({ + sortOrder: -1, + name: 'Edge', + type: 'select', + id: 'edge', + epic: false, + choices, + values, + effects, + }); + mods.push({ + name: 'Power (2nd edge)', + type: 'select', + id: 'power', + epic: true, + choices: powerChoices, + default: 'none', + values: powerValues, + effects, + }); + return mods; + } + + async parseValues() { + await super.parseValues(); + this.data.appliedEdge = this.edges.find((e) => e.id === this.data.edge); + this.data.powerEdge = this.data.power === 'none' ? null : this.edges.find((e) => e.id === this.data.power); + if (this.data.raise) { + const newApplied = this.edges.find((e) => e.name === `Improved ${this.data.appliedEdge.name}`); + this.data.appliedEdge = newApplied ? newApplied : this.data.appliedEdge; + if (this.data.powerEdge) { + const newPowerEdge = this.edges.find((e) => e.name === `Improved ${this.data.powerEdge.name}`); + this.data.powerEdge = newPowerEdge ? newPowerEdge : this.data.powerEdge; + } + } + } + + async createPrimaryEffect(maintId) { + const doc = await super.createPrimaryEffect(maintId); + doc.flags[moduleName].attachedItems = true; + return doc; + } + + get effectName() { + return `${this.name} (${this.data.appliedEdge.name}${this.data.powerEdge ? `, ${this.data.powerEdge.name}` : ''})`; + } + + get description() { + let text = super.description + `

Add the Edge ${this.data.appliedEdge.name} `; + if (this.data.power) { + text += `and the Edge ${this.data.powerEdge.name} `; + } + text += 'to the recipient(s)'; + return text; + } + + async sideEffects() { + await super.sideEffects(); + const candidateEdges = [this.data.appliedEdge]; + if (this.data.powerEdge) { + candidateEdges.push(this.data.powerEdge); + } + for (const target of this.targets) { + const targetEdges = []; + for (const edge of candidateEdges) { + if (target.actor.items.find((i) => i.type === 'edge' && i.system.swid === edge.system.swid)) { + continue; + } + const edgeDoc = edge.toObject(); + mergeObject(edgeDoc, { + name: `${edge.name} (from ${this.name})`, + flags: { [moduleName]: { maintId: this.data.maintId } }, + }); + targetEdges.push(edgeDoc); + } + if (targetEdges.length > 0) { + moduleHelpers.socket.executeAsGM(addItemsToToken, target.scene.id, target.id, targetEdges); + } + } + } +} diff --git a/src/module/swade-mb-helpers.js b/src/module/swade-mb-helpers.js index e23128b..eacfda0 100644 --- a/src/module/swade-mb-helpers.js +++ b/src/module/swade-mb-helpers.js @@ -6,7 +6,9 @@ import { api } from './api.js'; import { initVisionModes } from './visionModes.js'; import { addActiveEffectsToToken, + addItemsToToken, deleteActiveEffectsFromToken, + deleteItemsFromActor, deleteToken, requestTokenRoll, SwadeVAEbuttons, @@ -63,5 +65,7 @@ Hooks.once('socketlib.ready', () => { _socket.register('deleteToken', deleteToken); _socket.register('addActiveEffectsToToken', addActiveEffectsToToken); _socket.register('deleteActiveEffectsFromToken', deleteActiveEffectsFromToken); + _socket.register('addItemsToToken', addItemsToToken); + _socket.register('deleteItemsFromActor', deleteItemsFromActor); moduleHelpers._socket = _socket; });