burrow and boost lower trait

This commit is contained in:
Mike Bloy 2024-05-14 23:17:04 -05:00
parent cf30214502
commit f50a81a329
4 changed files with 267 additions and 248 deletions

View File

@ -25,12 +25,12 @@ export class PowerFormApplication extends FormApplication {
if (a.isGlobal !== b.isGlobal) {
return a.isGlobal ? -1 : 1;
}
if (a.type !== b.type) {
return a.type === 'checkbox' ? -1 : 1;
}
if ((a.sortOrder ?? 0) !== (b.sortOrder ?? 0)) {
return (a.sortOrder ?? 0) < (b.sortOrder ?? 0) ? -1 : 1;
}
if (a.type !== b.type) {
return a.type === 'checkbox' ? -1 : 1;
}
return a.name === b.name ? 0 : a.name < b.name ? -1 : 1;
}

View File

@ -0,0 +1,204 @@
import { moduleName } from '../globals.js';
import { PowerEffect } from './basePowers.js';
export 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) {
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.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 + '<p>This is the raise effect which can be shaken off separately.</p>';
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.greater) {
nameMods.push('Greater');
}
if (this.data.direction === 'Lower' && this.data.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 += `<p>${this.data.direction === 'Boost' ? 'Raise' : 'Lower'} the
target's ${this.data.trait.name} die type ${amount}.`;
if (this.data.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 += '</p>';
if (this.data.direction === 'Lower') {
desc += `<p>At the end of the target's following turns, they attempt to shake off
the affect with a Spirit${this.data.strong ? ' -2' : ''}
roll as a free action. Success reduces the effect one die type. A raise
completely shakes off the effect.</p>`;
}
return desc;
}
get modifiers() {
const mods = super.modifiers;
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());
const traitChoices = {};
const traitValues = {};
const traitEffects = {};
for (const trait of traitOptions) {
traitChoices[trait] = trait;
traitValues[trait] = 0;
traitEffects[trait] = null;
}
this.data.traits = traits;
mods.push({
sortOrder: -2,
name: 'Boost or Lower?',
id: 'direction',
type: 'radio',
default: 'Boost',
epic: false,
choices: { Boost: 'Boost', Lower: 'Lower' },
effects: { Boost: null, Lower: null },
values: { Boost: 0, Lower: 0 },
});
mods.push({
sortOrder: -1,
name: 'Trait',
id: 'traitName',
type: 'select',
epic: false,
choices: traitChoices,
values: traitValues,
effects: traitEffects,
});
mods.push({
name: 'Greater Boost/Lower Trailt',
type: 'checkbox',
value: 2,
id: 'greater',
epic: true,
effect: false,
});
mods.push({
name: 'Strong (lower only)',
type: 'checkbox',
value: 1,
id: 'strong',
epic: false,
effect: false,
});
return mods;
}
async parseValues() {
await super.parseValues();
this.data.trait = this.data.traits[this.data.traitName];
}
}

View File

@ -0,0 +1,58 @@
import { PowerEffect } from './basePowers.js';
export class BurrowEffect extends PowerEffect {
get name() {
return 'Burrow';
}
get duration() {
return 5;
}
get icon() {
return 'icons/magic/earth/projectile-stone-landslide.webp';
}
get hasAdditionalRecipients() {
return true;
}
get additionalRecipientCost() {
return 1;
}
get basePowerPoints() {
return 1;
}
get isTargeted() {
return true;
}
get modifiers() {
const mods = super.modifiers;
mods.push({
name: 'Power',
type: 'checkbox',
id: 'power',
value: 1,
epic: false,
effect: false,
});
return mods;
}
get effectName() {
return `${this.name} ${this.data.power ? '[Power] ' : ''}` + `(${this.data.raise ? 'full' : 'half'} pace)`;
}
get description() {
let text =
super.description +
`<p>Meld into the ground. Move at ${this.data.raise ? 'full' : 'half'} pace. May not run.</p>`;
if (this.data.power) {
text += '<p>Can <em>burrow</em> through solid stone, concrete, etc</p>';
}
return text;
}
}

View File

@ -8,251 +8,8 @@ import { BeastFriendEffect } from './beastFriend.js';
import { BlastEffect } from './blast.js';
import { BlindEffect } from './blind.js';
import { BoltEffect } from './bolt.js';
class BurrowEffect extends PowerEffect {
get name() {
return 'Burrow';
}
get duration() {
return 5;
}
get icon() {
return 'icons/magic/earth/projectile-stone-landslide.webp';
}
get hasAdditionalRecipients() {
return true;
}
get additionalRecipientCost() {
return 1;
}
get basePowerPoints() {
return 1;
}
get isTargeted() {
return true;
}
get modifiers() {
const mods = super.modifiers;
mods.push({
name: 'Power',
id: 'power',
value: 1,
epic: false,
effect: false,
});
return mods;
}
get effectName() {
return (
`${this.name} ${this.data.mods.has('power') ? '[Power] ' : ''}` + `(${this.data.raise ? 'full' : 'half'} pace)`
);
}
get description() {
let text =
super.description +
`<p>Meld into the ground. Move at ${this.data.raise ? 'full' : 'half'} pace. May not run.</p>`;
if (this.data.mods.has('power')) {
text += '<p>Can <em>burrow</em> through solid stone, concrete, etc</p>';
}
return text;
}
}
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 + '<p>This is the raise effect which can be shaken off separately.</p>';
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 += `<p>${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 += '</p>';
if (this.data.direction === 'Lower') {
desc += `<p>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.</p>`;
}
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() {
const total = super.powerPoints;
return total;
}
}
import { BurrowEffect } from './burrow.js';
import { BoostLowerTraitEffect } from './boostLowerTrait.js';
class BurstEffect extends PowerEffect {
get name() {