add detect-conceal arcana
This commit is contained in:
parent
8c373fcc8b
commit
1877b048d2
139
src/module/powers/detectConcealArcana.js
Normal file
139
src/module/powers/detectConcealArcana.js
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
import { PowerEffect } from './basePowers.js';
|
||||||
|
|
||||||
|
export class DetectConcealArcanaEffect extends PowerEffect {
|
||||||
|
get name() {
|
||||||
|
return 'Detect/Conceal Arcana';
|
||||||
|
}
|
||||||
|
|
||||||
|
get icon() {
|
||||||
|
return this.data.detect
|
||||||
|
? 'icons/magic/perception/third-eye-blue-red.webp'
|
||||||
|
: 'icons/magic/perception/silhouette-stealth-shadow.webp';
|
||||||
|
}
|
||||||
|
|
||||||
|
get duration() {
|
||||||
|
return this.data.detect ? 5 : 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
get basePowerPoints() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isTargeted() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasAdditionalRecipients() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
get additionalRecipientCost() {
|
||||||
|
return (this.data?.aoe || 0) > 0 ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
get modifiers() {
|
||||||
|
const mods = super.modifiers;
|
||||||
|
mods.push({
|
||||||
|
type: 'checkbox',
|
||||||
|
name: 'Alignment Sense (detect)',
|
||||||
|
value: 1,
|
||||||
|
id: 'alignment',
|
||||||
|
epic: false,
|
||||||
|
effect: false,
|
||||||
|
});
|
||||||
|
mods.push({
|
||||||
|
type: 'checkbox',
|
||||||
|
name: 'Identify (detect)',
|
||||||
|
value: 1,
|
||||||
|
id: 'identify',
|
||||||
|
epic: false,
|
||||||
|
effect: false,
|
||||||
|
});
|
||||||
|
mods.push({
|
||||||
|
type: 'checkbox',
|
||||||
|
name: 'Strong (conceal)',
|
||||||
|
value: 1,
|
||||||
|
id: 'strong',
|
||||||
|
epic: false,
|
||||||
|
effect: false,
|
||||||
|
});
|
||||||
|
mods.push({
|
||||||
|
sortOrder: -2,
|
||||||
|
name: 'Detect or Conceal?',
|
||||||
|
id: 'direction',
|
||||||
|
type: 'radio',
|
||||||
|
default: 'Detect',
|
||||||
|
epic: false,
|
||||||
|
choices: { Detect: 'Detect', Conceal: 'Conceal' },
|
||||||
|
effects: { Detect: null, Conceal: null },
|
||||||
|
values: { Detect: 0, Conceal: 0 },
|
||||||
|
});
|
||||||
|
mods.push({
|
||||||
|
name: 'Area of Effect (conceal)',
|
||||||
|
type: 'select',
|
||||||
|
default: 'none',
|
||||||
|
epic: false,
|
||||||
|
choices: { none: 'None', mbt: 'Medium Blast Template', lbt: 'Large Blast Template' },
|
||||||
|
effects: { none: null, mbt: null, lbt: null },
|
||||||
|
values: { none: 0, mbt: 1, lbt: 2 },
|
||||||
|
});
|
||||||
|
return mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasAoe() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async parseValues() {
|
||||||
|
await super.parseValues();
|
||||||
|
this.data.detect = this.data.direction == 'Detect';
|
||||||
|
}
|
||||||
|
|
||||||
|
get powerPoints() {
|
||||||
|
return super.powerPoints + this.data.aoe;
|
||||||
|
}
|
||||||
|
|
||||||
|
get effectName() {
|
||||||
|
return `${this.data.detect ? 'Detect' : 'Conceal'} Arcana`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get description() {
|
||||||
|
let desc = super.description;
|
||||||
|
if (this.data.detect) {
|
||||||
|
desc += `<p>The recipient can see and detect all supernatural persons,
|
||||||
|
objects, or effects in sight. This includes invisible foes, enchanted
|
||||||
|
objects, and so on.`;
|
||||||
|
if (this.data.raise) {
|
||||||
|
desc += `Since this was major Detect Arcana, the type of enchantments
|
||||||
|
is also known.`;
|
||||||
|
}
|
||||||
|
desc += `</p><p>If cast to learn more about a creature, the caster learns
|
||||||
|
active powers and arcane abilities.`;
|
||||||
|
if (this.data.raise) {
|
||||||
|
desc += `As major Detect in this mode, the caster also learns any
|
||||||
|
Weaknesses common to that creature type.`;
|
||||||
|
}
|
||||||
|
if (this.data.identify) {
|
||||||
|
desc += `<p>Items detected also give the recipient an idea of their
|
||||||
|
powers and how to activate them.</p>`;
|
||||||
|
}
|
||||||
|
if (this.data.alignment) {
|
||||||
|
desc += `<p>The recipient can also detect the presence and location
|
||||||
|
of supernatural good or evil within range, regardless of line of sight.</p>`;
|
||||||
|
}
|
||||||
|
desc += `</p><p><strong>Invisible Creatures:</strong> The recipient may
|
||||||
|
also ignore ${this.data.raise ? 'all' : 'up to 4 points of'} penalties
|
||||||
|
when attacking invisible or magically concealed foes.</p>`;
|
||||||
|
} else {
|
||||||
|
let area = 'one item or being';
|
||||||
|
if (this.data.aoe !== 0) {
|
||||||
|
area = `everything in a sphere the size of a
|
||||||
|
${this.data.aoe === 1 ? 'Medium' : 'Large'} Blast Template`;
|
||||||
|
}
|
||||||
|
desc += `<p>Conceal ${area} from the Detect Magic ability for
|
||||||
|
one hour. Attempts to <em>detect arcana</em> suffer a
|
||||||
|
${(this.data.strong ? -2 : 0) + this.data.raise ? -2 : -4} penalty.`;
|
||||||
|
}
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -16,148 +16,7 @@ import { CurseEffect } from './curse.js';
|
|||||||
import { DamageFieldEffect } from './damageField.js';
|
import { DamageFieldEffect } from './damageField.js';
|
||||||
import { DarksightEffect } from './darksight.js';
|
import { DarksightEffect } from './darksight.js';
|
||||||
import { DeflectionEffect } from './deflection.js';
|
import { DeflectionEffect } from './deflection.js';
|
||||||
|
import { DetectConcealArcanaEffect } from './detectConcealArcana.js';
|
||||||
class DetectConcealArcanaEffect extends PowerEffect {
|
|
||||||
get name() {
|
|
||||||
return 'Detect/Conceal Arcana';
|
|
||||||
}
|
|
||||||
|
|
||||||
get icon() {
|
|
||||||
return this.data.detect
|
|
||||||
? 'icons/magic/perception/third-eye-blue-red.webp'
|
|
||||||
: 'icons/magic/perception/silhouette-stealth-shadow.webp';
|
|
||||||
}
|
|
||||||
|
|
||||||
get duration() {
|
|
||||||
return this.data.detect ? 5 : 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
get basePowerPoints() {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
get isTargeted() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
get hasAdditionalRecipients() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
get additionalRecipientCost() {
|
|
||||||
return (this.data?.aoe || 0) > 0 ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
get modifiers() {
|
|
||||||
const mods = super.modifiers;
|
|
||||||
mods.push({
|
|
||||||
name: 'Alignment Sense (detect)',
|
|
||||||
value: 1,
|
|
||||||
id: 'alignment',
|
|
||||||
epic: false,
|
|
||||||
effect: false,
|
|
||||||
});
|
|
||||||
mods.push({
|
|
||||||
name: 'Identify (detect)',
|
|
||||||
value: 1,
|
|
||||||
id: 'identify',
|
|
||||||
epic: false,
|
|
||||||
effect: false,
|
|
||||||
});
|
|
||||||
mods.push({
|
|
||||||
name: 'Strong (conceal)',
|
|
||||||
value: 1,
|
|
||||||
id: 'strong',
|
|
||||||
epic: false,
|
|
||||||
effect: false,
|
|
||||||
});
|
|
||||||
return mods;
|
|
||||||
}
|
|
||||||
|
|
||||||
get hasAoe() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
get menuInputs() {
|
|
||||||
const inputs = super.menuInputs;
|
|
||||||
inputs.push({
|
|
||||||
type: 'select',
|
|
||||||
label: 'Area of Effect (conceal)',
|
|
||||||
options: [
|
|
||||||
{ html: 'None', value: 0, selected: true },
|
|
||||||
{ html: 'Medium Blast Template (+1)', value: 1, selected: false },
|
|
||||||
{ html: 'Large Blast Template (+2)', value: 2, selected: false },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
inputs.push({ type: 'info', label: 'Detect or Conceal?' });
|
|
||||||
inputs.push({
|
|
||||||
type: 'radio',
|
|
||||||
label: 'Detect',
|
|
||||||
options: ['isDetect', true],
|
|
||||||
});
|
|
||||||
inputs.push({
|
|
||||||
type: 'radio',
|
|
||||||
label: 'Conceal',
|
|
||||||
options: ['isDetect', false],
|
|
||||||
});
|
|
||||||
return inputs;
|
|
||||||
}
|
|
||||||
|
|
||||||
async parseValues() {
|
|
||||||
await super.parseValues();
|
|
||||||
this.data.aoe = this.data.values.shift();
|
|
||||||
this.data.values.shift();
|
|
||||||
this.data.detect = this.data.values.shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
get powerPoints() {
|
|
||||||
return super.powerPoints + this.data.aoe;
|
|
||||||
}
|
|
||||||
|
|
||||||
get effectName() {
|
|
||||||
return `${this.data.detect ? 'Detect' : 'Conceal'} Arcana`;
|
|
||||||
}
|
|
||||||
|
|
||||||
get description() {
|
|
||||||
let desc = super.description;
|
|
||||||
if (this.data.detect) {
|
|
||||||
desc += `<p>The recipient can see and detect all supernatural persons,
|
|
||||||
objects, or effects in sight. This includes invisible foes, enchanted
|
|
||||||
objects, and so on.`;
|
|
||||||
if (this.data.raise) {
|
|
||||||
desc += `Since this was major Detect Arcana, the type of enchantments
|
|
||||||
is also known.`;
|
|
||||||
}
|
|
||||||
desc += `</p><p>If cast to learn more about a creature, the caster learns
|
|
||||||
active powers and arcane abilities.`;
|
|
||||||
if (this.data.raise) {
|
|
||||||
desc += `As major Detect in this mode, the caster also learns any
|
|
||||||
Weaknesses common to that creature type.`;
|
|
||||||
}
|
|
||||||
if (this.data.mods.has('identify')) {
|
|
||||||
desc += `<p>Items detected also give the recipient an idea of their
|
|
||||||
powers and how to activate them.</p>`;
|
|
||||||
}
|
|
||||||
if (this.data.mods.has('alignment')) {
|
|
||||||
desc += `<p>The recipient can also detect the presence and location
|
|
||||||
of supernatural good or evil within range, regardless of line of sight.</p>`;
|
|
||||||
}
|
|
||||||
desc += `</p><p><strong>Invisible Creatures:</strong> The recipient may
|
|
||||||
also ignore ${this.data.raise ? 'all' : 'up to 4 points of'} penalties
|
|
||||||
when attacking invisible or magically concealed foes.</p>`;
|
|
||||||
} else {
|
|
||||||
let area = 'one item or being';
|
|
||||||
if (this.data.aoe !== 0) {
|
|
||||||
area = `everything in a sphere the size of a
|
|
||||||
${this.data.aoe === 1 ? 'Medium' : 'Large'} Blast Template`;
|
|
||||||
}
|
|
||||||
desc += `<p>Conceal ${area} from the Detect Magic ability for
|
|
||||||
one hour. Attempts to <em>detect arcana</em> suffer a
|
|
||||||
${(this.data.mods.has('strong') ? -2 : 0) + this.data.raise ? -2 : -4} penalty.`;
|
|
||||||
}
|
|
||||||
return desc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DisguiseEffect extends PowerEffect {
|
class DisguiseEffect extends PowerEffect {
|
||||||
get name() {
|
get name() {
|
||||||
@ -212,16 +71,20 @@ const PowerClasses = {
|
|||||||
blast: BlastEffect,
|
blast: BlastEffect,
|
||||||
blind: BlindEffect,
|
blind: BlindEffect,
|
||||||
bolt: BoltEffect,
|
bolt: BoltEffect,
|
||||||
|
'boostlower-trait': BoostLowerTraitEffect,
|
||||||
'boost-lower-trait': BoostLowerTraitEffect,
|
'boost-lower-trait': BoostLowerTraitEffect,
|
||||||
'boost-trait': BoostLowerTraitEffect,
|
'boost-trait': BoostLowerTraitEffect,
|
||||||
burrow: BurrowEffect,
|
burrow: BurrowEffect,
|
||||||
burst: BurstEffect,
|
burst: BurstEffect,
|
||||||
|
'conceal-arcana': DetectConcealArcanaEffect,
|
||||||
confusion: ConfusionEffect,
|
confusion: ConfusionEffect,
|
||||||
curse: CurseEffect,
|
curse: CurseEffect,
|
||||||
'damage-field': DamageFieldEffect,
|
'damage-field': DamageFieldEffect,
|
||||||
darksight: DarksightEffect,
|
darksight: DarksightEffect,
|
||||||
deflection: DeflectionEffect,
|
deflection: DeflectionEffect,
|
||||||
|
'detect-arcana': DetectConcealArcanaEffect,
|
||||||
'detect-conceal-arcana': DetectConcealArcanaEffect,
|
'detect-conceal-arcana': DetectConcealArcanaEffect,
|
||||||
|
'detectconceal-arcana': DetectConcealArcanaEffect,
|
||||||
disguise: DisguiseEffect,
|
disguise: DisguiseEffect,
|
||||||
'lower-trait': BoostLowerTraitEffect,
|
'lower-trait': BoostLowerTraitEffect,
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user