UNPKG

pogo-data-generator

Version:
1,222 lines 59.7 kB
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const pogo_protos_1 = require("@na-ji/pogo-protos");
const enum_1 = require("../utils/enum");
const tempEvolutions_1 = require("../utils/tempEvolutions");
const Item_1 = __importDefault(require("./Item"));
const LocationCards_1 = __importDefault(require("./LocationCards"));
const Masterfile_1 = __importDefault(require("./Masterfile"));
const PokeApi_1 = __importDefault(require("./PokeApi"));
const PokemonOverrides_1 = __importDefault(require("./PokemonOverrides"));
const reconcileBaseFormChanges = (parsedPokemon, parsedForms, id) => {
    const pokemon = parsedPokemon[id];
    if (!pokemon?.formChanges) {
        return;
    }
    pokemon.forms
        ?.filter((formId) => formId !== 0)
        .forEach((formId) => {
        const form = parsedForms[formId];
        if (!form?.formChanges) {
            return;
        }
        const seenFormChanges = new Set();
        const baseFormChanges = new Set(pokemon.formChanges.map((formChange) => JSON.stringify(formChange)));
        const formChanges = form.formChanges.filter((formChange) => {
            const key = JSON.stringify(formChange);
            if (seenFormChanges.has(key) || baseFormChanges.has(key)) {
                return false;
            }
            seenFormChanges.add(key);
            return true;
        });
        if (formChanges.length) {
            form.formChanges = formChanges;
        }
        else {
            delete form.formChanges;
        }
    });
};
const cleanNumberList = (arr) => Array.isArray(arr)
    ? Array.from(new Set(arr.filter((value) => typeof value === 'number')))
    : [];
const hasExactPlaceholderMoves = (moves, expected) => moves.length === expected.length &&
    moves.every((value, index) => value === expected[index]);
const shouldPreferEstimatedPlaceholderQuickMoves = (actualQuickMoves, actualChargedMoves, fallbackQuickMoves) => hasExactPlaceholderMoves(actualQuickMoves, [
    pogo_protos_1.Rpc.HoloPokemonMove.SPLASH_FAST,
]) &&
    hasExactPlaceholderMoves(actualChargedMoves, [
        pogo_protos_1.Rpc.HoloPokemonMove.STRUGGLE,
    ]) &&
    !fallbackQuickMoves.includes(pogo_protos_1.Rpc.HoloPokemonMove.SPLASH_FAST) &&
    fallbackQuickMoves.length > 0;
