add illusion, invisibility, intangibility
This commit is contained in:
parent
b4fd301a4f
commit
3d6a561929
@ -81,6 +81,7 @@ export class PowerFormApplication extends FormApplication {
|
||||
data.recipients.cost = this.powerEffect.additionalRecipientCost;
|
||||
data.recipients.count = this.powerEffect.targets.length - 1;
|
||||
data.recipients.total = data.recipients.cost * data.recipients.count;
|
||||
data.recipients.epic = this.powerEffect.additionalRecipientsIsEpic;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@ -186,6 +187,10 @@ export class PowerEffect {
|
||||
return false;
|
||||
}
|
||||
|
||||
get additionalRecipientsIsEpic() {
|
||||
return false;
|
||||
}
|
||||
|
||||
get additionalRecipientCost() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
113
src/module/powers/illusion.js
Normal file
113
src/module/powers/illusion.js
Normal file
@ -0,0 +1,113 @@
|
||||
import { PowerEffect } from './basePowers.js';
|
||||
|
||||
export class IllusionEffect extends PowerEffect {
|
||||
get name() {
|
||||
return 'Illusion';
|
||||
}
|
||||
|
||||
get icon() {
|
||||
return 'icons/magic/defensive/illusion-evasion-echo-purple.webp';
|
||||
}
|
||||
|
||||
get duration() {
|
||||
return this.data.duration ? 50 : 5;
|
||||
}
|
||||
|
||||
get isTargeted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
get isRaisable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get usePrimaryEffect() {
|
||||
return false;
|
||||
}
|
||||
|
||||
get basePowerPoints() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
get modifiers() {
|
||||
return [
|
||||
{
|
||||
name: 'Area of Effect',
|
||||
type: 'checkbox',
|
||||
value: 1,
|
||||
id: 'aoe',
|
||||
epic: false,
|
||||
effect: false,
|
||||
},
|
||||
{
|
||||
name: 'Deadly Illusion',
|
||||
type: 'checkbox',
|
||||
value: 3,
|
||||
id: 'deadly',
|
||||
epic: true,
|
||||
effect: false,
|
||||
},
|
||||
{
|
||||
name: 'Duration',
|
||||
type: 'checkbox',
|
||||
value: 2,
|
||||
id: 'duration',
|
||||
epic: true,
|
||||
effect: false,
|
||||
},
|
||||
{
|
||||
name: 'Mobility',
|
||||
type: 'select',
|
||||
default: 'none',
|
||||
id: 'mobility',
|
||||
choices: {
|
||||
none: 'None',
|
||||
12: 'Move and fly at Pace 12',
|
||||
24: 'Move and fly at Pace 24',
|
||||
},
|
||||
values: { none: 0, 12: 1, 24: 2 },
|
||||
effects: { none: null, 12: null, 24: null },
|
||||
epic: false,
|
||||
},
|
||||
{
|
||||
name: 'Sound',
|
||||
id: 'sound',
|
||||
type: 'checkbox',
|
||||
epic: false,
|
||||
effect: false,
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: 'Strong',
|
||||
id: 'strong',
|
||||
type: 'checkbox',
|
||||
epic: false,
|
||||
effect: false,
|
||||
value: 2,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
get description() {
|
||||
const size = this.data.aoe ? 'LBT' : 'MBT';
|
||||
const penalty = (this.data.raise ? -2 : 0) + (this.data.strong ? -2 : 0);
|
||||
const motion = this.data.mobility === 'none' ? '(stationary)' : `that can move at pace ${this.data.mobility}`;
|
||||
let text =
|
||||
super.description +
|
||||
`<p>
|
||||
Create an illusion ${motion} ${this.data.sound ? 'with sound' : ''}.
|
||||
Its effects must remain within a sphere the size of a ${size}. </p>
|
||||
<p>Creatures can actively disbelieve in the illusion with a Smarts roll
|
||||
${penalty === 0 ? '' : `at ${penalty}`}.</p>
|
||||
`;
|
||||
if (this.data.deadly) {
|
||||
text += `<p>The caster can 'attack' targets while the illusion is active
|
||||
with an opposed roll of the caster's arcane skill versus the target's
|
||||
Smarts${penalty === 0 ? '' : ` at ${penalty}`}. If the caster wins the
|
||||
target is Shaken (cannot incapacitate). With a raise, the target suffers
|
||||
a Wound.</p>.
|
||||
`;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
||||
70
src/module/powers/intangibility.js
Normal file
70
src/module/powers/intangibility.js
Normal file
@ -0,0 +1,70 @@
|
||||
import { moduleName } from '../globals.js';
|
||||
import { PowerEffect } from './basePowers.js';
|
||||
|
||||
export class IntangibilityEffect extends PowerEffect {
|
||||
get name() {
|
||||
return 'Intangility';
|
||||
}
|
||||
|
||||
get duration() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
get icon() {
|
||||
return 'icons/magic/control/debuff-energy-hold-levitate-blue-yellow.webp';
|
||||
}
|
||||
|
||||
get hasAdditionalRecipients() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get additionalRecipientCost() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
get additionalRecipientsIsEpic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get basePowerPoints() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
get isTargeted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get isRaisable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get modifiers() {
|
||||
const mods = super.modifiers;
|
||||
mods.push({
|
||||
name: 'Duration',
|
||||
type: 'checkbox',
|
||||
id: 'Duration',
|
||||
value: 3,
|
||||
epic: true,
|
||||
effect: false,
|
||||
});
|
||||
return mods;
|
||||
}
|
||||
|
||||
get description() {
|
||||
let text =
|
||||
super.description +
|
||||
`<p>
|
||||
The subject becomes incorporeal. Non magical weapons and walls can't
|
||||
affect him. The character may affect other incorporeal beings, and is still
|
||||
susceptible to supernatural attacks. Unwilling targets resist with Spirit,
|
||||
and shake off the effect with a Spirit roll at the end of following turns.</p>
|
||||
<p>The being is Stunned and shunted to an open space if it is within
|
||||
something solid when the power ends.</p>
|
||||
`;
|
||||
if (this.data.raise) {
|
||||
text += '<p>Reduce damage taken from supernatural effects and magic weapons by 4.</p>';
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
||||
80
src/module/powers/invisibility.js
Normal file
80
src/module/powers/invisibility.js
Normal file
@ -0,0 +1,80 @@
|
||||
import { moduleName } from '../globals.js';
|
||||
import { PowerEffect } from './basePowers.js';
|
||||
|
||||
export class InvisibliltyEffect extends PowerEffect {
|
||||
get name() {
|
||||
return 'Invisibility';
|
||||
}
|
||||
|
||||
get duration() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
get icon() {
|
||||
return 'icons/svg/invisible.svg';
|
||||
}
|
||||
|
||||
get hasAdditionalRecipients() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get additionalRecipientCost() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
get basePowerPoints() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
get isTargeted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get isRaisable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get modifiers() {
|
||||
const mods = super.modifiers;
|
||||
mods.push({
|
||||
name: 'Duration',
|
||||
type: 'checkbox',
|
||||
id: 'Duration',
|
||||
value: 2,
|
||||
epic: true,
|
||||
effect: false,
|
||||
});
|
||||
return mods;
|
||||
}
|
||||
|
||||
get description() {
|
||||
let text =
|
||||
super.description +
|
||||
`
|
||||
<p>The subject is invisible, except for a vague blur or outline.
|
||||
Any action taken against it that requires sight is made at
|
||||
${this.data.raise ? -6 : -4}, including Notice rolls. This penalty is
|
||||
reduced by 2 if the invisible character's position is given away by some
|
||||
environmental circumstance.</p>
|
||||
`;
|
||||
if (this.data.duration) {
|
||||
text += `<p>This long-duration invisibility ends immediately if the subject
|
||||
attempts a damage-causing attack or targets an unwilling character with a
|
||||
power.</p>`;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
async parseValues() {
|
||||
await super.parseValues();
|
||||
const doc = await PowerEffect.getStatus('EFFECT.StatusInvisible', 'Invisible');
|
||||
doc.description = `<p>From <strong>${this.source.name}</strong> casting <em>${this.name}</em></p>`;
|
||||
doc.flags = mergeObject(doc.flags ?? {}, { [moduleName]: { powerEffect: true } });
|
||||
(doc.duration = { rounds: 99 }), (this.baseEffectDoc = doc);
|
||||
this.basePrimaryEffectDoc = doc;
|
||||
}
|
||||
|
||||
get basePrimaryEffect() {
|
||||
return this.basePrimaryEffectDoc;
|
||||
}
|
||||
}
|
||||
@ -31,6 +31,9 @@ import { FlyEffect } from './fly.js';
|
||||
import { GrowthShrinkEffect } from './growthShrink.js';
|
||||
import { HavocEffect } from './havoc.js';
|
||||
import { HealingEffect } from './healing.js';
|
||||
import { IllusionEffect } from './illusion.js';
|
||||
import { IntangibilityEffect } from './intangibility.js';
|
||||
import { InvisibliltyEffect } from './invisibility.js';
|
||||
|
||||
const PowerClasses = {
|
||||
'arcane-protection': ArcaneProtectionEffect,
|
||||
@ -71,6 +74,9 @@ const PowerClasses = {
|
||||
growthshrink: GrowthShrinkEffect,
|
||||
havoc: HavocEffect,
|
||||
healing: HealingEffect,
|
||||
illusion: IllusionEffect,
|
||||
intangibility: IntangibilityEffect,
|
||||
invisibility: InvisibliltyEffect,
|
||||
'lower-trait': BoostLowerTraitEffect,
|
||||
shrink: GrowthShrinkEffect,
|
||||
};
|
||||
|
||||
@ -19,7 +19,8 @@
|
||||
<strong>Targets</strong>:
|
||||
{{#each targets}}{{#if @index}}, {{/if}}{{this}}{{/each}}
|
||||
{{#if recipients.cost}}
|
||||
<br>(Additional Recipients {{recipients.cost}}pp each × {{recipients.count}} = {{recipients.total}})
|
||||
<br>({{#if recipients.epic}}⭐ {{/if}}Additional Recipients
|
||||
{{recipients.cost}}pp each × {{recipients.count}} = {{recipients.total}})
|
||||
{{/if}}
|
||||
</p>
|
||||
{{/if}}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user