megaten
Version:
An unofficial collection of data from the Shin Megami Tensei and Persona games.
151 lines (150 loc) • 5.81 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Persona = exports.Demon = void 0;
const node_fs_1 = require("node:fs");
const promises_1 = require("node:fs/promises");
const node_path_1 = __importDefault(require("node:path"));
const util_1 = require("@squiddleton/util");
const demonData_js_1 = __importDefault(require("./demonData.js"));
const error_js_1 = require("./error.js");
const skill_js_1 = require("./skill.js");
function isPersona(demon) {
return demon.race === 'Persona';
}
function mapByDevName(obj) {
return [obj.devName, obj];
}
class Demon {
/** The demon's name */
name;
/** The demon's alternative names */
aliases;
/** The demon's normalized name used for matching queries */
devName;
/** The demon's skill potential and inherit affinity */
affinities;
/** The demon's Arcana in Persona titles, or null if unknown */
arcana;
/** The demon's race in mainline Shin Megami Tensei titles, or null if unknown */
race;
/** The demon's initial level */
level;
/** The demon's initial HP */
hp;
/** The demon's initial MP/SP */
mp;
/** The demon's initial stats */
stats;
/** The skills that the demon learns via leveling up */
learnset;
/** The demon's ailment and affinity resistances */
resistances;
/** The game that the demon's data originates from */
game;
/** The demon's moral and ethical alignment */
alignment;
/** The demon's backstory, or null for older Personas */
lore;
/** The demon's mythological origin */
origin;
constructor(data) {
this.name = data.name;
this.aliases = data.aliases ?? [];
this.devName = (0, util_1.normalize)(data.name);
this.affinities = data.affinities;
this.arcana = data.arcana;
this.race = data.race;
this.level = data.level;
this.hp = data.hp;
this.mp = data.mp;
this.stats = data.stats;
this.learnset = data.learnset;
this.resistances = data.resistances;
this.game = data.game;
this.alignment = data.alignment;
this.lore = data.lore;
this.origin = data.origin;
}
/** Asynchronously gets an image of the demon */
getImage() {
return (0, promises_1.readFile)(node_path_1.default.join(__dirname, '..', `images/demons/${this.devName}.png`));
}
/** Whether the demon is a Persona instance */
isPersona() {
return isPersona(this);
}
/** Whether the demon is exclusive to Persona games */
isPersonaBased() {
return this.race !== null && ['Persona', 'Picaro', 'Treasure'].includes(this.race);
}
/** Returns a string in "(Race) (Name)" format, or the name if the race is unknown */
toString() {
return this.race !== null && !this.isPersonaBased() ? `${this.race} ${this.name}` : this.name;
}
/** An image of the demon */
get image() {
return (0, node_fs_1.readFileSync)(node_path_1.default.join(__dirname, '..', `images/demons/${this.devName}.png`));
}
/** An array of every Demon and Persona instance */
static array = [];
/** A map of every Demon and Persona 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(demon => demon.aliases.some(alias => (0, util_1.normalize)(alias) === normalized)) ?? null;
if (error && found === null)
throw new error_js_1.MegatenError(name, 'Demon');
return found;
}
}
exports.Demon = Demon;
class Persona extends Demon {
/** The Persona's user */
user;
/** The Persona's stage of evolution */
stage;
/** The name of the skill that the Persona will learn upon reaching this stage, or null if none */
evoSkillName;
/** The Skill instance that the Persona will learn upon reaching this stage, or null if none */
evoSkill;
constructor(data) {
super(data);
this.user = data.user;
this.stage = data.stage;
this.evoSkillName = data.evoSkillName;
this.evoSkill = this.evoSkillName === null ? null : skill_js_1.Skill.get(this.evoSkillName, true);
}
/** The Persona that this Persona can evolve into, or null if none */
get evolution() {
return Persona.array.find(persona => persona.user === this.user && persona.stage === (this.stage + 1)) ?? null;
}
/**
* Returns a string in "(User)'s (Name)" format
*/
toString() {
return `${(0, util_1.formatPossessive)(this.user)} ${this.name}`;
}
/** An array of every Persona instance */
static array = [];
/** A map of every Persona instance, keyed by their devName properties */
static map = new Map();
static get(name, error = false) {
try {
return super.get(name, error);
}
catch (e) {
if (e instanceof error_js_1.MegatenError)
throw new error_js_1.MegatenError(name, 'Persona');
else
throw e;
}
}
}
exports.Persona = Persona;
Demon.array = Object.freeze(demonData_js_1.default.map(data => isPersona(data) ? new Persona(data) : new Demon(data)));
Demon.map = new Map(Demon.array.map(mapByDevName));
Persona.array = Object.freeze(Demon.array.filter(isPersona));
Persona.map = new Map(Persona.array.map(mapByDevName));