From 929cdda415a93a8b954464400a28fbb59a010256 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sat, 8 Jun 2024 00:27:30 -0500 Subject: [PATCH] summon mods for zombie pt 1 --- src/module/powers/basePowers.js | 4 + src/module/powers/summon.js | 325 +++++++++++++++++++++++--------- 2 files changed, 242 insertions(+), 87 deletions(-) diff --git a/src/module/powers/basePowers.js b/src/module/powers/basePowers.js index 33e8aa6..bafc7d3 100644 --- a/src/module/powers/basePowers.js +++ b/src/module/powers/basePowers.js @@ -481,6 +481,10 @@ export class PowerEffect { const name = 'effects' in mod ? mod.effects[modValue].name : mod.name; const changes = 'effects' in mod ? mod.effects[modValue].changes : mod.changes; const doc = this.enhanceSecondaryEffect(maintId, this.createEffectDocument(icon, name, changes)); + const desc = 'effects' in mod ? mod.effects?.[modValue]?.description : mod.description; + if (desc) { + doc.description += desc; + } docs.push(doc); } } diff --git a/src/module/powers/summon.js b/src/module/powers/summon.js index 7200863..1adfc20 100644 --- a/src/module/powers/summon.js +++ b/src/module/powers/summon.js @@ -11,12 +11,56 @@ class BaseSummonEffect extends ActorFolderEffect { return 'Summonables'; } + get summonCount() { + return 0; + } + + async parseValuesPre() {} + + async parseValuesMid() {} + + async parseValuesPost() {} + + async parseValues() { + await super.parseValues(); + await this.parseValuesPre(); + await this.parseValuesMid(); + await this.parseValuesPost(); + } + + async spawn() { + const spawned = await new Portal() + .addCreature(this.targetTokenDoc, { count: this.summonCount }) + .texture(this.targetTokenDoc.texture.src) + .spawn(); + return spawned; + } + + async apply() { + await super.apply(); + const maintainDoc = await this.createMaintainEffect(this.data.maintId); + maintainDoc.flags[moduleName].targetIds = this.data.spawned.map((t) => t.id); + if (this.duration > 0) { + await this.applyActiveEffects(this.source, [maintainDoc]); + } + } +} + +class BaseAllyEffect extends BaseSummonEffect { get values() { return {}; } - get hasIncreasedTrait() { - return true; + get basePowerPoints() { + return 0; + } + + get duration() { + return 5; + } + + get isTargeted() { + return false; } get summonCount() { @@ -37,17 +81,15 @@ class BaseSummonEffect extends ActorFolderEffect { get modifiers() { const mods = super.modifiers; - if (this.hasIncreasedTrait) { - mods.push({ - type: 'checkbox', - name: 'Increased Trait (+1 per trait)', - id: 'increasedTrait', - value: 0, - effect: false, - epic: false, - default: false, - }); - } + mods.push({ + type: 'checkbox', + name: 'Increased Trait (+1 per trait)', + id: 'increasedTrait', + value: 0, + effect: false, + epic: false, + default: false, + }); mods.push({ type: 'number', name: `${this.additionalName} ${this.additionalDesc}`, @@ -62,7 +104,10 @@ class BaseSummonEffect extends ActorFolderEffect { name: 'Mind Rider', id: 'mindRider', value: 1, - effect: false, + effect: true, + icon: 'icons/magic/control/hypnosis-mesmerism-eye.webp', + changes: [], + description: 'The caster can communicate and sense through the ally.', epic: false, default: false, }); @@ -77,8 +122,36 @@ class BaseSummonEffect extends ActorFolderEffect { return 0; } - async prepIncreasedTrait() { - if (!(this.hasIncreasedTrait && this?.data?.increasedTrait)) { + get powerPoints() { + let value = super.powerPoints; + value += this.data.increasedTraitCount; + let halfValue = Math.ceil(value / 2); + return value + (this.data.additionalAllies ?? 0) * halfValue; + } + + async parseValuesPre() { + await super.parseValuesPre(); + this.data.actorUpdates = { + name: `${this.source.actor.name}'s summoned ${this.targetActor.name}`, + }; + this.data.tokenUpdates = { + actorLink: false, + name: `${this.source.name}'s ${this.targetActor.prototypeToken.name}`, + disposition: this.source.document.disposition, + sight: { + enabled: true, + }, + }; + this.data.embeddedUpdates = { + ActiveEffect: {}, + Item: {}, + }; + this.data.primaryEffectChanges = []; + } + + async parseValuesPost() { + await super.parseValuesPost(); + if (!this?.data?.increasedTrait) { this.data.increasedTraitCount = 0; return; } @@ -153,51 +226,20 @@ class BaseSummonEffect extends ActorFolderEffect { this.data.increasedTraitCount = count; } - get powerPoints() { - let value = super.powerPoints; - value += this.data.increasedTraitCount; - let halfValue = Math.ceil(value / 2); - return value + (this.data.additionalAllies ?? 0) * halfValue; - } - - async prePrep() {} - - async parseValues() { - await super.parseValues(); - this.data.actorUpdates = { - name: `${this.source.actor.name}'s summoned ${this.targetActor.name}`, - }; - this.data.tokenUpdates = { - actorLink: false, - name: `${this.source.name}'s ${this.targetActor.prototypeToken.name}`, - disposition: this.source.document.disposition, - sight: { - enabled: true, - }, - }; - this.data.embeddedUpdates = { - ActiveEffect: {}, - Item: {}, - }; - this.data.primaryEffectChanges = []; - await this.prePrep(); - await this.prepIncreasedTrait(); - } - getPrimaryEffectChanges() { return [...super.getPrimaryEffectChanges(), ...this.data.primaryEffectChanges]; } async createSecondaryEffects(maintId) { const effects = await super.createSecondaryEffects(maintId); - if (this.data.mindRider) { - const doc = this.enhanceSecondaryEffect( - maintId, - this.createEffectDocument('icons/magic/control/hypnosis-mesmerism-eye.webp', 'Mind Rider', []), - ); - doc.description = `The caster can communicate and sense through the ally`; - effects.push(doc); - } + // if (this.data.mindRider) { + // const doc = this.enhanceSecondaryEffect( + // maintId, + // this.createEffectDocument('icons/magic/control/hypnosis-mesmerism-eye.webp', 'Mind Rider', []), + // ); + // doc.description = `The caster can communicate and sense through the ally`; + // effects.push(doc); + // } if ((this.data?.increasedTraitChanges?.length ?? 0) > 0) { const doc = this.enhanceSecondaryEffect( maintId, @@ -216,23 +258,6 @@ class BaseSummonEffect extends ActorFolderEffect { return updates; } - async spawn() { - const spawned = await new Portal() - .addCreature(this.targetTokenDoc, { count: this.summonCount }) - .texture(this.targetTokenDoc.texture.src) - .spawn(); - return spawned; - } - - async apply() { - await super.apply(); - const maintainDoc = await this.createMaintainEffect(this.data.maintId); - maintainDoc.flags[moduleName].targetIds = this.data.spawned.map((t) => t.id); - if (this.duration > 0) { - await this.applyActiveEffects(this.source, [maintainDoc]); - } - } - get description() { let desc = super.description; desc += `

Summon a ${this.targetActor.prototypeToken.name} ally to serve @@ -245,27 +270,15 @@ class BaseSummonEffect extends ActorFolderEffect { } } -export class SummonAllyEffect extends BaseSummonEffect { +export class SummonAllyEffect extends BaseAllyEffect { get name() { return 'Summon Ally'; } - get basePowerPoints() { - return 0; - } - - get duration() { - return 5; - } - get icon() { return 'icons/magic/control/silhouette-hold-beam-blue.webp'; } - get isTargeted() { - return false; - } - get values() { return { attendant: 1, @@ -325,8 +338,8 @@ export class SummonAllyEffect extends BaseSummonEffect { return mods; } - async prePrep() { - await super.prePrep(); + async parseValuesMid() { + await super.parseValuesMid(); if (this.data.raise && this.data.actors['raise_template']) { const raiseTemplate = this.data.actors.raise_template; for (const item of raiseTemplate.items) { @@ -438,3 +451,141 @@ export class SummonAllyEffect extends BaseSummonEffect { return desc; } } + +export class ZombieEffect extends BaseSummonEffect { + get name() { + return 'Zombie'; + } + + get icon() { + return 'icons/magic/death/hand-dirt-undead-zombie.webp'; + } + + get modifiers() { + const mods = super.modifiers; + mods.push( + { + type: 'number', + name: 'Additional Zombies (+1 per zombie)', + id: 'additionalAllies', + value: 0, + default: 0, + epic: false, + effect: false, + }, + { + type: 'checkbox', + name: 'Armed (+1 per zombie)', + id: 'armed', + value: 0, + default: false, + epic: false, + effect: false, + }, + { + type: 'checkbox', + name: 'Armor (+1 per zombie)', + id: 'armor', + default: false, + epic: false, + effect: true, + icon: 'icons/equipment/chest/breastplate-leather-brown-belted.webp', + changes: [ + { + key: 'system.stats.toughness.armor', + value: 2, + priority: 0, + mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD, + }, + ], + }, + { + type: 'checkbox', + name: 'Skeletal', + value: 0, + id: 'skeletal', + epic: false, + default: false, + effect: true, + icon: 'icons/magic/death/hand-undead-skeleton-fire-pink.webp', + changes: [ + { + key: 'system.attributes.agility.die.sides', + value: 2, + priority: 0, + mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD, + }, + { + key: '@Skill{Athletics}[system.die.sides]', + value: 2, + priority: 0, + mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD, + }, + { + key: '@Skill{Fighting}[system.die.sides]', + value: 2, + priority: 0, + mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD, + }, + { + key: '@Skill{Shooting}[system.die.sides]', + value: 2, + priority: 0, + mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD, + }, + ], + }, + { + type: 'radio', + name: 'Mind Rider', + id: 'mindRider', + default: 'none', + epic: false, + choices: { none: 'None', single: 'Single', all: 'All' }, + values: { none: 0, single: 1, all: 3 }, + effects: { + none: null, + single: { + name: 'Mind Rider (single)', + icon: 'icons/magic/control/hypnosis-mesmerism-eye.webp', + changes: [], + description: 'The caster can communicate and sense through the ally.', + }, + all: { + name: 'Mind Rider (all)', + icon: 'icons/magic/control/hypnosis-mesmerism-eye.webp', + changes: [], + description: 'The caster can communicate and sense through the ally.', + }, + }, + }, + { + type: 'checkbox', + name: 'Permanent', + id: 'permanent', + default: false, + epic: false, + value: 0, + effect: true, + icon: 'icons/magic/death/skeleton-worn-skull-tan.webp', + changes: [], + description: 'This zombie is permanant until dismissed.', + }, + ); + return mods; + } + + actorValue(actor) { + const size = actor.system.stats.size; + if (size <= -1) { + return 2; + } + return 3 + size; + } + + async parseValuesPre() { + await super.parseValuesPre(); + this.data.actorUpdates.name = `${this.source.acor.name}'s raised ${this.targetActor.name}`; + this.data.tokenUpdates.name = `${this.source.name}'s raised ${this.targetActor.name}`; + } +}