UNPKG

megaten

Version:

An unofficial collection of data from the Shin Megami Tensei and Persona games.

954 lines (953 loc) 40.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WallSkill = exports.TauntSkill = exports.SusceptibilitySkill = exports.SupportSkill = exports.SummonSkill = exports.SpringSkill = exports.SMTCounterSkill = exports.SiphonSkill = exports.SetSkill = exports.RegenSkill = exports.RecoverySkill = exports.PostBattleSkill = exports.PersonaCounterSkill = exports.NaviSkill = exports.MiscSkill = exports.MasterSkill = exports.InstaKillBoostSkill = exports.EvasionSkill = exports.EndureSkill = exports.DefensiveSkill = exports.CritBoostSkill = exports.CritSkill = exports.ChargeSkill = exports.BreakSkill = exports.BoostSkill = exports.BarrierBreakSkill = exports.BarrierSkill = exports.AutoBuffSkill = exports.AttackSkill = exports.AilmentSkill = exports.AilDefensiveSkill = exports.AilBoostSkill = exports.Skill = void 0; const util_1 = require("@squiddleton/util"); const error_js_1 = require("./error.js"); const skillData_js_1 = __importDefault(require("./skillData.js")); class Skill { /** The skill's name (adjusted for consistency with SMT5) */ name; /** The skill's alternative names */ aliases; /** The skill's normalized name used for matching queries */ devName; /** Whether the skill is unique to any specific demon(s), or null if the demon cannot be fused */ unique; /** The skill's affinity (adjusted for consistency with SMT5) */ affinity; /** The skill's type */ type; constructor(data) { this.name = data.name; this.aliases = data.aliases ?? []; this.devName = (0, util_1.normalize)(data.name); this.unique = data.unique === undefined ? false : data.unique; this.affinity = data.affinity; this.type = data.type; } /** Returns a string in "(Name): (Description)" format */ toString() { return `${this.name}: ${this.description}`; } /** An array of every Skill instance */ static array = []; /** A map of every Skill instance, keyed by their devName properties */ static map = new Map(); static get(name, error = false) { const normalized = (0, util_1.normalize)(name); const found = this.map.get(normalized) ?? this.array.find(skill => skill.aliases.some(alias => (0, util_1.normalize)(alias) === normalized)) ?? null; if (error && found === null) throw new error_js_1.MegatenError(name, 'Skill'); return found; } } exports.Skill = Skill; /** A skill that boosts the chance of inflicting ailments */ class AilBoostSkill extends Skill { description; /** The ailment that the skill increases the chance of inflicting */ ailment; /** The additional chance of inflicting the ailment */ amount; /** The conditions that the skill triggers under, or null if always in effect */ criteria; constructor(data) { const { ailment, criteria } = data; super(data); this.description = `Increases chance of inflicting ${ailment === 'All' ? 'ailments' : ailment}${criteria === null ? '' : ` during ${criteria}`}.`; this.ailment = ailment; this.amount = data.amount; this.criteria = criteria; } } exports.AilBoostSkill = AilBoostSkill; /** A skill that decreases the chance of afflicting the user with an ailment */ class AilDefensiveSkill extends Skill { description; /** The ailment resisted by this skill */ ailment; /** The level of resistance to the ailment */ resistance; constructor(data) { const { ailment, resistance } = data; super(data); this.description = resistance === 'Resist' ? `Decreases chance of being inflicted with ${ailment}.` : `Prevents infliction of ${ailment}.`; this.ailment = ailment; this.resistance = resistance; } } exports.AilDefensiveSkill = AilDefensiveSkill; /** A skill that inflicts an ailment */ class AilmentSkill extends Skill { description; /** The ailments that the skill inflicts */ ailments; /** The chance of inflicting the ailments (adjusted for consistency with SMT5) */ chance; /** The skill's MP cost */ cost; /** Debuffs that the skill applies */ debuffs; /** * The skill's special or notable features * * @deprecated Use AilmentSkill#debuffs instead. */ flags; /** The range that the skill targets */ range; constructor(data) { const { ailments, flags: debuffs = [], range } = data; super(data); this.description = `Chance of inflicting ${ailments.join(' and ')} to ${range === 'One' ? '1 foe' : 'all foes'}${debuffs.length === 0 ? '' : `and lowers ${debuffs.map(debuff => debuff.split(' ')[0]).join('')} by ${debuffs.every(debuff => debuff.includes('Greatly')) ? '2 ranks' : '1 rank'} for 3 turns`}.`; this.ailments = ailments; this.chance = data.chance; this.cost = data.cost; this.debuffs = debuffs; this.flags = this.debuffs; this.range = range; } } exports.AilmentSkill = AilmentSkill; /** A skill that deals damage, potentially having other effects */ class AttackSkill extends Skill { description; /** The skill's accuracy */ accuracy; /** The names and chances of ailments that the skill inflicts */ ailments; /** The skill cost's type and amount */ cost; /** The skill's special or notable features */ flags; /** The maximum times that the skill can land */ max; /** The minimum times that the skill can land, excluding misses */ min; /** The numerical and displayed amount of damage that the skill deals */ power; /** The range that the skill targets */ range; /** The game series that the skill data originates from */ series; constructor(data) { const { accuracy, affinity, ailments = [], flags = [], max = 1, min = 1, power, range, series } = data; super(data); const times = max === 1 ? '' : max === min ? max.toString() : `${min}~${max}`; const displayAffinity = `${times !== '' ? `${times} ${power.display.toLowerCase()}` : power.display} ${(flags.includes('Pierce') && ailments.length > 0) ? 'Piercing ' : ''}${(power.type === 'Physical' && !['Phys', 'Gun'].includes(affinity)) ? 'Strength-based ' : ''}${affinity}`; const displayRange = { One: '1 foe', All: 'all foes', Random: 'random foes' }[range]; if (flags.includes('Drain HP/MP')) { this.description = `${displayAffinity} HP/MP drain attack to ${displayRange}.`; } else if (flags.includes('Drain HP')) { this.description = flags.includes('Static Damage') ? `Drains ${power.amount} HP from ${displayRange}.` : `${displayAffinity} ${power.display === 'Weak' ? 'HP drain' : 'HP-draining'} attack to ${displayRange}.`; } else if (flags.includes('Drain MP')) { this.description = flags.includes('Static Damage') ? `Drains ${power.amount} MP from ${displayRange}.` : `${displayAffinity} MP drain attack to ${displayRange}.`; } else { this.description = `${displayAffinity} attack${max > 1 ? 's' : ''} to ${displayRange}.`; } const sentences = []; if (ailments.length > 0) sentences.push(`Chance of inflicting ${ailments.map(ailment => ailment.name).join('/')}.`); if (flags.length > 0) { if (flags.includes('+20% Crit Rate') || flags.includes('+30% Crit Rate')) { sentences.push('High chance of Critical.'); } if (flags.includes('+200% Crit Rate') && accuracy !== 50) { if (flags.includes('Pierce')) sentences.push('Ignores resistance, pierces, and always Critical.'); else if (accuracy === 50) sentences.push('Low accuracy, but hits are always Critical.'); else sentences.push('Always lands Critical hits.'); } if (flags.includes('Accuracy/Evasion Down')) { sentences.push('Lowers target\'s Accuracy/Evasion by 1 rank for 3 turns.'); } if (flags.includes('Afflicted Boost')) { sentences.push('Greater effect if target has an ailment.'); } if (flags.includes('Asleep Boost')) { sentences.push('Greater effect when target is asleep.'); } if (flags.includes('Attack Down')) { if (flags.includes('Defense Down')) sentences.push('Lowers target\'s Attack/Defense by 1 rank for 3 turns.'); else sentences.push('Lowers target\'s Attack by 1 rank for 3 turns.'); } if (flags.includes('Attack Reduced')) { sentences.push('Decreases Attack after use.'); } if (flags.includes('Baton Boost')) { sentences.push('Powers up after a Baton Pass.'); } if (flags.includes('Charmed Boost')) { sentences.push('Greater effect if target is Charmed.'); } if (flags.includes('Confused Boost')) { sentences.push('Greater effect when target is Confused.'); } if (flags.includes('Crit Damage Boost')) { sentences.push('Greater effect when landing a Critical.'); } if (flags.includes('Defense Down')) { if (!flags.includes('Attack Down')) sentences.push('Lowers target\'s Defense by 1 rank for 3 turns.'); } if (flags.includes('Defense Greatly Down')) { sentences.push('Lowers Defense by 2 ranks for 3 turns.'); } if (flags.includes('Down Boost')) { sentences.push('Highly effective if foe is Downed.'); } if (flags.includes('HP Dependent')) { sentences.push('The more remaining HP you have, the stronger the attack.'); } if (flags.includes('Instakill')) { sentences.push('Chance of instakill.'); } if (flags.includes('Minimize Defense')) { sentences.push('Lowers target\'s Defense to the minimum for 3 turns.'); } if (flags.includes('Negate Buffs')) { sentences.push('Negates target\'s status buff effects.'); } if (flags.includes('Pierce') && ailments.length === 0 && !flags.includes('+200% Crit Rate')) { sentences.push('Ignores affinity resistance and pierces through.'); } if (flags.includes('Poisoned Boost')) { sentences.push('Greater effect if target is Poisoned.'); } if (flags.includes('Surround Boost')) { sentences.push('Powers up when surrounded.'); } if (flags.includes('Weakness Instakill')) { sentences.push('Chance of instakill when striking weakness.'); } if (flags.includes('Weather Boost')) { sentences.push('Increased Critical rate in rainy or snowy weather.'); } } if (accuracy >= 95 && affinity === 'Phys' && series === 'persona') sentences.push('High accuracy.'); else if (accuracy === 50 && !flags.includes('+200% Crit Rate')) sentences.push('Low accuracy.'); if (sentences.length > 0) this.description += ` ${sentences.join(' ')}`; this.accuracy = accuracy; this.ailments = ailments; this.cost = data.cost; this.flags = flags; this.max = max; this.min = min; this.power = power; this.range = range; this.series = series; } } exports.AttackSkill = AttackSkill; /** A skill that automatically casts a buff at the start of battle */ class AutoBuffSkill extends Skill { description; /** The buff automatically applied by the skill */ buff; /** The range that the skill targets */ range; constructor(data) { const { buff, range } = data; super(data); let buffSkillName = { Attack: 'Tarukaja', Defense: 'Rakukaja', 'Accuracy/Evasion': 'Sukukaja' }[buff]; const isParty = range === 'Party'; if (isParty) { buffSkillName = buffSkillName.toLowerCase(); } this.description = `Automatic ${isParty ? 'Ma' : ''}${buffSkillName} at the start of battle.`; this.buff = buff; this.range = range; } } exports.AutoBuffSkill = AutoBuffSkill; /** A skill that forms a barrier */ class BarrierSkill extends Skill { description; /** The barriers that the skill forms */ barriers; /** The skill's MP cost */ cost; /** The range that the skill targets */ range; constructor(data) { super(data); if (data.barriers.length > 1) { this.description = 'Forms a barrier that reflects all attacks for all allies.'; } else { const [barrier] = data.barriers; switch (barrier) { case 'Tetraja': { this.description = 'A barrier that nullifies an instakill for all allies one time.'; break; } case 'Painting': { this.description = 'Forms a barrier that can absorb one attack (except Almighty).'; break; } case 'Shield of Justice': { this.description = 'Shields the party from all damage once.'; break; } case 'Kannabi Veil': { this.description = 'Decreases damage to all allies until the next turn.'; break; } case 'Tetrakarn': case 'Makarakarn': { this.description = `Reflects a ${barrier === 'Tetrakarn' ? 'Phys' : 'Magic'} attack once for 1 ally for 1 turn.`; break; } default: { this.description = `Nullifies a${['Ice', 'Elec'].some(affinity => this.name.includes(affinity)) ? 'n' : ''} ${this.name.replace(' Wall', '')} attack against all allies once for 1 turn.`; } } } this.barriers = data.barriers; this.cost = data.cost; this.range = data.range; } } exports.BarrierSkill = BarrierSkill; /** A skill that removes a barrier */ class BarrierBreakSkill extends Skill { description; /** The barrier that the skill removes */ barrier; /** The skill's MP cost */ cost; constructor(data) { const { barrier } = data; super(data); this.description = `Negates ${barrier} on all foes.`; this.barrier = barrier; this.cost = data.cost; } } exports.BarrierBreakSkill = BarrierBreakSkill; /** A skill that boosts the damage/recovery amount of skills with a specific affinity */ class BoostSkill extends Skill { description; /** The amount that the element's damage is boosted by */ amount; /** The affinity of the skills that the skill boosts */ element; /** Whether the skill stacks additively or multiplicatively */ stacks; constructor(data) { const { amount, element, stacks } = data; super(data); if (element === 'All') this.description = 'Strengtens all attacks. Can stack.'; else if (stacks === 'x') this.description = `Strengthens ${element} skills by ${amount}%.`; else this.description = `${amount === 35 ? 'Greatly i' : 'I'}ncreases ${element} attack damage.`; this.amount = amount; this.element = element; this.stacks = stacks; } } exports.BoostSkill = BoostSkill; /** A skill that negates resistance to an affinity */ class BreakSkill extends Skill { description; /** The skill's MP cost */ cost; /** The affinity whose resistance is negated by the skill */ element; constructor(data) { const { element } = data; super(data); this.description = `Negates ${element} resistance of all foes. Cannot negate ${element} Wall.`; this.cost = data.cost; this.element = element; } } exports.BreakSkill = BreakSkill; /** A skill that casts a charge */ class ChargeSkill extends Skill { description; /** The charge that the skill casts */ charge; /** The skill's MP cost */ cost; /** The range that the skill targets */ range; constructor(data) { const { charge, range } = data; super(data); switch (charge) { case 'Critical': { this.description = 'Next Strength-based attack of self will be 100% accurate and guaranteed Critical.'; break; } case 'Pierce': { this.description = 'Increases the damage of the next attack and adds Pierce effect for self.'; break; } case 'Recovery': { this.description = 'Greatly increases the effect of the next HP healing skill of self and allows it to heal above MAX HP.'; break; } default: this.description = range === 'Party' ? `Next ${charge === 'Charge' ? 'physical' : 'magical'} attack deals over double the damage for all allies.` : `Greatly increases damage of the next ${charge === 'Charge' ? 'Strength' : 'Magic'}-based attack ${range === 'Self' ? 'from self' : 'on 1 ally'}.`; } this.charge = charge; this.cost = data.cost; this.range = range; } } exports.ChargeSkill = ChargeSkill; /** A skill that is cast to increase the chance of landing critical hits */ class CritSkill extends Skill { description; /** The skill's MP cost */ cost; /** The range that the skill targets */ range; constructor(data) { const { range } = data; super(data); this.description = `Increases chance of Critical for ${{ All: 'all', Ally: 'one ally', Party: 'all allies' }[range]} for 3 turns.`; this.cost = data.cost; this.range = range; } } exports.CritSkill = CritSkill; /** A skill that passively increases the chance of landing critical hits */ class CritBoostSkill extends Skill { description; /** The additional chance of landing a critical hit */ amount; /** The conditions that the skill triggers under, or null if always in effect */ criteria; constructor(data) { const { criteria } = data; super(data); switch (criteria) { case 'Ambush': { this.description = 'Increases Critical rate during an Ambush.'; break; } case 'Surround': { this.description = 'Increases Critical Rate when surrounded.'; break; } case null: this.description = 'Increases chance of Critical.'; } this.amount = data.amount; this.criteria = criteria; } } exports.CritBoostSkill = CritBoostSkill; /** A skill that increases resistance to damage from a specific affinity */ class DefensiveSkill extends Skill { description; /** The affinity that the skill increases resistance from */ element; /** The skill user's new resistance to the element */ newResistance; constructor(data) { const { element, newResistance } = data; super(data); this.description = { Drain: `Absorbs damage from ${element} skills.`, Repel: `Reflects ${element} skills.`, Resist: `Strengthens resistance to ${element} skills.`, Null: `Nullifies ${element} skills.` }[newResistance]; this.element = element; this.newResistance = newResistance; } } exports.DefensiveSkill = DefensiveSkill; /** A skill that saves the user from a lethal attack */ class EndureSkill extends Skill { description; /** The priority that the skill triggers compared to other EndureSkill instances (a higher priority will trigger earlier in battle), or the chance that the skill triggers */ amount; /** The conditions that the skill triggers under, or null if always in effect */ criteria; constructor(data) { const { amount, criteria } = data; super(data); if (criteria === 'Light/Dark') this.description = 'Survive instakill skills with 1 HP.'; else if (criteria !== null) this.description = `${amount}% chance to survive ${criteria} skills with 1 HP.`; else if (amount === 1) this.description = 'Revives with 1 HP when KO\'d. Usable once per battle.'; else this.description = 'Endures lethal attack and fully heals HP once in battle.'; this.amount = amount; this.criteria = criteria; } } exports.EndureSkill = EndureSkill; /** A skill that increases evasion from skills with specific affinities */ class EvasionSkill extends Skill { description; /** The amount that the skill increases the chance of evading the elements by, or 0 if unknown */ amount; /** The conditions that the skill triggers under, or null if always in effect */ criteria; /** The affinity that the skill increases evasion from */ element; constructor(data) { const { amount, criteria, element } = data; super(data); if (criteria === 'Rain/Snow') this.description = 'Greatly increases Evasion from all affinities during Rain/Snow.'; else if (criteria === 'Surrounded') this.description = 'Greatly decreases Accuracy of all foes\' attacks except Almighty when surrounded.'; else if (element === 'Crit/Magic') this.description = 'Increases Evasion from Critical and magical attacks.'; else if (element === 'Magic') this.description = 'Increases Evasion from all magical attacks except Almighty.'; else this.description = `${amount === 3 ? 'Greatly i' : 'I'}ncreases Evasion from ${element} skills.${amount === 3 ? ' Does not stack.' : ''}`; this.amount = amount; this.criteria = criteria; this.element = element; } } exports.EvasionSkill = EvasionSkill; /** A skill that increases the chance of landing an instakill */ class InstaKillBoostSkill extends Skill { description; /** The affinity of the instakill skill that the skill boosts (adjusted for consistency with SMT5) */ element; constructor(data) { const { element } = data; super(data); this.description = `Increases success rate of ${element === 'Light' ? 'Hama' : 'Mudo'} skills.`; this.element = element; } } exports.InstaKillBoostSkill = InstaKillBoostSkill; /** A skill that decreases the cost of skills */ class MasterSkill extends Skill { description; /** The amount of the stat that skills' costs are reduced by */ amount; /** The stat cost that the skill lowers */ stat; constructor(data) { const { amount, stat } = data; super(data); const displayStat = { HP: 'HP', MP: 'MP', HPMP: 'HP and MP' }[stat]; this.description = `Decreases ${displayStat} cost of skills by ${amount}%.`; this.amount = amount; this.stat = stat; } } exports.MasterSkill = MasterSkill; /** A skill with miscellaneous (likely unique) effects */ class MiscSkill extends Skill { description; /** The skill's MP cost, or null if the skill has a Passive affinity */ cost; constructor(data) { super(data); this.description = data.description; this.cost = data.cost; } } exports.MiscSkill = MiscSkill; /** A skill learned by a navigator in the Persona serise */ class NaviSkill extends Skill { description; constructor(data) { super(data); this.description = data.description; } } exports.NaviSkill = NaviSkill; /** A skill that may reflect physical damage */ class PersonaCounterSkill extends Skill { description; /** The chance of countering attacks */ chance; constructor(data) { const { chance } = data; super(data); this.description = `${chance}% chance of reflecting physical attacks.`; this.chance = chance; } } exports.PersonaCounterSkill = PersonaCounterSkill; /** A skill that restores a stat when a battle ends */ class PostBattleSkill extends Skill { description; /** The amount of the stat that the skill increases */ amount; /** Whether the skill triggers for nonparticipating party members */ inactive; /** The stat that the skill increases */ stat; constructor(data) { const { amount, inactive, stat } = data; super(data); switch (stat) { case 'HP': case 'MP': { this.description = `Recover ${amount === 25 ? 'a little ' : ''}${stat} after a battle.`; break; } case 'HPMP': { this.description = amount === 100 ? 'Fully restores HP/MP after battle.' : `Restores ${amount}% HP and MP after battle.`; break; } case 'EXP': { this.description = inactive ? `Earn ${amount}% EXP even when not participating in battle.` : `EXP gained in battle increased by ${amount}%.`; break; } case 'Money': { this.description = `Increases money gained by ${amount}%.`; break; } } this.amount = amount; this.inactive = inactive; this.stat = stat; } } exports.PostBattleSkill = PostBattleSkill; /** A skill that recovers HP, ailments, and/or casts buffs */ class RecoverySkill extends Skill { description; /** The ailments that the skill recovers from */ ailments; /** The displayed amount that the skill heals, or null if it does not heal */ amount; /** The buffs that the skill casts */ buffs; /** The skill's MP cost */ cost; /** Special flags for the skill */ flags; /** The range that the skill targets */ range; constructor(data) { const { ailments = [], amount, buffs = [], flags = [], range } = data; super(data); const isParty = range === 'Party'; if (ailments === 'All') { this.description = amount === null ? `Cure status ailments on ${isParty ? 'all allies' : '1 ally'}.` : `${amount} HP recovery and cures status ailments${flags.includes('Revert Debuffs') ? '/debuffs' : ''} for ${isParty ? 'all allies' : '1 ally'}.`; } else if (ailments.length > 0) { this.description = `Cures ${ailments.join('/')} for ${isParty ? 'all allies' : 'one ally'}.`; } else if (flags.includes('Revive') && amount !== null) { this.description = flags.includes('Summon') ? 'Summons 1 demon at full HP. Effective on dead members as well.' : `Revive ${isParty ? 'all allies' : 'one ally'} with ${amount.toLowerCase()} HP.`; } else if (amount === '130%') { this.description = 'Full HP recovery to all allies and heals above MAX HP.'; } else { this.description = `${amount} HP recovery to ${isParty ? 'all allies' : '1 ally'}${buffs.length > 0 ? ` and raises ${buffs.length === 3 ? 'all stats' : buffs.join('/')} by ${buffs[0].includes('Double') ? '2 ranks' : '1 rank'} for 3 turns` : ''}.`; } this.ailments = ailments; this.amount = amount; this.buffs = buffs; this.cost = data.cost; this.flags = flags; this.range = range; } } exports.RecoverySkill = RecoverySkill; /** A skill that regenerates a stat each turn */ class RegenSkill extends Skill { description; /** The amount of the stat that the skill recovers */ amount; /** The conditions that the skill triggers under, or null if always in effect */ criteria; /** The stat that the skill recovers */ stat; constructor(data) { const { amount, criteria, stat } = data; super(data); this.description = { HP: `Restores ${amount} of max HP each turn in battle.`, MP: criteria === 'Baton Pass' ? `Restores ${amount} MP after a Baton Pass.` : `Restores ${amount} MP each turn in battle.`, HPMP: criteria === 'Ambush' && typeof amount === 'number' ? `Restores ${amount / 2}% max HP and ${amount} MP each turn during an Ambush.` : `Restores ${amount}% HP and ${amount} MP each turn in battle.`, AIL: amount === 1 ? 'Decreases recovery time from ailments by half.' : 'Decreases recovery time from ailments to 1 turn.' }[stat]; this.amount = amount; this.criteria = criteria; this.stat = stat; } } exports.RegenSkill = RegenSkill; /** A skill that sets an enemy's HP to a specific amount */ class SetSkill extends Skill { description; /** The amount of the enemy's current HP that it will be set to */ amount; /** The skill's MP cost, or null if enemy-exclusive */ cost; constructor(data) { const { amount } = data; super(data); this.description = typeof amount === 'string' ? `${this.affinity} attack that reduces HP of one foe by ${amount}.` : `Reduces enemy to ${amount} HP.`; this.amount = amount; this.cost = data.cost; } } exports.SetSkill = SetSkill; /** A skill that restores MP under certain criteria */ class SiphonSkill extends Skill { description; /** The amount of MP that the skill recovers */ amount; /** The conditions that the skill triggers under, or null if always in effect */ criteria; constructor(data) { const { amount, criteria } = data; super(data); this.description = `${amount === 10 ? 'Low ' : ' '}MP recovery when ${criteria === 'Ailment' ? 'inflicting status ailments' : 'you strike a foe\'s weakness or land a Critical'}.`; this.amount = amount; this.criteria = criteria; } } exports.SiphonSkill = SiphonSkill; /** A skill that automatically triggers when hit by a physical attack */ class SMTCounterSkill extends Skill { description; /** Whether the skill lowers the attack of the attacker */ attackDown; /** The chance for the skill to take effect */ chance; /** The affinity of the attack dealt from the counter */ element; /** The numerical and displayed amount of damage that the skill deals */ power; /** Whether the skill inflicts Shroud on the attacker */ shroud; constructor(data) { const { attackDown, chance, element, power, shroud = false } = data; super(data); this.description = shroud ? `Counters all attacks with a ${power.display.toLowerCase()} ${element} attack for one turn. Counterattack also inflicts Shroud.` : chance === 100 ? `Counterattacks with ${power.display.toLowerCase()} ${element} attack when a Thunder Bit is defeated.` : `Chance to counter Strength-based attacks with a ${power.display.toLowerCase()} ${element} attack.${this.name === 'Retaliate' ? ' Does not stack with Counter.' : ''}${attackDown ? ' Lowers target\'s Attack 1 rank for 3 turns.' : ''}`; this.attackDown = attackDown; this.chance = chance; this.element = element; this.power = power; this.shroud = shroud; } } exports.SMTCounterSkill = SMTCounterSkill; /** A skill that increases the user's maximum HP or MP */ class SpringSkill extends Skill { description; /** The amount that the stat is increased by */ amount; /** The stat that the skill increases */ stat; constructor(data) { const { amount, stat } = data; super(data); this.description = typeof amount === 'string' ? `Increases max ${stat} by ${amount}.` : `${amount === 30 ? 'Greatly i' : 'I'}ncreases MAX ${stat}.`; this.amount = amount; this.stat = stat; } } exports.SpringSkill = SpringSkill; /** A skill that summons one or more demons as allies */ class SummonSkill extends Skill { description; /** The summoned demon's name, or null if unknown */ demon; constructor(data) { super(data); this.description = 'Summons allies.'; this.demon = data.demon; } } exports.SummonSkill = SummonSkill; /** A skill that casts buffs, debuffs, or negates those on either allies or enemies */ class SupportSkill extends Skill { description; /** The barriers or charges automatically cast by having the skill */ auto; /** The buffs cast by the skill */ buffs; /** The skill's MP cost */ cost; /** The debuffs cast by the skill */ debuffs; /** The skill's special or notable features */ flags; /** Whether the skill negates its buffs or debuffs from enemies or allies, respectively */ negate; /** The range that the skill targets */ range; constructor(data) { const { buffs, debuffs, flags = [], negate, range } = data; super(data); const isAllyRangeFunc = (allyRange) => ['Ally', 'Party'].includes(range); const isAllyRange = isAllyRangeFunc(range); if (flags.includes('Cure Non-Special Ailments')) { this.description = 'Cures all non-special ailments for all allies.'; } else if (flags.includes('Maximize Buff')) { this.description = `Maximizes ${buffs[0]} for 3 turns.`; } else if (flags.includes('Minimize Debuffs')) { this.description = `Minimizes ${debuffs.join('/')} of 1 foe for 3 turns.`; } else { this.description = negate ? `Negates status ${isAllyRange ? 'de' : ''}buff effects on all ${isAllyRange ? 'allies' : 'foes'}.` : isAllyRange ? `Raises ${buffs.length === 3 ? 'all stats' : buffs.join('/').replace('Double ', '')} of ${range === 'Party' ? 'all allies' : '1 ally'} by ${buffs[0].includes('Double') ? '2 ranks' : '1 rank'} for 3 turns${flags.includes('Surrounded Only') ? ' when surrounded' : ''}.` : `Lowers ${debuffs.length === 3 ? 'all stats' : debuffs.join('/')} of ${range === 'All' ? 'all foes' : '1 foe'} by ${debuffs[0].includes('Double') ? '2 ranks' : '1 rank'} for 3 turns.`; } this.auto = data.auto; this.buffs = buffs; this.cost = data.cost; this.debuffs = debuffs; this.flags = flags; this.negate = negate; this.range = range; } } exports.SupportSkill = SupportSkill; /** A skill that increases the target's susceptibility to ailments */ class SusceptibilitySkill extends Skill { description; /** The skill's MP cost */ cost; /** The range that the skill targets */ range; constructor(data) { const { range } = data; super(data); this.description = `Increases chance of inflicting ailments to ${range === 'All' ? 'all' : 'one foe'}.`; this.cost = data.cost; this.range = range; } } exports.SusceptibilitySkill = SusceptibilitySkill; /** A skill that increases the chance of enemies targeting the user */ class TauntSkill extends Skill { description; /** The buff cast by the skill, or null if none */ buff; /** The skill's MP cost */ cost; constructor(data) { const { buff, cost } = data; super(data); this.description = buff === null ? cost === 4 ? 'Raises own chances of being targeted by foes.' : 'Raises chances of being targeted by foes for 3 turns.' : `Draws enemy hostility, but increases your ${buff} ${buff.includes('Double') ? '2 tiers' : 'by 1 rank'} for 3 turns.`; this.buff = buff; this.cost = cost; } } exports.TauntSkill = TauntSkill; /** A skill that temporarily increases an ally's resistance to damage from skills with a specific affinity */ class WallSkill extends Skill { description; /** The skill's MP cost */ cost; /** The affinity that the skill temporarily increases resistance from */ element; constructor(data) { const { element } = data; super(data); this.description = `Adds ${element} resistance to one ally for 3 turns.`; this.cost = data.cost; this.element = element; } } exports.WallSkill = WallSkill; Skill.array = Object.freeze(skillData_js_1.default.map(data => { switch (data.type) { case 'AILBOOST': return new AilBoostSkill(data); case 'AILDEFENSIVE': return new AilDefensiveSkill(data); case 'AILMENT': return new AilmentSkill(data); case 'ATTACK': return new AttackSkill(data); case 'AUTOBUFF': return new AutoBuffSkill(data); case 'BARRIER': return new BarrierSkill(data); case 'BARRIERBREAK': return new BarrierBreakSkill(data); case 'BOOST': return new BoostSkill(data); case 'BREAK': return new BreakSkill(data); case 'CHARGE': return new ChargeSkill(data); case 'CRIT': return new CritSkill(data); case 'CRITBOOST': return new CritBoostSkill(data); case 'DEFENSIVE': return new DefensiveSkill(data); case 'ENDURE': return new EndureSkill(data); case 'EVASION': return new EvasionSkill(data); case 'INSTAKILLBOOST': return new InstaKillBoostSkill(data); case 'MASTER': return new MasterSkill(data); case 'MISC': return new MiscSkill(data); case 'NAVI': return new NaviSkill(data); case 'PERSONACOUNTER': return new PersonaCounterSkill(data); case 'POSTBATTLE': return new PostBattleSkill(data); case 'RECOVERY': return new RecoverySkill(data); case 'REGEN': return new RegenSkill(data); case 'SET': return new SetSkill(data); case 'SIPHON': return new SiphonSkill(data); case 'SMTCOUNTER': return new SMTCounterSkill(data); case 'SPRING': return new SpringSkill(data); case 'SUMMON': return new SummonSkill(data); case 'SUPPORT': return new SupportSkill(data); case 'SUSCEPTIBILITY': return new SusceptibilitySkill(data); case 'TAUNT': return new TauntSkill(data); case 'WALL': return new WallSkill(data); } })); Skill.map = new Map(Skill.array.map(skill => [skill.devName, skill]));