"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var dex_species_exports = {}; __export(dex_species_exports, { DexSpecies: () => DexSpecies, Learnset: () => Learnset, Species: () => Species }); module.exports = __toCommonJS(dex_species_exports); var import_dex_data = require("./dex-data"); var import_utils = require("../lib/utils"); var import_node_util = require("node:util"); class Species extends import_dex_data.BasicEffect { constructor(data) { super(data); this.fullname = `pokemon: ${data.name}`; this.effectType = "Pokemon"; this.baseSpecies = data.baseSpecies || this.name; this.forme = data.forme || ""; this.baseForme = data.baseForme || ""; this.cosmeticFormes = data.cosmeticFormes || void 0; this.otherFormes = data.otherFormes || void 0; this.formeOrder = data.formeOrder || void 0; this.spriteid = data.spriteid || (0, import_dex_data.toID)(this.baseSpecies) + (this.baseSpecies !== this.name ? `-${(0, import_dex_data.toID)(this.forme)}` : ""); this.abilities = data.abilities || { 0: "" }; this.types = data.types || ["???"]; this.addedType = data.addedType || void 0; this.prevo = data.prevo || ""; this.tier = data.tier || ""; this.doublesTier = data.doublesTier || ""; this.natDexTier = data.natDexTier || ""; this.evos = data.evos || []; this.evoType = data.evoType || void 0; this.evoMove = data.evoMove || void 0; this.evoLevel = data.evoLevel || void 0; this.nfe = data.nfe || false; this.eggGroups = data.eggGroups || []; this.canHatch = data.canHatch || false; this.gender = data.gender || ""; this.genderRatio = data.genderRatio || (this.gender === "M" ? { M: 1, F: 0 } : this.gender === "F" ? { M: 0, F: 1 } : this.gender === "N" ? { M: 0, F: 0 } : { M: 0.5, F: 0.5 }); this.requiredItem = data.requiredItem || void 0; this.requiredItems = data.requiredItems || (this.requiredItem ? [this.requiredItem] : void 0); this.baseStats = data.baseStats || { hp: 0, atk: 0, def: 0, spa: 0, spd: 0, spe: 0 }; this.bst = this.baseStats.hp + this.baseStats.atk + this.baseStats.def + this.baseStats.spa + this.baseStats.spd + this.baseStats.spe; this.weightkg = data.weightkg || 0; this.weighthg = this.weightkg * 10; this.heightm = data.heightm || 0; this.color = data.color || ""; this.tags = data.tags || []; this.unreleasedHidden = data.unreleasedHidden || false; this.maleOnlyHidden = !!data.maleOnlyHidden; this.maxHP = data.maxHP || void 0; this.isMega = !!(this.forme && ["Mega", "Mega-X", "Mega-Y"].includes(this.forme)) || void 0; this.canGigantamax = data.canGigantamax || void 0; this.gmaxUnreleased = !!data.gmaxUnreleased; this.cannotDynamax = !!data.cannotDynamax; this.battleOnly = data.battleOnly || (this.isMega ? this.baseSpecies : void 0); this.changesFrom = data.changesFrom || (this.battleOnly !== this.baseSpecies ? this.battleOnly : this.baseSpecies); if (Array.isArray(this.changesFrom)) this.changesFrom = this.changesFrom[0]; this.pokemonGoData = data.pokemonGoData || void 0; if (!this.gen && this.num >= 1) { if (this.num >= 906 || this.forme.includes("Paldea")) { this.gen = 9; } else if (this.num >= 810 || ["Gmax", "Galar", "Galar-Zen", "Hisui"].includes(this.forme)) { this.gen = 8; } else if (this.num >= 722 || this.forme.startsWith("Alola") || this.forme === "Starter") { this.gen = 7; } else if (this.forme === "Primal") { this.gen = 6; this.isPrimal = true; this.battleOnly = this.baseSpecies; } else if (this.num >= 650 || this.isMega) { this.gen = 6; } else if (this.num >= 494) { this.gen = 5; } else if (this.num >= 387) { this.gen = 4; } else if (this.num >= 252) { this.gen = 3; } else if (this.num >= 152) { this.gen = 2; } else { this.gen = 1; } } (0, import_dex_data.assignMissingFields)(this, data); } } const EMPTY_SPECIES = import_utils.Utils.deepFreeze(new Species({ id: "", name: "", exists: false, tier: "Illegal", doublesTier: "Illegal", natDexTier: "Illegal", isNonstandard: "Custom" })); class Learnset { constructor(data, species) { this.exists = true; this.effectType = "Learnset"; this.learnset = data.learnset || void 0; this.eventOnly = !!data.eventOnly; this.eventData = data.eventData || void 0; this.encounters = data.encounters || void 0; this.species = species; } } class DexSpecies { constructor(dex) { this.speciesCache = /* @__PURE__ */ new Map(); this.learnsetCache = /* @__PURE__ */ new Map(); this.allCache = null; this.dex = dex; } get(name) { if (name && typeof name !== "string") return name; let id = ""; if (name) { name = name.trim(); id = (0, import_dex_data.toID)(name); if (id === "nidoran" && name.endsWith("\u2640")) { id = "nidoranf"; } else if (id === "nidoran" && name.endsWith("\u2642")) { id = "nidoranm"; } } return this.getByID(id); } getByID(id) { if (id === "") return EMPTY_SPECIES; let species = this.speciesCache.get(id); if (species) return species; if (this.dex.data.Aliases.hasOwnProperty(id)) { if (this.dex.data.FormatsData.hasOwnProperty(id)) { const baseId = (0, import_dex_data.toID)(this.dex.data.Aliases[id]); species = new Species({ ...this.dex.data.Pokedex[baseId], ...this.dex.data.FormatsData[id], name: id }); species.abilities = { 0: species.abilities["S"] }; } else { species = this.get(this.dex.data.Aliases[id]); if (species.cosmeticFormes) { for (const forme of species.cosmeticFormes) { if ((0, import_dex_data.toID)(forme) === id) { species = new Species({ ...species, name: forme, forme: forme.slice(species.name.length + 1), baseForme: "", baseSpecies: species.name, otherFormes: null, cosmeticFormes: null }); break; } } } } this.speciesCache.set(id, this.dex.deepFreeze(species)); return species; } if (!this.dex.data.Pokedex.hasOwnProperty(id)) { let aliasTo = ""; const formeNames = { alola: ["a", "alola", "alolan"], galar: ["g", "galar", "galarian"], hisui: ["h", "hisui", "hisuian"], paldea: ["p", "paldea", "paldean"], mega: ["m", "mega"], primal: ["p", "primal"] }; for (const forme in formeNames) { let pokeName = ""; for (const i of formeNames[forme]) { if (id.startsWith(i)) { pokeName = id.slice(i.length); } else if (id.endsWith(i)) { pokeName = id.slice(0, -i.length); } } if (this.dex.data.Aliases.hasOwnProperty(pokeName)) pokeName = (0, import_dex_data.toID)(this.dex.data.Aliases[pokeName]); if (this.dex.data.Pokedex[pokeName + forme]) { aliasTo = pokeName + forme; break; } } if (aliasTo) { species = this.get(aliasTo); if (species.exists) { this.speciesCache.set(id, species); return species; } } } if (id && this.dex.data.Pokedex.hasOwnProperty(id)) { const pokedexData = this.dex.data.Pokedex[id]; const baseSpeciesTags = pokedexData.baseSpecies && this.dex.data.Pokedex[(0, import_dex_data.toID)(pokedexData.baseSpecies)].tags; species = new Species({ tags: baseSpeciesTags, ...pokedexData, ...this.dex.data.FormatsData[id] }); const baseSpeciesStatuses = this.dex.data.Conditions[(0, import_dex_data.toID)(species.baseSpecies)]; if (baseSpeciesStatuses !== void 0) { for (const key in baseSpeciesStatuses) { if (!(key in species)) { species[key] = baseSpeciesStatuses[key]; } } } if (!species.tier && !species.doublesTier && !species.natDexTier && species.baseSpecies !== species.name) { if (species.baseSpecies === "Mimikyu") { species.tier = this.dex.data.FormatsData[(0, import_dex_data.toID)(species.baseSpecies)].tier || "Illegal"; species.doublesTier = this.dex.data.FormatsData[(0, import_dex_data.toID)(species.baseSpecies)].doublesTier || "Illegal"; species.natDexTier = this.dex.data.FormatsData[(0, import_dex_data.toID)(species.baseSpecies)].natDexTier || "Illegal"; } else if (species.id.endsWith("totem")) { species.tier = this.dex.data.FormatsData[species.id.slice(0, -5)].tier || "Illegal"; species.doublesTier = this.dex.data.FormatsData[species.id.slice(0, -5)].doublesTier || "Illegal"; species.natDexTier = this.dex.data.FormatsData[species.id.slice(0, -5)].natDexTier || "Illegal"; } else if (species.battleOnly) { species.tier = this.dex.data.FormatsData[(0, import_dex_data.toID)(species.battleOnly)].tier || "Illegal"; species.doublesTier = this.dex.data.FormatsData[(0, import_dex_data.toID)(species.battleOnly)].doublesTier || "Illegal"; species.natDexTier = this.dex.data.FormatsData[(0, import_dex_data.toID)(species.battleOnly)].natDexTier || "Illegal"; } else { const baseFormatsData = this.dex.data.FormatsData[(0, import_dex_data.toID)(species.baseSpecies)]; if (!baseFormatsData) { throw new Error(`${species.baseSpecies} has no formats-data entry`); } species.tier = baseFormatsData.tier || "Illegal"; species.doublesTier = baseFormatsData.doublesTier || "Illegal"; species.natDexTier = baseFormatsData.natDexTier || "Illegal"; } } if (!species.tier) species.tier = "Illegal"; if (!species.doublesTier) species.doublesTier = species.tier; if (!species.natDexTier) species.natDexTier = species.tier; if (species.gen > this.dex.gen) { species.tier = "Illegal"; species.doublesTier = "Illegal"; species.natDexTier = "Illegal"; species.isNonstandard = "Future"; } if (this.dex.currentMod === "gen7letsgo" && !species.isNonstandard) { const isLetsGo = (species.num <= 151 || ["Meltan", "Melmetal"].includes(species.name)) && (!species.forme || ["Alola", "Mega", "Mega-X", "Mega-Y", "Starter"].includes(species.forme) && species.name !== "Pikachu-Alola"); if (!isLetsGo) species.isNonstandard = "Past"; } if (this.dex.currentMod === "gen8bdsp" && (!species.isNonstandard || ["Gigantamax", "CAP"].includes(species.isNonstandard))) { if (species.gen > 4 || species.num < 1 && species.isNonstandard !== "CAP" || species.id === "pichuspikyeared") { species.isNonstandard = "Future"; species.tier = species.doublesTier = species.natDexTier = "Illegal"; } } species.nfe = species.evos.some((evo) => { const evoSpecies = this.get(evo); return !evoSpecies.isNonstandard || evoSpecies.isNonstandard === species?.isNonstandard || // Pokemon with Hisui evolutions evoSpecies.isNonstandard === "Unobtainable"; }); species.canHatch = species.canHatch || !["Ditto", "Undiscovered"].includes(species.eggGroups[0]) && !species.prevo && species.name !== "Manaphy"; if (this.dex.gen === 1) species.bst -= species.baseStats.spd; if (this.dex.gen < 5) { species.abilities = this.dex.deepClone(species.abilities); delete species.abilities["H"]; } if (this.dex.gen === 3 && this.dex.abilities.get(species.abilities["1"]).gen === 4) delete species.abilities["1"]; if (this.dex.parentMod) { const parentMod = this.dex.mod(this.dex.parentMod); if (this.dex.data.Pokedex[id] === parentMod.data.Pokedex[id]) { const parentSpecies = parentMod.species.getByID(id); if (species.tier === parentSpecies.tier && (0, import_node_util.isDeepStrictEqual)(species, parentSpecies)) { species = parentSpecies; } } } } else { species = new Species({ id, name: id, exists: false, tier: "Illegal", doublesTier: "Illegal", natDexTier: "Illegal", isNonstandard: "Custom" }); } if (species.exists) this.speciesCache.set(id, this.dex.deepFreeze(species)); return species; } /** * @param id the ID of the species the move pool belongs to * @param isNatDex * @returns a Set of IDs of the full valid movepool of the given species for the current generation/mod. * Note that inter-move incompatibilities, such as those from exclusive events, are not considered and all moves are * lumped together. However, Necturna and Necturine's Sketchable moves are omitted from this pool, as their fundamental * incompatibility with each other is essential to the nature of those species. */ getMovePool(id, isNatDex = false) { let eggMovesOnly = false; let maxGen = this.dex.gen; const gen3HMMoves = ["cut", "fly", "surf", "strength", "flash", "rocksmash", "waterfall", "dive"]; const gen4HMMoves = ["cut", "fly", "surf", "strength", "rocksmash", "waterfall", "rockclimb"]; const movePool = /* @__PURE__ */ new Set(); for (const { species, learnset } of this.getFullLearnset(id)) { if (!eggMovesOnly) eggMovesOnly = this.eggMovesOnly(species, this.get(id)); for (const moveid in learnset) { if (species.isNonstandard !== "CAP") { if (gen4HMMoves.includes(moveid) && this.dex.gen >= 5) { if (!learnset[moveid].some((source) => parseInt(source.charAt(0)) >= 5 && parseInt(source.charAt(0)) <= this.dex.gen)) continue; } else if (gen3HMMoves.includes(moveid) && this.dex.gen >= 4 && !learnset[moveid].some( (source) => parseInt(source.charAt(0)) >= 4 && parseInt(source.charAt(0)) <= this.dex.gen )) { continue; } } if (eggMovesOnly) { if (learnset[moveid].some((source) => source.startsWith("9E"))) { movePool.add(moveid); } } else if (maxGen >= 9) { if (isNatDex || learnset[moveid].some((source) => source.startsWith("9"))) { movePool.add(moveid); } } else { if (learnset[moveid].some((source) => parseInt(source.charAt(0)) <= maxGen)) { movePool.add(moveid); } } if (moveid === "sketch" && movePool.has("sketch")) { if (species.isNonstandard === "CAP") { continue; } const sketchables = this.dex.moves.all().filter((m) => !m.flags["nosketch"] && !m.isNonstandard); for (const move of sketchables) { movePool.add(move.id); } break; } } if (species.evoRegion) { if (this.dex.gen >= 9) eggMovesOnly = true; if (this.dex.gen === 8 && species.evoRegion === "Alola") maxGen = 7; } } return movePool; } getFullLearnset(id) { const originalSpecies = this.get(id); let species = originalSpecies; const out = []; const alreadyChecked = {}; while (species?.name && !alreadyChecked[species.id]) { alreadyChecked[species.id] = true; const learnset = this.getLearnsetData(species.id); if (learnset.learnset) { out.push(learnset); species = this.learnsetParent(species, true); continue; } if ((species.changesFrom || species.baseSpecies) !== species.name) { species = this.get(species.changesFrom || species.baseSpecies); continue; } if (species.isNonstandard) { return out; } if (species.prevo && this.getLearnsetData((0, import_dex_data.toID)(species.prevo)).learnset) { species = this.get((0, import_dex_data.toID)(species.prevo)); continue; } throw new Error(`Species with no learnset data: ${species.id}`); } return out; } learnsetParent(species, checkingMoves = false) { if (["Gastrodon", "Pumpkaboo", "Sinistea", "Tatsugiri"].includes(species.baseSpecies) && species.forme) { return this.get(species.baseSpecies); } else if (species.prevo) { species = this.get(species.prevo); if (species.gen > Math.max(2, this.dex.gen)) return null; return species; } else if (species.changesFrom && species.baseSpecies !== "Kyurem") { return this.get(species.changesFrom); } else if (checkingMoves && !species.prevo && species.baseSpecies && this.get(species.baseSpecies).prevo) { let baseEvo = this.get(species.baseSpecies); while (baseEvo.prevo) { baseEvo = this.get(baseEvo.prevo); } return baseEvo; } return null; } /** * Gets the raw learnset data for the species. * * In practice, if you're trying to figure out what moves a pokemon learns, * you probably want to `getFullLearnset` or `getMovePool` instead. */ getLearnsetData(id) { let learnsetData = this.learnsetCache.get(id); if (learnsetData) return learnsetData; if (!this.dex.data.Learnsets.hasOwnProperty(id)) { return new Learnset({ exists: false }, this.get(id)); } learnsetData = new Learnset(this.dex.data.Learnsets[id], this.get(id)); this.learnsetCache.set(id, this.dex.deepFreeze(learnsetData)); return learnsetData; } getPokemonGoData(id) { return this.dex.data.PokemonGoData[id]; } all() { if (this.allCache) return this.allCache; const species = []; for (const id in this.dex.data.Pokedex) { species.push(this.getByID(id)); } this.allCache = Object.freeze(species); return this.allCache; } eggMovesOnly(child, father) { if (child.baseSpecies === father?.baseSpecies) return false; while (father) { if (father.name === child.name) return false; father = this.learnsetParent(father); } return true; } } //# sourceMappingURL=dex-species.js.map