diff --git a/sim/dex-data.ts b/sim/dex-data.ts index 033a8b28a720..4d679c356918 100644 --- a/sim/dex-data.ts +++ b/sim/dex-data.ts @@ -6,6 +6,9 @@ */ import {Utils} from '../lib'; +/** Unfortunately we do for..in too much to want to deal with the casts */ +export interface DexTable {[id: string]: T} + /** * Converts anything to an ID. An ID must have only lowercase alphanumeric * characters. @@ -210,6 +213,7 @@ export interface TypeData { HPivs?: SparseStatsTable; isNonstandard?: Nonstandard | null; } +const TYPE_DATA_KEYS: readonly (keyof TypeData)[] = Object.freeze(['damageTaken', 'HPivs', 'HPdvs', 'isNonstandard']); export type ModdedTypeData = TypeData | Partial> & {inherit: true}; export interface TypeDataTable {[typeid: IDEntry]: TypeData} @@ -285,15 +289,61 @@ export class DexTypes { allCache: readonly TypeInfo[]; namesCache: readonly string[]; - constructor(dex: ModdedDex) { + constructor(dex: ModdedDex, patches: ModdedTypeDataTable, parent?: DexTypes) { this.dex = dex; + + let patchesEmpty = true; + for (const k in patches) { // eslint-disable-line @typescript-eslint/no-unused-vars + patchesEmpty = false; + break; + } + if (parent && patchesEmpty) { + this.allCache = parent.allCache; + this.namesCache = parent.namesCache; + this.typeCache = parent.typeCache; + return; + } const allCache = []; const namesCache = []; - for (const _id in this.dex.data.TypeChart) { + if (parent) { + for (const parentType of parent.all()) { + const id = parentType.id; + const patchEntry = patches[id]; + // null means don't inherit + if (patchEntry === null) { + delete patches[id]; + continue; + } + let type; + // if patchEntry present, construct + // else re-use parent's object + if (patchEntry) { + // if inherit, copy fields from parent into child + if ('inherit' in patchEntry && patchEntry.inherit === true) { + delete (patchEntry as any).inherit; + for (const field of TYPE_DATA_KEYS) { + if (field in patchEntry) continue; + // nonsense to appease tsc. + (patchEntry as any)[field] = parentType[field]; + } + // patchEntry is now a complete TypeData + } + type = new TypeInfo({name: parentType.name, id, ...patchEntry}); + type = dex.deepFreeze(type); + delete patches[id]; + } else { + type = parentType; + } + this.typeCache.set(id, type); + allCache.push(type); + if (!type.isNonstandard) namesCache.push(type.name); + } + } + for (const _id in patches) { const id = _id as ID; const typeName = id.charAt(0).toUpperCase() + id.substr(1); - const type = new TypeInfo({name: typeName, id, ...this.dex.data.TypeChart[id]}); - this.typeCache.set(id, this.dex.deepFreeze(type)); + const type = new TypeInfo({name: typeName, id, ...patches[id]}); + this.typeCache.set(id, dex.deepFreeze(type)); allCache.push(type); if (!type.isNonstandard) namesCache.push(type.name); } diff --git a/sim/dex.ts b/sim/dex.ts index 37f71a71d839..2c07ea03b88c 100644 --- a/sim/dex.ts +++ b/sim/dex.ts @@ -31,6 +31,8 @@ import * as fs from 'fs'; import * as path from 'path'; import * as Data from './dex-data'; +import {DexTable} from './dex-data'; +export {DexTable} from './dex-data'; import {Condition, DexConditions} from './dex-conditions'; import {DataMove, DexMoves} from './dex-moves'; import {Item, DexItems} from './dex-items'; @@ -78,8 +80,6 @@ const DATA_FILES = { TypeChart: 'typechart', }; -/** Unfortunately we do for..in too much to want to deal with the casts */ -export interface DexTable {[id: string]: T} export interface AliasesTable {[id: IDEntry]: string} interface DexTableData { @@ -95,7 +95,7 @@ interface DexTableData { PokemonGoData: DexTable; Scripts: DexTable; Conditions: DexTable; - TypeChart: DexTable; + TypeChart: import('./dex-data').ModdedTypeDataTable; } interface TextTableData { Abilities: DexTable; @@ -185,6 +185,7 @@ export class ModdedDex { if (parentDex) { dataCache['Aliases'] = parentDex.data['Aliases']; for (const dataType of DATA_TYPES) { + if (dataType === 'TypeChart') continue; // ported to CoW const parentTypedData: DexTable = parentDex.data[dataType]; const childTypedData: DexTable = dataCache[dataType] || (dataCache[dataType] = {}); for (const entryId in parentTypedData) { @@ -225,7 +226,8 @@ export class ModdedDex { this.species = new DexSpecies(this); this.conditions = new DexConditions(this); this.natures = new Data.DexNatures(this); - this.types = new Data.DexTypes(this); + this.types = new Data.DexTypes(this, dataCache.TypeChart, parentDex?.types); + delete dataCache.TypeChart; this.stats = new Data.DexStats(this); } @@ -258,6 +260,7 @@ export class ModdedDex { } modData(dataType: DataType, id: string) { + if (dataType === 'TypeChart') throw new Error("todo: modify modData"); if (this.isBase) return this.data[dataType][id]; if (this.data[dataType][id] !== this.mod(this.parentMod).data[dataType][id]) return this.data[dataType][id]; return (this.data[dataType][id] = Utils.deepClone(this.data[dataType][id]));