diff --git a/scripts/powers.js b/scripts/powers.js index 09a01a1..97118a1 100644 --- a/scripts/powers.js +++ b/scripts/powers.js @@ -184,9 +184,11 @@ class BlastEffect extends PowerEffect { get name () { return 'Blast' } get icon () { return 'icons/magic/fire/explosion-fireball-large-red-orange.webp' } get duration () { return 0 } - get isTargeted () { return false } + get isTargeted () { return true } + get usePrimaryEffect () { return false } get isDamaging () { return true } get basePowerPoints () { return 3 } + get hasAoe () { return true } get menuInputs () { const inputs = super.menuInputs inputs.push @@ -202,7 +204,7 @@ class BlastEffect extends PowerEffect { const mods = super.modifiers mods.push( { name: 'Damage', value: 2, id: 'damage', epic: false, effect: false }, - { name: 'Greater Blast', value: 1, id: 'greater', epic: true, effect: false }, + { name: 'Greater Blast', value: 4, id: 'greater', epic: true, effect: false }, ) return mods } @@ -231,6 +233,7 @@ class BlindEffect extends PowerEffect { get icon () { return 'icons/skills/wounds/injury-eyes-blood-red.webp' } get duration () { return 0 } get isTargeted () { return true } + get hasAoe () { return true } get basePowerPoints () { return 2 } getPrimaryEffectChanges () { const changes = [ @@ -310,12 +313,13 @@ class BoltEffect extends PowerEffect { get isTargeted () { return true } get isDamaging () { return true } get basePowerPoints () { return 3 } + get usePrimaryEffect () { return false } get modifiers () { const mods = super.modifiers mods.push( { name: 'Damage', value: 2, id: 'damage', epic: false, effect: false }, { name: 'Disintegrate', value: 1, id: 'disintigrate', epic: true, effect: false }, - { name: 'Greater Blast', value: 1, id: 'greater', epic: true, effect: false }, + { name: 'Greater Bolt', value: 4, id: 'greater', epic: true, effect: false }, { name: 'Rate of Fire', value: 2, id: 'rof', epic: true, effect: false }, ) return mods @@ -378,6 +382,149 @@ class BurrowEffect extends PowerEffect { } } +class BoostLowerTraitEffect extends PowerEffect { + get name () { return 'Boost/Lower Trait' } + get hasAdditionalRecipients () { return true } + get additionalRecipientCost () { return 2 } + get icon () { + return (this?.data?.direction === 'Boost' ? + 'icons/magic/life/cross-embers-glow-yellow-purple.webp' : + 'icons/magic/movement/chevrons-down-yellow.webp' + ) + } + get duration () { + return (this?.data?.direction === 'Boost' ? 5 : 0) + } + get isTargeted () { return true } + get basePowerPoints () { return 3 } + getPrimaryEffectChanges () { + let modValue = '2' + if (this.data.raise && this.data.direction === 'Boost') { + modValue = '4' + } + modValue = (this.data.direction === 'Boost' ? '+' : '-') + modValue + const changes = [ + { key: this.data.trait.diekey, value: modValue, + priority: 0, mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD } ] + if (this.data.direction === 'Lower' && this.data.mods.has('greater')) { + changes.push({ + key: this.data.trait.modkey, mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD, + value: -2, priority: 0}) + } + return changes + } + async createSecondaryEffects (maintId) { + const docs = await super.createSecondaryEffects(maintId) + if (this.data.raise && this.data.direction === 'Lower') { + const name = 'major ' + this.effectName + const modValue = (this.data.direction === 'Boost' ? '+2': '-2') + const changes = [ + { key: this.data.trait.diekey, value: modValue, + priority: 0, mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD } ] + const doc = this.createEffectDocument(this.icon, name, changes) + doc.duration.seconds = 594 + doc.description = this.description + + "

This is the raise effect which can be shaken off separately.

" + doc.flags[moduleName].maintId = maintId + docs.push(doc) + } + return docs + } + get effectName () { + let name = `${this.data.direction} ${this.data.trait.name}` + const nameMods = [] + if (this.data.mods.has('greater')) { + nameMods.push('Greater') + } + if (this.data.direction === 'Lower' && this.data.mods.has('strong')) { + nameMods.push('Strong') + } + if (nameMods.length > 0) { + name += ` (${nameMods.join(', ')})` + } + return name + } + get description () { + let desc = super.description + const amount = `${this.data.raise ? 2 : 1} die type${this.data.raise ? 's' :''}` + desc += `

${this.data.direction === 'Boost' ? 'Raise' : 'Lower'} the + target's ${this.data.trait.name} die type ${amount}.` + if (this.data.mods.has('greater')) { + if (this.data.direction === 'Boost') { + desc += ` Additionally, the target gains a free ${this.data.trait.name} + reroll once per ${this.data.raise ? 'action' : 'round'}.` + } else { + desc += ` Additionally, the target suffers a -2 penalty to their + ${this.data.trait.name} rolls.` + } + } + desc += '

' + if (this.data.direction === 'Lower') { + desc += `

At the end of the target's following turns, they attempt to shake off + the affect with a Spirit${this.data.mods.has('strong') ? ' -2' : ''} + roll as a free action. Success reduces the effect one die type. A raise + completely shakes off the effect.

` + } + return desc + } + get modifiers () { + const mods = super.modifiers + mods.push( + {name: 'Greater Boost/Lower Trailt', value: 2, id: 'greater', epic: true, effect: false}) + mods.push( + { name: 'Strong (lower only)', value: 1, id: 'strong', epic: false, effect: false } + ) + return mods + } + get menuInputs () { + const inputs = super.menuInputs + let traitOptions = ['Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor'] + const allSkills = new Set() + const traits = {} + for (const traitName of traitOptions) { + const lower = traitName.toLowerCase() + traits[traitName] = { + name: traitName, + type: 'attribute', + modkey: `system.attributes.${lower}.die.modifier`, + diekey: `system.attributes.${lower}.die.sides` + } + } + for (const token of this.targets) { + const skills = token.actor.items.filter(item => item.type === 'skill') + for (const skill of skills) { + const name = skill.name + traits[name] = { + name, + type: 'skill', + modkey: `@Skill{${name}}[system.die.modifier]`, + diekey: `@Skill{${name}}[system.die.sides]`, + } + if (name !== 'Unskilled') { + allSkills.add(name) + } + } + } + traitOptions = traitOptions.concat(Array.from(allSkills).sort()) + this.data.traits = traits + inputs.push({type: 'select', label: 'Trait', options: traitOptions}) + inputs.push({type: 'info', label: 'Boost or Lower?'}) + inputs.push({type: 'radio', label: 'Boost', options: ['isBoost', true]}) + inputs.push({type: 'radio', label: 'Lower', options: ['isBoost', false]}) + return inputs + } + async parseValues () { + await super.parseValues() + this.data.trait = this.data.traits[this.data.values.shift()] + this.data.values.shift() + this.data.direction = this.data.values.shift() ? 'Boost' : 'Lower' + } + get powerPoints () { + let total = super.powerPoints + return total + } +} + const PowerClasses = { "arcane-protection": ArcaneProtectionEffect, banish: BanishEffect, @@ -386,6 +533,9 @@ const PowerClasses = { blast: BlastEffect, blind: BlindEffect, bolt: BoltEffect, + "boost-lower-trait": BoostLowerTraitEffect, + "boost-trait": BoostLowerTraitEffect, + "lower-trait": BoostLowerTraitEffect, burrow: BurrowEffect, }