const excludedPlaceholderFallbackChargedMoves = new Set([
    pogo_protos_1.Rpc.HoloPokemonMove.FRUSTRATION,
    pogo_protos_1.Rpc.HoloPokemonMove.RETURN,
]);
class Pokemon extends Masterfile_1.default {
    parsedPokemon;
    parsedPokeForms;
    parsedForms;
    formsRef;
    generations;
    lcBanList;
    evolvedPokemon;
    options;
    formsToSkip;
    evolutionQuests;
    parsedCostumes;
    jungleCupRules;
    constructor(options) {
        super();
        this.options = options;
        this.formsToSkip = this.options.skipForms
            ? this.options.skipForms.map((name) => name.toLowerCase())
            : [];
        this.parsedPokemon = {};
        this.parsedForms = {
            0: {
                formName: options.unsetFormName ?? 'Unset',
                proto: 'FORM_UNSET',
                formId: 0,
            },
        };
        this.formsRef = {};
        this.evolvedPokemon = new Set();
        this.generations = {
            1: {
                name: 'Kanto',
                range: [1, 151],
            },
            2: {
                name: 'Johto',
                range: [152, 251],
            },
            3: {
                name: 'Hoenn',
                range: [252, 386],
            },
            4: {
                name: 'Sinnoh',
                range: [387, 493],
            },
            5: {
                name: 'Unova',
                range: [494, 649],
            },
            6: {
                name: 'Kalos',
                range: [650, 721],
            },
            7: {
                name: 'Alola',
                range: [722, 809],
            },
            8: {
                name: 'Galar',
                range: [810, 905],
            },
            9: {
                name: 'Paldea',
                range: [906, 1010],
            },
        };
        this.evolutionQuests = {};
        this.parsedCostumes = {};
        this.jungleCupRules = { types: [], banned: [] };
    }
    pokemonName(id) {
        try {
            switch (id) {
                case 29:
                    return 'Nidoran♀';
                case 32:
                    return 'Nidoran♂';
                default:
                    return this.capitalize(pogo_protos_1.Rpc.HoloPokemonId[id]);
            }
        }
        catch (e) {
            console.warn(e, `Failed to set pokemon name for ${id}`);
        }
    }
    formName(id, formName) {
        if (!formName)
            return '';
        try {
            const name = formName.substring(id === pogo_protos_1.Rpc.HoloPokemonId.NIDORAN_FEMALE ||
                id === pogo_protos_1.Rpc.HoloPokemonId.NIDORAN_MALE
                ? 8
                : pogo_protos_1.Rpc.HoloPokemonId[id].length + 1);
            return this.capitalize(name);
        }
        catch (e) {
            console.warn(e, `Failed to lookup form name for ${formName}, ID#`, id);
        }
    }
    skipForms(formName) {
        if (!formName)
            return false;
        try {
            return this.formsToSkip.some((form) => formName.toLowerCase() === form);
        }
        catch (e) {
            console.warn(e, `Failed to skip forms for ${formName}`);
        }
    }
    lookupPokemon(name) {
        if (!name)
            return '';
        try {
            for (const key of Object.keys(pogo_protos_1.Rpc.HoloPokemonId)) {
                if (name.startsWith('PORYGON_Z_')) {
                    return 'PORYGON_Z';
                }
                else if (name.startsWith(`${key}_`)) {
                    return key;
                }
            }
        }
        catch (e) {
            console.warn(e, `Failed to lookup pokemon for ${name}`);
        }
    }
    lookupForm(id) {
        if (!id)
            return '';
        try {
            return (Object.entries(pogo_protos_1.Rpc.PokemonDisplayProto.Form).find(([_, v]) => {
                return v === id;
            })?.[0] || '');
        }
        catch (e) {
            console.warn(e, `Failed to lookup form for ${id}`);
        }
    }
    getGeneration(id) {
        try {
            const genInfo = {};
            genInfo.genId = +Object.keys(this.generations).find((gen) => {
                return (id >= this.generations[gen].range[0] &&
                    id <= this.generations[gen].range[1]);
            });
            if (genInfo.genId) {
                genInfo.generation = this.generations[genInfo.genId].name;
            }
            return genInfo;
        }
        catch (e) {
            console.warn(e, `Failed to lookup generation for ${id}`);
        }
    }
    getMoves(moves) {
        if (!moves)
            return [];
        try {
            return moves
                .map((move) => typeof move === 'string'
                ? pogo_protos_1.Rpc.HoloPokemonMove[move]
                : move)
                .filter(Boolean)
                .sort((a, b) => a - b);
        }
        catch (e) {
            console.warn(e, `Failed to lookup moves for ${moves}`);
        }
    }
    getTypes(incomingTypes) {
        if (!incomingTypes)
            return [];
        try {
            if (!incomingTypes[1]) {
                incomingTypes.pop();
            }
            return incomingTypes
                .map((type) => typeof type === 'string'
                ? pogo_protos_1.Rpc.HoloPokemonType[type]
                : type)
                .filter(Boolean)
                .sort((a, b) => a - b);
        }
        catch (e) {
            console.warn(e, `Failed to lookup types for ${incomingTypes}`);
        }
    }
    getCostumeOverrides(costumes) {
        try {
            return costumes.map((costume) => ({
                costumeId: pogo_protos_1.Rpc.PokemonDisplayProto.Costume[costume],
                costumeProto: costume,
                costumeName: this.capitalize(costume),
            }));
        }
        catch (e) {
            console.warn('Failed to process costume overrides', e, costumes);
        }
    }
    compileFormChanges(formChanges) {
        if (!Array.isArray(formChanges))
            return [];
        try {
            const seenFormChanges = new Set();
            return formChanges
                .map((formChange) => {
                const availableForms = (0, enum_1.resolveEnumIds)(pogo_protos_1.Rpc.PokemonDisplayProto.Form, formChange.availableForm || [], 'form');
                const questRequirements = formChange.questRequirement
                    ?.map((requirement) => ({
                    questRequirement: requirement.questRequirementTemplateId,
                    description: requirement.description,
                    target: requirement.target,
                }))
                    .filter((requirement) => requirement.questRequirement ||
                    requirement.description ||
                    requirement.target !== undefined) || [];
                const componentLocationCardSettings = formChange.componentPokemonSettings?.locationCardSettings
                    ?.map((settings) => ({
                    basePokemonLocationCard: LocationCards_1.default.resolveId(settings.basePokemonLocationCard, 'form change location card'),
                    componentPokemonLocationCard: LocationCards_1.default.resolveId(settings.componentPokemonLocationCard, 'form change location card'),
                    fusionPokemonLocationCard: LocationCards_1.default.resolveId(settings.fusionPokemonLocationCard, 'form change location card'),
                }))
                    .filter((settings) => Object.values(settings).some((value) => value !== undefined)) || [];
                const componentPokemonSettings = formChange.componentPokemonSettings
                    ? {
                        pokedexId: (0, enum_1.resolveEnumId)(pogo_protos_1.Rpc.HoloPokemonId, formChange.componentPokemonSettings.pokedexId, 'pokemon'),
                        formId: (0, enum_1.resolveEnumId)(pogo_protos_1.Rpc.PokemonDisplayProto.Form, formChange.componentPokemonSettings.form, 'form'),
                        componentCandyCost: formChange.componentPokemonSettings.componentCandyCost,
                        formChangeType: (0, enum_1.enumName)(pogo_protos_1.Rpc.ComponentPokemonSettingsProto.FormChangeType, formChange.componentPokemonSettings.formChangeType, 'form change type'),
                        fusionMove1: (0, enum_1.resolveEnumId)(pogo_protos_1.Rpc.HoloPokemonMove, formChange.componentPokemonSettings.fusionMove1, 'move'),
                        fusionMove2: (0, enum_1.resolveEnumId)(pogo_protos_1.Rpc.HoloPokemonMove, formChange.componentPokemonSettings.fusionMove2, 'move'),
                        locationCardSettings: componentLocationCardSettings.length
                            ? componentLocationCardSettings
                            : undefined,
                        familyId: (0, enum_1.resolveEnumId)(pogo_protos_1.Rpc.HoloPokemonFamilyId, formChange.componentPokemonSettings.familyId, 'family'),
                    }
                    : undefined;
                const moveReassignment = formChange.moveReassignment
                    ? {
                        quickMoves: formChange.moveReassignment.quickMoves
                            ?.map((moves) => ({
                            existingMoves: (0, enum_1.resolveEnumIds)(pogo_protos_1.Rpc.HoloPokemonMove, moves.existingMoves || [], 'move'),
                            replacementMoves: (0, enum_1.resolveEnumIds)(pogo_protos_1.Rpc.HoloPokemonMove, moves.replacementMoves || [], 'move'),
                        }))
                            .filter((moves) => moves.existingMoves.length ||
                            moves.replacementMoves.length) || undefined,
                        chargedMoves: formChange.moveReassignment.cinematicMoves
                            ?.map((moves) => ({
                            existingMoves: (0, enum_1.resolveEnumIds)(pogo_protos_1.Rpc.HoloPokemonMove, moves.existingMoves || [], 'move'),
                            replacementMoves: (0, enum_1.resolveEnumIds)(pogo_protos_1.Rpc.HoloPokemonMove, moves.replacementMoves || [], 'move'),
                        }))
                            .filter((moves) => moves.existingMoves.length ||
                            moves.replacementMoves.length) || undefined,
                    }
                    : undefined;
                const requiredQuickMoves = formChange.requiredQuickMoves
                    ?.map((moves) => ({
                    requiredMoves: (0, enum_1.resolveEnumIds)(pogo_protos_1.Rpc.HoloPokemonMove, moves.requiredMoves || [], 'move'),
                }))
                    .filter((moves) => moves.requiredMoves.length) || [];
                const requiredChargedMoves = formChange.requiredCinematicMoves
                    ?.map((moves) => ({
                    requiredMoves: (0, enum_1.resolveEnumIds)(pogo_protos_1.Rpc.HoloPokemonMove, moves.requiredMoves || [], 'move'),
                }))
                    .filter((moves) => moves.requiredMoves.length) || [];
                const requiredBreadMoves = formChange.requiredBreadMoves
                    ?.map((moves) => {
                    const moveTypes = moves.moveTypes?.filter(Boolean) || [];
                    return {
                        moveTypes: moveTypes.length ? moveTypes : undefined,
                        moveLevel: (0, enum_1.enumName)(pogo_protos_1.Rpc.BreadMoveLevels, moves.moveLevel, 'bread move level'),
                    };
                })
                    .filter((moves) => (moves.moveTypes?.length || 0) > 0 ||
                    moves.moveLevel !== undefined) || [];
                const formChangeBonusAttributes = formChange.formChangeBonusAttributes
                    ?.map((attributes) => {
                    const maxMoves = attributes.maxMoves
                        ?.map((move) => ({
                        moveType: (0, enum_1.enumName)(pogo_protos_1.Rpc.BreadMoveSlotProto.BreadMoveType, move.moveType, 'bread move type'),
                        moveLevel: (0, enum_1.enumName)(pogo_protos_1.Rpc.BreadMoveLevels, move.moveLevel, 'bread move level'),
                    }))
                        .filter((move) => move.moveType !== undefined ||
                        move.moveLevel !== undefined) || [];
                    return {
                        targetForm: (0, enum_1.resolveEnumId)(pogo_protos_1.Rpc.PokemonDisplayProto.Form, attributes.targetForm, 'form'),
                        breadMode: (0, enum_1.enumName)(pogo_protos_1.Rpc.BreadModeEnum.Modifier, attributes.breadMode, 'bread mode'),
                        clearBreadMode: attributes.clearBreadMode,
                        maxMoves: maxMoves.length ? maxMoves : undefined,
                    };
                })
                    .filter((attributes) => Object.entries(attributes).some(([key, value]) => key === 'maxMoves'
                    ? Array.isArray(value)
                        ? value.length > 0
                        : false
                    : value !== undefined)) || [];
                const locationCardSettings = formChange.locationCardSettings
                    ?.map((settings) => ({
                    existingLocationCard: LocationCards_1.default.resolveId(settings.existingLocationCard, 'form change location card'),
                    replacementLocationCard: LocationCards_1.default.resolveId(settings.replacementLocationCard, 'form change location card'),
                }))
                    .filter((settings) => Object.values(settings).some((value) => value !== undefined)) || [];
                const normalized = {
                    availableForms: availableForms.length ? availableForms : undefined,
                    candyCost: formChange.candyCost,
                    stardustCost: formChange.stardustCost,
                    itemRequirement: Item_1.default.resolveId(formChange.item, 'form change item'),
                    itemCostCount: formChange.itemCostCount,
                    questRequirements: questRequirements.length
                        ? questRequirements
                        : undefined,
                    componentPokemonSettings: componentPokemonSettings &&
                        Object.entries(componentPokemonSettings).some(([key, value]) => key === 'locationCardSettings'
                            ? Array.isArray(value)
                                ? value.length > 0
                                : false
                            : value !== undefined)
                        ? componentPokemonSettings
                        : undefined,
                    moveReassignment: moveReassignment &&
                        (moveReassignment.quickMoves?.length ||
                            moveReassignment.chargedMoves?.length)
                        ? moveReassignment
                        : undefined,
                    requiredQuickMoves: requiredQuickMoves.length
                        ? requiredQuickMoves
                        : undefined,
                    requiredChargedMoves: requiredChargedMoves.length
                        ? requiredChargedMoves
                        : undefined,
                    requiredBreadMoves: requiredBreadMoves.length
                        ? requiredBreadMoves
                        : undefined,
                    priority: formChange.priority,
                    formChangeBonusAttributes: formChangeBonusAttributes.length
                        ? formChangeBonusAttributes
                        : undefined,
                    locationCardSettings: locationCardSettings.length
                        ? locationCardSettings
                        : undefined,
                };
                return Object.values(normalized).some((value) => value !== undefined)
                    ? normalized
                    : undefined;
            })
                .filter((formChange) => {
                if (!formChange) {
                    return false;
                }
                const key = JSON.stringify(formChange);
                if (seenFormChanges.has(key)) {
                    return false;
                }
                seenFormChanges.add(key);
                return true;
            });
        }
        catch (e) {
            console.warn(e, `Failed to compile form changes for ${JSON.stringify(formChanges, null, 2)}`);
            return [];
        }
    }
    compileEvos(mfObject) {
        const overrides = PokemonOverrides_1.default.checkEvos(this, mfObject);
        if (overrides)
            return overrides;
        try {
            const evolutions = [];
            mfObject.forEach((branch) => {
                if (branch.temporaryEvolution) {
                    return;
                }
                else if (branch.evolution) {
                    const id = pogo_protos_1.Rpc.HoloPokemonId[branch.evolution];
                    const formId = typeof branch.form === 'number'
                        ? branch.form
                        : /^\d+$/.test(branch.form)
                            ? +branch.form
                            : pogo_protos_1.Rpc.PokemonDisplayProto.Form[branch.form];
                    evolutions.push({
                        evoId: id,
                        formId: this.options.includeUnset ? formId || 0 : formId,
                        genderRequirement: this.options.genderString
                            ? this.genders[pogo_protos_1.Rpc.PokemonDisplayProto.Gender[branch.genderRequirement]]
                            : pogo_protos_1.Rpc.PokemonDisplayProto.Gender[branch.genderRequirement],
                        candyCost: branch.candyCost,
                        itemRequirement: pogo_protos_1.Rpc.Item[branch.evolutionItemRequirement],
                        tradeBonus: branch.noCandyCostViaTrade,
                        mustBeBuddy: branch.mustBeBuddy,
                        onlyDaytime: branch.onlyDaytime,
                        onlyNighttime: branch.onlyNighttime,
                        questRequirement: branch.questDisplay
                            ? branch.questDisplay[0].questRequirementTemplateId
                            : undefined,
                    });
                    this.evolvedPokemon.add(id);
                }
            });
            return evolutions.sort((a, b) => a.evoId - b.evoId);
        }
        catch (e) {
            console.warn(e, `Failed to compile evos for ${JSON.stringify(mfObject, null, 2)}`);
        }
    }
    compileTempEvos(mfObject, evoBranch, primaryForm) {
        try {
            const tempEvolutions = mfObject
                .filter((tempEvo) => tempEvo.stats)
                .map((tempEvo) => {
                const resolvedTempEvoId = pogo_protos_1.Rpc.HoloTemporaryEvolutionId[tempEvo.tempEvoId] ??
                    (tempEvo.tempEvoId === 'TEMP_EVOLUTION_MEGA_Z'
                        ? 5
                        : tempEvo.tempEvoId);
                const newTempEvolution = {
                    tempEvoId: resolvedTempEvoId,
                };
                switch (true) {
                    case tempEvo.stats.baseAttack !== primaryForm.attack:
                    case tempEvo.stats.baseDefense !== primaryForm.defense:
                    case tempEvo.stats.baseStamina !== primaryForm.stamina:
                        newTempEvolution.attack = tempEvo.stats.baseAttack;
                        newTempEvolution.defense = tempEvo.stats.baseDefense;
                        newTempEvolution.stamina = tempEvo.stats.baseStamina;
                }
                if (tempEvo.averageHeightM !== primaryForm.height) {
                    newTempEvolution.height = tempEvo.averageHeightM;
                }
                if (tempEvo.averageWeightKg !== primaryForm.weight) {
                    newTempEvolution.weight = tempEvo.averageWeightKg;
                }
                const types = this.getTypes([
                    tempEvo.typeOverride1,
                    tempEvo.typeOverride2,
                ]);
                if (!this.compare(types, primaryForm.types)) {
                    newTempEvolution.types = types;
                }
                const energy = evoBranch.find((branch) => branch.temporaryEvolution === tempEvo.tempEvoId);
                if (energy) {
                    newTempEvolution.firstEnergyCost =
                        energy.temporaryEvolutionEnergyCost;
                    newTempEvolution.subsequentEnergyCost =
                        energy.temporaryEvolutionEnergyCostSubsequent;
                }
                return newTempEvolution;
            });
            return (0, tempEvolutions_1.sortTempEvolutions)(tempEvolutions);
        }
        catch (e) {
            console.warn(e, `Failed to compile temp evos for ${JSON.stringify(mfObject, null, 2)}`);
        }
    }
    generateProtoForms() {
        Object.entries(pogo_protos_1.Rpc.PokemonDisplayProto.Form).forEach((proto) => {
            const [name, formId] = proto;
            try {
                const pokemon = name.startsWith('NIDORAN_')
                    ? ['NIDORAN_FEMALE', 'NIDORAN_MALE']
                    : [this.formsRef[name] || this.lookupPokemon(name)];
                for (const pkmn of pokemon) {
                    if (pkmn) {
                        const id = pogo_protos_1.Rpc.HoloPokemonId[pkmn];
                        const formName = this.formName(id, name);
                        if (!this.parsedPokemon[id]) {
                            this.parsedPokemon[id] = {
                                pokemonName: this.pokemonName(id),
                                forms: this.options.includeUnset && !this.options.noFormPlaceholders
                                    ? [0]
                                    : [],
                                pokedexId: id,
                                defaultFormId: 0,
                                ...this.getGeneration(+id),
                            };
                        }
                        if (!this.skipForms(formName) &&
                            !(this.parsedPokemon[id].defaultFormId === 0 &&
                                formName === 'Normal' &&
                                this.options.skipNormalIfUnset)) {
                            this.parsedForms[formId] = {
                                ...this.parsedForms[formId],
                                formName,
                                proto: name,
                                formId: +formId,
                            };
                            PokemonOverrides_1.default.addFormData(this, formId);
                            if (!this.parsedPokemon[id].forms.includes(+formId)) {
                                if (!this.parsedPokemon[id].forms)
                                    this.parsedPokemon[id].forms = [];
                                this.parsedPokemon[id].forms.push(+formId);
                            }
                            reconcileBaseFormChanges(this.parsedPokemon, this.parsedForms, id);
                        }
                    }
                }
            }
            catch (e) {
                console.warn(e, '\n', proto);
            }
        });
    }
    addExtendedStats(object) {
        const id = pogo_protos_1.Rpc.HoloPokemonId[object.pokemonExtendedSettings.uniqueId];
        if (id) {
            if (!this.parsedPokemon[id]) {
                this.parsedPokemon[id] = {};
            }
            const values = Object.entries(object.pokemonExtendedSettings.sizeSettings).map(([name, value]) => ({ name, value }));
            const protoForm = object.pokemonExtendedSettings.form
                ? typeof object.pokemonExtendedSettings.form === 'number'
                    ? object.pokemonExtendedSettings.form
                    : /^\d+$/.test(object.pokemonExtendedSettings.form)
                        ? +object.pokemonExtendedSettings.form
                        : pogo_protos_1.Rpc.PokemonDisplayProto.Form[object.pokemonExtendedSettings.form]
                : 0;
            if (protoForm) {
                if (!this.parsedForms[protoForm]) {
                    this.parsedForms[protoForm] = {};
                }
                this.parsedForms[protoForm].sizeSettings = values;
            }
            else {
                this.parsedPokemon[id].sizeSettings = values;
            }
        }
    }
    cleanExtendedStats() {
        Object.values(this.parsedPokemon).forEach((pkmn) => {
            if (pkmn.sizeSettings && pkmn.forms) {
                const pkmnSizeTree = Object.fromEntries(pkmn.sizeSettings.map(({ name, value }) => [name, value]));
                pkmn.forms.forEach((formId) => {
                    if (this.parsedForms[formId]?.sizeSettings) {
                        if (this.parsedForms[formId].sizeSettings.every((size) => pkmnSizeTree[size.name] === size.value)) {
                            delete this.parsedForms[formId].sizeSettings;
                        }
                    }
                });
            }
        });
    }
    addFormBaseStats(formId, hp, a, d, sa, sd, sp) {
        if (this.parsedForms[formId].attack ||
            this.parsedForms[formId].defense ||
            this.parsedForms[formId].stamina) {
            console.warn('Base stats already found for', pogo_protos_1.Rpc.PokemonDisplayProto.Form[formId]);
            return;
        }
        this.parsedForms[formId].attack = PokeApi_1.default.attack(a, sa, sp);
        this.parsedForms[formId].defense = PokeApi_1.default.defense(d, sd, sp);
        this.parsedForms[formId].stamina = PokeApi_1.default.stamina(hp);
    }
    addEvolutionQuest(object) {
        try {
            const { evolutionQuestTemplate, templateId } = object;
            this.evolutionQuests[templateId] = {
                questType: pogo_protos_1.Rpc.QuestType[evolutionQuestTemplate.questType],
                target: evolutionQuestTemplate.goals[0].target,
                assetsRef: evolutionQuestTemplate.display.description.toLowerCase(),
            };
            if (this.evolutionQuests[templateId].target) {
                this.evolutionQuests[templateId].assetsRef = this.evolutionQuests[templateId].assetsRef.replace('single', 'plural');
            }
            if (evolutionQuestTemplate.goals.at(1)) {
                console.warn(`Second quest goal detected, fix it. ${templateId}`);
            }
        }
        catch (e) {
            console.warn(e, `Failed to add evolution quest for ${JSON.stringify(object, null, 2)}`);
        }
    }
    addForm(object) {
        if (object.templateId.split('_')[1]) {
            const id = Number(object.templateId.split('_')[1].slice(1));
            try {
                const forms = object.formSettings.forms;
                if (forms) {
                    if (!this.parsedPokemon[id]) {
                        this.parsedPokemon[id] = {};
                    }
                    if (!this.parsedPokemon[id].forms) {
                        this.parsedPokemon[id].forms = [];
                    }
                    for (let i = 0; i < forms.length; i += 1) {
                        const value = forms[i].form;
                        if (!value)
                            continue;
                        const formId = typeof value === 'number'
                            ? value
                            : pogo_protos_1.Rpc.PokemonDisplayProto.Form[value];
                        const form = typeof value === 'number' ? this.lookupForm(value) : value;
                        this.formsRef[form] = object.formSettings.pokemon;
                        const name = this.formName(id, form);
                        if (i === 0) {
                            this.parsedPokemon[id].defaultFormId = formId || 0;
                        }
                        if (!this.skipForms(name)) {
                            this.parsedForms[formId] = {
                                ...this.parsedForms[formId],
                                formName: name,
                                proto: form,
                                formId,
                                isCostume: forms[i].isCostume,
                            };
                        }
                    }
                }
                else {
                    if (!this.parsedPokemon[id]) {
                        this.parsedPokemon[id] = {
                            pokemonName: this.pokemonName(id),
                            forms: [],
                            pokedexId: id,
                            ...this.getGeneration(+id),
                        };
                    }
                }
                reconcileBaseFormChanges(this.parsedPokemon, this.parsedForms, id);
                if (this.options.includeUnset && !this.options.noFormPlaceholders) {
                    this.parsedPokemon[id].forms.push(0);
                }
            }
            catch (e) {
                console.warn(e, '\n', JSON.stringify(object, null, 2));
            }
        }
    }
    addPokemon(object) {
        const { templateId, pokemonSettings } = object;
        const split = templateId.split('_');
        const id = Number(split[0].slice(1));
        try {
            if (!this.parsedPokemon[id]) {
                this.parsedPokemon[id] = {};
            }
            const formId = /^V\d{4}_POKEMON_/.test(templateId)
                ? pogo_protos_1.Rpc.PokemonDisplayProto.Form[templateId.substring('V9999_POKEMON_'.length)]
                : null;
            if (formId) {
                if (!this.parsedPokemon[id].forms) {
                    this.parsedPokemon[id].forms = [];
                }
                const primaryForm = this.parsedPokemon[id];
                const formName = this.formName(id, split.filter((word, i) => i > 1 && word).join('_'));
                if (!this.skipForms(formName)) {
                    this.parsedForms[formId] = {
                        ...this.parsedForms[formId],
                        formName,
                        proto: templateId,
                        formId,
                    };
                    if (!this.parsedPokemon[id].forms.includes(formId)) {
                        this.parsedPokemon[id].forms.push(formId);
                    }
                    const form = this.parsedForms[formId];
                    switch (true) {
                        case pokemonSettings.stats.baseAttack !== primaryForm.attack:
                        case pokemonSettings.stats.baseDefense !== primaryForm.defense:
                        case pokemonSettings.stats.baseStamina !== primaryForm.stamina:
                            form.attack = pokemonSettings.stats.baseAttack;
                            form.defense = pokemonSettings.stats.baseDefense;
                            form.stamina = pokemonSettings.stats.baseStamina;
                    }
                    switch (true) {
                        case pokemonSettings.pokedexHeightM !== primaryForm.height:
                        case pokemonSettings.pokedexWeightKg !== primaryForm.weight:
                            form.height = pokemonSettings.pokedexHeightM;
                            form.weight = pokemonSettings.pokedexWeightKg;
                    }
                    const qMoves = this.getMoves(pokemonSettings.quickMoves);
                    if (!this.compare(qMoves, primaryForm.quickMoves)) {
                        form.quickMoves = qMoves;
                    }
                    const cMoves = this.getMoves(pokemonSettings.cinematicMoves);
                    if (!this.compare(cMoves, primaryForm.chargedMoves)) {
                        form.chargedMoves = cMoves;
                    }
                    const eqMoves = this.getMoves(pokemonSettings.eliteQuickMove);
                    if (!this.compare(eqMoves, primaryForm.eliteQuickMoves)) {
                        form.eliteQuickMoves = eqMoves;
                    }
                    const ecMoves = this.getMoves(pokemonSettings.eliteCinematicMove);
                    if (!this.compare(ecMoves, primaryForm.eliteChargedMoves)) {
                        form.eliteChargedMoves = ecMoves;
                    }
                    const types = this.getTypes([
                        pokemonSettings.type,
                        pokemonSettings.type2,
                    ]);
                    if (!this.compare(types, primaryForm.types)) {
                        form.types = types;
                    }
                    const family = pogo_protos_1.Rpc.HoloPokemonFamilyId[pokemonSettings.familyId];
                    if (family !== primaryForm.family) {
                        form.family = family;
                    }
                    if (pokemonSettings.evolutionBranch?.some((evo) => evo.evolution)) {
                        if (!form.evolutions) {
                            form.evolutions = [];
                        }
                        form.evolutions.push(...this.compileEvos(pokemonSettings.evolutionBranch));
                    }
                    const formChanges = this.compileFormChanges(pokemonSettings.formChange);
                    if (formChanges.length) {
                        form.formChanges = formChanges;
                    }
                    else {
                        delete form.formChanges;
                    }
                    if (pokemonSettings.tempEvoOverrides) {
                        form.tempEvolutions = this.compileTempEvos(pokemonSettings.tempEvoOverrides, pokemonSettings.evolutionBranch, this.parsedPokemon[id]);
                    }
                    if ((form.formName === 'Normal' || form.formName === 'Purified') &&
                        primaryForm.tempEvolutions) {
                        form.tempEvolutions = Object.values(primaryForm.tempEvolutions).map((tempEvo) => tempEvo);
                    }
                    if (pokemonSettings.shadow) {
                        form.purificationDust =
                            pokemonSettings.shadow.purificationStardustNeeded;
                        form.purificationCandy =
                            pokemonSettings.shadow.purificationCandyNeeded;
                    }
                    if (pokemonSettings.allowNoevolveEvolution) {
                        form.costumeOverrideEvos = this.getCostumeOverrides(pokemonSettings.allowNoevolveEvolution);
                    }
                    reconcileBaseFormChanges(this.parsedPokemon, this.parsedForms, id);
                }
            }
            else {
                this.parsedPokemon[id] = {
                    pokemonName: this.pokemonName(id),
                    forms: this.parsedPokemon[id].forms || [],
                    ...this.parsedPokemon[id],
                    pokedexId: id,
                    types: this.getTypes([pokemonSettings.type, pokemonSettings.type2]),
                    attack: pokemonSettings.stats.baseAttack,
                    defense: pokemonSettings.stats.baseDefense,
                    stamina: pokemonSettings.stats.baseStamina,
                    height: pokemonSettings.pokedexHeightM,
                    weight: pokemonSettings.pokedexWeightKg,
                    eliteQuickMoves: this.getMoves(pokemonSettings.eliteQuickMove),
                    eliteChargedMoves: this.getMoves(pokemonSettings.eliteCinematicMove),
                    family: pogo_protos_1.Rpc.HoloPokemonFamilyId[pokemonSettings.familyId],
                    bonusCandyCapture: pokemonSettings.encounter.bonusCandyCaptureReward,
                    bonusStardustCapture: pokemonSettings.encounter.bonusStardustCaptureReward,
                    legendary: pogo_protos_1.Rpc.HoloPokemonClass[pokemonSettings.pokemonClass] === 1,
                    mythic: pogo_protos_1.Rpc.HoloPokemonClass[pokemonSettings.pokemonClass] === 2,
                    ultraBeast: pogo_protos_1.Rpc.HoloPokemonClass[pokemonSettings.pokemonClass] === 3,
                    buddyGroupNumber: pokemonSettings.buddyGroupNumber,
                    buddyDistance: pokemonSettings.kmBuddyDistance,
                    buddyMegaEnergy: pokemonSettings.buddyWalkedMegaEnergyAward,
                    thirdMoveStardust: pokemonSettings.thirdMove.stardustToUnlock,
                    thirdMoveCandy: pokemonSettings.thirdMove.candyToUnlock,
                    gymDefenderEligible: pokemonSettings.isDeployable,
                    tradable: pokemonSettings.isTradable,
                    transferable: pokemonSettings.isTransferable,
                    ...this.getGeneration(id),
                };
                if (id !== 235) {
                    this.parsedPokemon[id].quickMoves = this.getMoves(pokemonSettings.quickMoves);
                    this.parsedPokemon[id].chargedMoves = this.getMoves(pokemonSettings.cinematicMoves);
                }
                else {
                    if (pokemonSettings.quickMoves?.length)
                        console.warn('unexpected Smeargle quick moves', pokemonSettings.quickMoves);
                    if (pokemonSettings.cinematicMoves?.length)
                        console.warn('unexpected Smeargle charged moves', pokemonSettings.cinematicMoves);
                }
                if (pokemonSettings.evolutionBranch?.some((evo) => evo.evolution)) {
                    this.parsedPokemon[id].evolutions = this.compileEvos(pokemonSettings.evolutionBranch);
                }
                const formChanges = this.compileFormChanges(pokemonSettings.formChange);
                if (formChanges.length) {
                    this.parsedPokemon[id].formChanges = formChanges;
                    reconcileBaseFormChanges(this.parsedPokemon, this.parsedForms, id);
                }
                if (pokemonSettings.tempEvoOverrides) {
                    this.parsedPokemon[id].tempEvolutions = this.compileTempEvos(pokemonSettings.tempEvoOverrides, pokemonSettings.evolutionBranch, this.parsedPokemon[id]);
                }
                if (pokemonSettings.allowNoevolveEvolution) {
                    this.parsedPokemon[id].costumeOverrideEvos = this.getCostumeOverrides(pokemonSettings.allowNoevolveEvolution);
                }
                if (pokemonSettings.shadow) {
                    this.parsedPokemon[id].purificationDust =
                        pokemonSettings.shadow.purificationStardustNeeded;
                    this.parsedPokemon[id].purificationCandy =
                        pokemonSettings.shadow.purificationCandyNeeded;
                }
            }
        }
        catch (e) {
            console.warn(e, `Failed to parse Pokemon for ${id}`, JSON.stringify(object, null, 2));
        }
    }
    addSourdoughMoveMappings({ sourdoughMoveMappingSettings: { mappings }, }) {
        for (let i = 0; i < mappings.length; i += 1) {
            const mapping = mappings[i];
            try {
                const id = pogo_protos_1.Rpc.HoloPokemonId[mapping.pokemonId];
                if (!this.parsedPokemon[id]) {
                    this.parsedPokemon[id] = {};
                }
                let target = this.parsedPokemon[id];
                if ('form' in mapping) {
                    const rawForm = mapping.form;
                    const formId = typeof rawForm === 'number'
                        ? rawForm
                        : /^\d+$/.test(rawForm)
                            ? +rawForm
                            : pogo_protos_1.Rpc.PokemonDisplayProto.Form[rawForm];
                    if (!this.parsedPokemon[id].forms) {
                        this.parsedPokemon[id].forms = [];
                    }
                    const formProto = typeof rawForm === 'number'
                        ? this.lookupForm(rawForm)
                        : /^\d+$/.test(rawForm)
                            ? this.lookupForm(+rawForm)
                            : rawForm;
                    const formName = this.formName(id, formProto);
                    if (!this.skipForms(formName)) {
                        this.parsedForms[formId] = {
                            ...this.parsedForms[formId],
                            formName,
                            formId,
                        };
                        if (!this.parsedPokemon[id].forms.includes(formId)) {
                            this.parsedPokemon[id].forms.push(formId);
                        }
                        target = this.parsedForms[formId];
                    }
                }
                target.gmaxMove = pogo_protos_1.Rpc.HoloPokemonMove[mapping.move];
            }
            catch (e) {
                console.warn(e, `Failed to parse gmax move mapping #${i}`, JSON.stringify(mapping, null, 2));
            }
        }
    }
    addSmeargleMovesSettings({ data: { smeargleMovesSettings: { quickMoves, cinematicMoves }, }, }) {
        const id = 235;
        if (!this.parsedPokemon[id]) {
            this.parsedPokemon[id] = {};
        }
        try {
            this.parsedPokemon[id].quickMoves = this.getMoves(quickMoves);
        }
        catch (e) {
            console.warn(e, `Failed to parse smeargle quick move mapping`, JSON.stringify(quickMoves, null, 2));
        }
        try {
            this.parsedPokemon[id].chargedMoves = this.getMoves(cinematicMoves);
        }
        catch (e) {
            console.warn(e, `Failed to parse smeargle charged move mapping`, JSON.stringify(cinematicMoves, null, 2));
        }
    }
    missingPokemon() {
        Object.values(pogo_protos_1.Rpc.HoloPokemonId).forEach((id) => {
            try {
                if (id) {
                    this.parsedPokemon[id] = {
                        pokemonName: this.pokemonName(+id),
                        pokedexId: +id,
                        defaultFormId: 0,
                        types: [],
                        quickMoves: [],
                        chargedMoves: [],
                        eliteQuickMoves: [],
                        eliteChargedMoves: [],
                        ...this.getGeneration(+id),
                        ...this.parsedPokemon[id],
                    };
                    if (!this.parsedPokemon[id].forms) {
                        this.parsedPokemon[id].forms = this.options.noFormPlaceholders
                            ? []
                            : [0];
                    }
                    else if ((this.parsedPokemon[id].forms.length === 0 &&
                        !this.options.noFormPlaceholders) ||
                        this.parsedPokemon[id].defaultFormId === 0) {
                        this.parsedPokemon[id].forms.push(0);
                    }
                    reconcileBaseFormChanges(this.parsedPokemon, this.parsedForms, +id);
                }
            }
            catch (e) {
                console.warn(e, `Failed to parse Future Pokemon for ${id}`);
            }
        });
    }
    sortForms() {
        Object.values(this.parsedPokemon).forEach((pokemon) => {
            try {
                if (pokemon.forms) {
                    pokemon.forms.sort((a, b) => a - b);
                }
            }
            catch (e) {
                console.warn(e, `Failed to sort forms for ${pokemon.pokemonName}`);
            }
        });
    }
    littleCup() {
        try {
            if (this.lcBanList === undefined) {
                console.warn('Missing little cup ban list from Masterfile');
            }
            else {
                this.lcBanList.add('FARFETCHD');
                this.parsedForms[pogo_protos_1.Rpc.PokemonDisplayProto.Form.FARFETCHD_GALARIAN].little = true;
            }
            for (const [id, pokemon] of Object.entries(this.parsedPokemon)) {
                const allowed = !this.evolvedPokemon.has(+id) && pokemon.evolutions !== undefined;
                if (allowed || +id === pogo_protos_1.Rpc.HoloPokemonId.DEERLING) {
                    pokemon.little = true;
                }
            }
        }
        catch (e) {
            console.warn(e, `Failed to parse Little Cup`);
        }
    }
    jungleCup(object) {
        const { combatLeague: { pokemonCondition, bannedPokemon }, } = object;
        pokemonCondition.forEach((condition) => {
            if (condition.type === 'WITH_POKEMON_TYPE') {
                condition.withPokemonType.pokemonType.forEach((type) => {
                    this.jungleCupRules.types.push(pogo_protos_1.Rpc.HoloPokemonType[type]);
                });
            }
        });
        this.jungleCupRules.banned =
            bannedPokemon?.map((poke) => {
                return pogo_protos_1.Rpc.HoloPokemonId[poke];
            }) ?? [];
    }
    jungleEligibility() {
        Object.entries(this.parsedPokemon).forEach(([id, pokemon]) => {
            const allowed = this.jungleCupRules.types.some((type) => pokemon.types.includes(type)) && !this.jungleCupRules.banned.includes(+id);
            if (allowed)
                pokemon.jungle = true;
        });
    }
    makeFormsSeparate() {
        try {
            this.parsedPokeForms = {};
            Object.values(this.parsedPokemon).forEach((pokemon) => {
                if (pokemon.forms) {
                    pokemon.forms.forEach((form) => {
                        this.parsedPokeForms[`${pokemon.pokedexId}_${form}`] = {
                            ...pokemon,
                            evolutions: form === 0 ? pokemon.evolutions : undefined,
                            formChanges: form === 0 ? pokemon.formChanges : undefined,
                            tempEvolutions: form === 0 ? pokemon.tempEvolutions : undefined,
                            ...this.parsedForms[form],
                            forms: [form],
                        };
                    });
                }
            });
        }
        catch (e) {
            console.warn(e, `Failed to make forms separate`);
        }
    }
    parseCostumes() {
        Object.entries(pogo_protos_1.Rpc.PokemonDisplayProto.Costume).forEach((proto) => {
            const [name, id] = proto;
            this.parsedCostumes[id] = {
                id: +id,
                name: this.capitalize(name),
                proto: name,
                noEvolve: name.endsWith('_NOEVOLVE'),
            };
        });
    }
    parsePokeApi(baseStats, tempEvos) {
        if (this.options.includeEstimatedPokemon === true ||
            this.options.includeEstimatedPokemon.baseStats) {
            Object.keys(baseStats).forEach((id) => {
                try {
                    if (!this.parsedPokemon[id]) {
                        this.parsedPokemon[id] = {
                            pokemonName: this.pokemonName(+id),
                            pokedexId: +id,
                            defaultFormId: 0,
                            forms: this.options.includeUnset && !this.options.noFormPlaceholders
                                ? [0]
                                : [],
                            types: [],
                            quickMoves: [],
                            chargedMoves: [],
                            ...this.getGeneration(+id),
                        };
                    }
                    const existing = this.parsedPokemon[id];
                    const baseEntry = baseStats[id];
                    const defaultFormId = this.options.includeUnset && !this.options.noFormPlaceholders
                        ? 0
                        : undefined;
                    const preferActualNumbers = (actual, fallback, label) => {
                        const actualValues = cleanNumberList(actual);
                        const fallbackValues = cleanNumberList(fallback);
                        if (actualValues.length) {
                            if (fallbackValues.length) {
                                const fallbackSet = new Set(fallbackValues);
                                const mismatch = actualValues.length !== fallbackSet.size ||
                                    actualValues.some((value) => !fallbackSet.has(value));
                                if (mismatch) {
                                    console.warn(`[BASE_STATS] Overwriting ${label} for ${id} with Game Master data`);
                                }
                            }
                            return actualValues;
                        }
                        return fallbackValues.length ? fallbackValues : undefined;
                    };
                    const existingEvos = Array.isArray(existing.evolutions)
                        ? existing.evolutions.map((evo) => ({ ...evo }))
                        : [];
                    const resolveFormId = (value) => value !== undefined && value !== null
                        ? value
                        : defaultFormId !== undefined
                            ? defaultFormId
                            : undefined;
                    const resolveFormKey = (value) => {
                        const resolved = resolveFormId(value);
                        return resolved !== undefined ? `${resolved}` : 'unset';
                    };
                    const formEvolutionKeys = new Set();
                    const formEvolutionTargets = new Set();
                    if (Array.isArray(existing.forms)) {
                        existing.forms.forEach((formId) => {
                            const formEvos = this.parsedForms[formId]?.evolutions;
                            if (Array.isArray(formEvos)) {
                                formEvos.forEach((formEvo) => {
                                    const key = `${formEvo.evoId ?? 'unknown'}:${resolveFormKey(formEvo.formId)}`;
                                    formEvolutionKeys.add(key);
                                    formEvolutionTargets.add(`${formEvo.evoId ?? 'unknown'}`);
                                });
                            }
                        });
                    }
                    const baseEvos = Array.isArray(baseEntry.evolutions)
                        ? baseEntry.evolutions.map((evo) => ({
                            evoId: evo.evoId,
                            formId: resolveFormId(evo.formId),
                            key: `${evo.evoId ?? 'unknown'}:${resolveFormKey(evo.formId)}`,
                            targetKey: `${evo.evoId ?? 'unknown'}`,
                            hasSpecificForm: evo.formId !== undefined && evo.formId !== null,
                        }))
                        : [];
                    if (baseEvos.length &&
                        formEvolutionTargets.size &&
                        baseEvos.every((evo) => formEvolutionKeys.has(evo.key) ||
                            (!evo.hasSpecificForm &&
                                formEvolutionTargets.has(evo.targetKey)))) {
                        console.warn(`[BASE_STATS] Dropping PokeApi entry for ${id} because form-specific evolutions exist`);
                        delete baseStats[id];
                        return;
                    }
                    const baseEvosToMerge = baseEvos.map((evo) => ({
                        evoId: evo.evoId,
                        formId: evo.formId,
                    }));
                    if (baseEvosToMerge.length) {
                        const keyFor = (evo) => {
                            const formIdentifier = evo.formId !== undefined && evo.formId !== null
                                ? evo.formId
                                : (defaultFormId ?? 'unset');
                            return `${evo.evoId ?? 'unknown'}:${formIdentifier}`;
                        };
                        const seen = new Set(existingEvos.map((evo) => keyFor(evo)));
                        baseEvosToMerge.forEach((evo) => {
                            const key = keyFor(evo);
                            if (seen.has(key)) {
                                console.warn(`[BASE_STATS] Overwriting evolution for ${id} -> ${evo.evoId ?? 'unknown'}:${evo.formId ?? defaultFormId ?? 'unset'} with Game Master data`);
                            }
                            else {
                                seen.add(key);
                                existingEvos.push(evo);
                            }
                        });
                    }
                    const { _hiddenOnlyChargedMoves, ...cacheEntry } = baseEntry;
                    const actualQuickMoves = cleanNumberList(existing.quickMoves);
                    const actualChargedMoves = cleanNumberList(existing.chargedMoves);
                    const fallbackQuickMoves = cleanNumberList(cacheEntry.quickMoves);
                    const fallbackChargedMoves = cleanNumberList(cacheEntry.chargedMoves);
                    const sanitizedFallbackChargedMoves = fallbackChargedMoves.filter((move) => !excludedPlaceholderFallbackChargedMoves.has(move));
                    const hasHiddenOnlyFallbackChargedMoves = _hiddenOnlyChargedMoves === true;
                    const preferEstimatedPlaceholderQuickMoves = shouldPreferEstimatedPlaceholderQuickMoves(actualQuickMoves, actualChargedMoves, fallbackQuickMoves);
                    const shouldDropPlaceholderChargedMoves = preferEstimatedPlaceholderQuickMoves &&
                        (fallbackChargedMoves.length > 0 ||
                            hasHiddenOnlyFallbackChargedMoves) &&
                        sanitizedFallbackChargedMoves.length === 0;
                    const preferEstimatedPlaceholderChargedMoves = preferEstimatedPlaceholderQuickMoves &&
                        sanitizedFallbackChargedMoves.length > 0;
                    if (preferEstimatedPlaceholderQuickMoves) {
                        console.warn(`[BASE_STATS] Replacing placeholder moves for ${id} with PokeApi data`);
                    }
                    const quickMoves = preferEstimatedPlaceholderQuickMoves
                        ? fallbackQuickMoves
                        : (preferActualNumbers(existing.quickMoves, cacheEntry.quickMoves, 'quick moves') ?? (actualQuickMoves.length ? actualQuickMoves : undefined));
                    const chargedMoves = preferEstimatedPlaceholderChargedMoves
                        ? sanitizedFallbackChargedMoves
                        : shouldDropPlaceholderChargedMoves
                            ? undefined
                            : (preferActualNumbers(existing.chargedMoves, sanitizedFallbackChargedMoves, 'charged moves') ??
                                (actualChargedMoves.length ? actualChargedMoves : undefined));
                    const types = preferActualNumbers(existing.types, cacheEntry.types, 'types') ??
                        (Array.isArray(existing.types) && existing.types.length
                            ? Array.from(new Set(existing.types))
                            : undefined);
                    this.parsedPokemon[id] = {
                        ...cacheEntry,
                        ...existing,
                        pokemonName: existing.pokemonName || cacheEntry.pokemonName,
                        quickMoves,
                        chargedMoves,
                        types,
                        evolutions: existingEvos.length ? existingEvos : undefined,
                    };
                }
                catch (e) {
                    console.warn(e, `Failed to parse base stats for ${id}`);
                }
            });
            PokemonOverrides_1.default.addEvos(this.parsedForms);
        }
        Object.keys(tempEvos).forEach((category) => {
            try {
                if (this.options.includeEstimatedPokemon === true ||
                    this.options.includeEstimatedPokemon[category]) {
                    Object.keys(tempEvos[category]).forEach((id) => {
                        try {
                            const tempEvolutions = (0, tempEvolutions_1.mergeTempEvolutions)(tempEvos[category][id].tempEvolutions, this.parsedPokemon[id].tempEvolutions);
                            this.parsedPokemon[id] = {
                                ...this.parsedPokemon[id],
                                tempEvolutions,
                            };
                            if (this.parsedPokemon[id].forms) {
                                this.parsedPokemon[id].forms.forEach((form) => {
                                    if (this.parsedForms[form].formName === 'Normal' ||
                                        this.parsedForms[form].formName === 'Purified') {
                                        this.parsedForms[form].tempEvolutions = tempEvolutions;
                                    }
                                });
                            }
                        }
                        catch (e) {
                            console.warn(e, `Failed to parse temp evos for ${category}-${id}`);
                        }
                    });
                }
            }
            catch (e) {
                console.warn(e, `Failed to parse temp evos for ${category}`);
            }
        });
    }
}
exports.default = Pokemon;