Spaces:
Paused
Paused
| ; | |
| 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 | |