[Refactor] Refactor data/pokemon-species.ts (#4054)

* Setting species-variables to read only

* set generations to protected

* formIndex set to protected

* quick fix

* typedocs fixes

* get / set generation

* wait

* Use get/set for formIndex too

* Fix misplaced line

* Replace a couple `!!` with default params

---------

Co-authored-by: frutescens <info@laptop>
Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
Co-authored-by: Tempoanon <163687446+Tempo-anon@users.noreply.github.com>
This commit is contained in:
Mumble 2024-11-02 20:11:24 -07:00 committed by GitHub
parent c31657d952
commit 70ddc29e86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 82 additions and 63 deletions

View File

@ -4465,7 +4465,7 @@ export class FormChangeItemTypeAttr extends VariableMoveTypeAttr {
} }
if ([ user.species.speciesId, user.fusionSpecies?.speciesId ].includes(Species.ARCEUS) || [ user.species.speciesId, user.fusionSpecies?.speciesId ].includes(Species.SILVALLY)) { if ([ user.species.speciesId, user.fusionSpecies?.speciesId ].includes(Species.ARCEUS) || [ user.species.speciesId, user.fusionSpecies?.speciesId ].includes(Species.SILVALLY)) {
const form = user.species.speciesId === Species.ARCEUS || user.species.speciesId === Species.SILVALLY ? user.formIndex : user.fusionSpecies?.formIndex!; // TODO: is this bang correct? const form = user.species.speciesId === Species.ARCEUS || user.species.speciesId === Species.SILVALLY ? user.formIndex : user.fusionSpecies?.formIndex!;
moveType.value = Type[Type[form]]; moveType.value = Type[Type[form]];
return true; return true;

View File

@ -47,7 +47,7 @@ export function getPokemonSpecies(species: Species | Species[] | undefined): Pok
return allSpecies[species - 1]; return allSpecies[species - 1];
} }
export function getPokemonSpeciesForm(species: Species, formIndex: integer): PokemonSpeciesForm { export function getPokemonSpeciesForm(species: Species, formIndex: number): PokemonSpeciesForm {
const retSpecies: PokemonSpecies = species >= 2000 const retSpecies: PokemonSpecies = species >= 2000
? allSpecies.find(s => s.speciesId === species)! // TODO: is the bang correct? ? allSpecies.find(s => s.speciesId === species)! // TODO: is the bang correct?
: allSpecies[species - 1]; : allSpecies[species - 1];
@ -129,26 +129,27 @@ export type PokemonSpeciesFilter = (species: PokemonSpecies) => boolean;
export abstract class PokemonSpeciesForm { export abstract class PokemonSpeciesForm {
public speciesId: Species; public speciesId: Species;
public formIndex: integer; protected _formIndex: number;
public generation: integer; protected _generation: number;
public type1: Type; readonly type1: Type;
public type2: Type | null; readonly type2: Type | null;
public height: number; readonly height: number;
public weight: number; readonly weight: number;
public ability1: Abilities; readonly ability1: Abilities;
public ability2: Abilities; readonly ability2: Abilities;
public abilityHidden: Abilities; readonly abilityHidden: Abilities;
public baseTotal: integer; readonly baseTotal: number;
public baseStats: integer[]; readonly baseStats: number[];
public catchRate: integer; readonly catchRate: number;
public baseFriendship: integer; readonly baseFriendship: number;
public baseExp: integer; readonly baseExp: number;
public genderDiffs: boolean; readonly genderDiffs: boolean;
public isStarterSelectable: boolean; readonly isStarterSelectable: boolean;
constructor(type1: Type, type2: Type | null, height: number, weight: number, ability1: Abilities, ability2: Abilities, abilityHidden: Abilities, constructor(type1: Type, type2: Type | null, height: number, weight: number, ability1: Abilities, ability2: Abilities, abilityHidden: Abilities,
baseTotal: integer, baseHp: integer, baseAtk: integer, baseDef: integer, baseSpatk: integer, baseSpdef: integer, baseSpd: integer, baseTotal: number, baseHp: number, baseAtk: number, baseDef: number, baseSpatk: number, baseSpdef: number, baseSpd: number,
catchRate: integer, baseFriendship: integer, baseExp: integer, genderDiffs: boolean, isStarterSelectable: boolean) { catchRate: number, baseFriendship: number, baseExp: number, genderDiffs: boolean, isStarterSelectable: boolean
) {
this.type1 = type1; this.type1 = type1;
this.type2 = type2; this.type2 = type2;
this.height = height; this.height = height;
@ -180,7 +181,23 @@ export abstract class PokemonSpeciesForm {
return ret; return ret;
} }
isOfType(type: integer): boolean { get generation(): number {
return this._generation;
}
set generation(generation: number) {
this._generation = generation;
}
get formIndex(): number {
return this._formIndex;
}
set formIndex(formIndex: number) {
this._formIndex = formIndex;
}
isOfType(type: number): boolean {
return this.type1 === type || (this.type2 !== null && this.type2 === type); return this.type1 === type || (this.type2 !== null && this.type2 === type);
} }
@ -188,7 +205,7 @@ export abstract class PokemonSpeciesForm {
* Method to get the total number of abilities a Pokemon species has. * Method to get the total number of abilities a Pokemon species has.
* @returns Number of abilities * @returns Number of abilities
*/ */
getAbilityCount(): integer { getAbilityCount(): number {
return this.abilityHidden !== Abilities.NONE ? 3 : 2; return this.abilityHidden !== Abilities.NONE ? 3 : 2;
} }
@ -197,7 +214,7 @@ export abstract class PokemonSpeciesForm {
* @param abilityIndex Which ability to get (should only be 0-2) * @param abilityIndex Which ability to get (should only be 0-2)
* @returns The id of the Ability * @returns The id of the Ability
*/ */
getAbility(abilityIndex: integer): Abilities { getAbility(abilityIndex: number): Abilities {
let ret: Abilities; let ret: Abilities;
if (abilityIndex === 0) { if (abilityIndex === 0) {
ret = this.ability1; ret = this.ability1;
@ -277,12 +294,12 @@ export abstract class PokemonSpeciesForm {
return ret; return ret;
} }
getSpriteAtlasPath(female: boolean, formIndex?: integer, shiny?: boolean, variant?: integer): string { getSpriteAtlasPath(female: boolean, formIndex?: number, shiny?: boolean, variant?: number): string {
const spriteId = this.getSpriteId(female, formIndex, shiny, variant).replace(/\_{2}/g, "/"); const spriteId = this.getSpriteId(female, formIndex, shiny, variant).replace(/\_{2}/g, "/");
return `${/_[1-3]$/.test(spriteId) ? "variant/" : ""}${spriteId}`; return `${/_[1-3]$/.test(spriteId) ? "variant/" : ""}${spriteId}`;
} }
getSpriteId(female: boolean, formIndex?: integer, shiny?: boolean, variant: integer = 0, back?: boolean): string { getSpriteId(female: boolean, formIndex?: number, shiny?: boolean, variant: number = 0, back?: boolean): string {
if (formIndex === undefined || this instanceof PokemonForm) { if (formIndex === undefined || this instanceof PokemonForm) {
formIndex = this.formIndex; formIndex = this.formIndex;
} }
@ -299,11 +316,11 @@ export abstract class PokemonSpeciesForm {
return `${back ? "back__" : ""}${shiny && (!variantSet || (!variant && !variantSet[variant || 0])) ? "shiny__" : ""}${baseSpriteKey}${shiny && variantSet && variantSet[variant] === 2 ? `_${variant + 1}` : ""}`; return `${back ? "back__" : ""}${shiny && (!variantSet || (!variant && !variantSet[variant || 0])) ? "shiny__" : ""}${baseSpriteKey}${shiny && variantSet && variantSet[variant] === 2 ? `_${variant + 1}` : ""}`;
} }
getSpriteKey(female: boolean, formIndex?: integer, shiny?: boolean, variant?: integer): string { getSpriteKey(female: boolean, formIndex?: number, shiny?: boolean, variant?: number): string {
return `pkmn__${this.getSpriteId(female, formIndex, shiny, variant)}`; return `pkmn__${this.getSpriteId(female, formIndex, shiny, variant)}`;
} }
abstract getFormSpriteKey(formIndex?: integer): string; abstract getFormSpriteKey(formIndex?: number): string;
/** /**
@ -311,9 +328,9 @@ export abstract class PokemonSpeciesForm {
* @param formIndex optional form index for pokemon with different forms * @param formIndex optional form index for pokemon with different forms
* @returns species id if no additional forms, index with formkey if a pokemon with a form * @returns species id if no additional forms, index with formkey if a pokemon with a form
*/ */
getVariantDataIndex(formIndex?: integer) { getVariantDataIndex(formIndex?: number) {
let formkey: string | null = null; let formkey: string | null = null;
let variantDataIndex: integer | string = this.speciesId; let variantDataIndex: number | string = this.speciesId;
const species = getPokemonSpecies(this.speciesId); const species = getPokemonSpecies(this.speciesId);
if (species.forms.length > 0 && formIndex !== undefined) { if (species.forms.length > 0 && formIndex !== undefined) {
formkey = species.forms[formIndex]?.getFormSpriteKey(formIndex); formkey = species.forms[formIndex]?.getFormSpriteKey(formIndex);
@ -324,13 +341,13 @@ export abstract class PokemonSpeciesForm {
return variantDataIndex; return variantDataIndex;
} }
getIconAtlasKey(formIndex?: integer, shiny?: boolean, variant?: integer): string { getIconAtlasKey(formIndex?: number, shiny?: boolean, variant?: number): string {
const variantDataIndex = this.getVariantDataIndex(formIndex); const variantDataIndex = this.getVariantDataIndex(formIndex);
const isVariant = shiny && variantData[variantDataIndex] && (variant !== undefined && variantData[variantDataIndex][variant]); const isVariant = shiny && variantData[variantDataIndex] && (variant !== undefined && variantData[variantDataIndex][variant]);
return `pokemon_icons_${this.generation}${isVariant ? "v" : ""}`; return `pokemon_icons_${this.generation}${isVariant ? "v" : ""}`;
} }
getIconId(female: boolean, formIndex?: integer, shiny?: boolean, variant?: integer): string { getIconId(female: boolean, formIndex?: number, shiny?: boolean, variant?: number): string {
if (formIndex === undefined) { if (formIndex === undefined) {
formIndex = this.formIndex; formIndex = this.formIndex;
} }
@ -379,7 +396,7 @@ export abstract class PokemonSpeciesForm {
return ret; return ret;
} }
getCryKey(formIndex?: integer): string { getCryKey(formIndex?: number): string {
let speciesId = this.speciesId; let speciesId = this.speciesId;
if (this.speciesId > 2000) { if (this.speciesId > 2000) {
switch (this.speciesId) { switch (this.speciesId) {
@ -446,7 +463,7 @@ export abstract class PokemonSpeciesForm {
return ret; return ret;
} }
validateStarterMoveset(moveset: StarterMoveset, eggMoves: integer): boolean { validateStarterMoveset(moveset: StarterMoveset, eggMoves: number): boolean {
const rootSpeciesId = this.getRootSpeciesId(); const rootSpeciesId = this.getRootSpeciesId();
for (const moveId of moveset) { for (const moveId of moveset) {
if (speciesEggMoves.hasOwnProperty(rootSpeciesId)) { if (speciesEggMoves.hasOwnProperty(rootSpeciesId)) {
@ -467,7 +484,7 @@ export abstract class PokemonSpeciesForm {
return true; return true;
} }
loadAssets(scene: BattleScene, female: boolean, formIndex?: integer, shiny?: boolean, variant?: Variant, startLoad?: boolean): Promise<void> { loadAssets(scene: BattleScene, female: boolean, formIndex?: number, shiny?: boolean, variant?: Variant, startLoad?: boolean): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
const spriteKey = this.getSpriteKey(female, formIndex, shiny, variant); const spriteKey = this.getSpriteKey(female, formIndex, shiny, variant);
scene.loadPokemonAtlas(spriteKey, this.getSpriteAtlasPath(female, formIndex, shiny, variant)); scene.loadPokemonAtlas(spriteKey, this.getSpriteAtlasPath(female, formIndex, shiny, variant));
@ -536,7 +553,7 @@ export abstract class PokemonSpeciesForm {
return cry; return cry;
} }
generateCandyColors(scene: BattleScene): integer[][] { generateCandyColors(scene: BattleScene): number[][] {
const sourceTexture = scene.textures.get(this.getSpriteKey(false)); const sourceTexture = scene.textures.get(this.getSpriteKey(false));
const sourceFrame = sourceTexture.frames[sourceTexture.firstFrame]; const sourceFrame = sourceTexture.frames[sourceTexture.firstFrame];
@ -544,7 +561,7 @@ export abstract class PokemonSpeciesForm {
const canvas = document.createElement("canvas"); const canvas = document.createElement("canvas");
const spriteColors: integer[][] = []; const spriteColors: number[][] = [];
const context = canvas.getContext("2d"); const context = canvas.getContext("2d");
const frame = sourceFrame; const frame = sourceFrame;
@ -567,7 +584,7 @@ export abstract class PokemonSpeciesForm {
} }
for (let i = 0; i < pixelData.length; i += 4) { for (let i = 0; i < pixelData.length; i += 4) {
const total = pixelData.slice(i, i + 3).reduce((total: integer, value: integer) => total + value, 0); const total = pixelData.slice(i, i + 3).reduce((total: number, value: number) => total + value, 0);
if (!total) { if (!total) {
continue; continue;
} }
@ -586,27 +603,28 @@ export abstract class PokemonSpeciesForm {
Math.random = originalRandom; Math.random = originalRandom;
return Array.from(paletteColors.keys()).map(c => Object.values(rgbaFromArgb(c)) as integer[]); return Array.from(paletteColors.keys()).map(c => Object.values(rgbaFromArgb(c)) as number[]);
} }
} }
export default class PokemonSpecies extends PokemonSpeciesForm implements Localizable { export default class PokemonSpecies extends PokemonSpeciesForm implements Localizable {
public name: string; public name: string;
public subLegendary: boolean; readonly subLegendary: boolean;
public legendary: boolean; readonly legendary: boolean;
public mythical: boolean; readonly mythical: boolean;
public species: string; readonly species: string;
public growthRate: GrowthRate; readonly growthRate: GrowthRate;
public malePercent: number | null; readonly malePercent: number | null;
public genderDiffs: boolean; readonly genderDiffs: boolean;
public canChangeForm: boolean; readonly canChangeForm: boolean;
public forms: PokemonForm[]; readonly forms: PokemonForm[];
constructor(id: Species, generation: integer, subLegendary: boolean, legendary: boolean, mythical: boolean, species: string, constructor(id: Species, generation: number, subLegendary: boolean, legendary: boolean, mythical: boolean, species: string,
type1: Type, type2: Type | null, height: number, weight: number, ability1: Abilities, ability2: Abilities, abilityHidden: Abilities, type1: Type, type2: Type | null, height: number, weight: number, ability1: Abilities, ability2: Abilities, abilityHidden: Abilities,
baseTotal: integer, baseHp: integer, baseAtk: integer, baseDef: integer, baseSpatk: integer, baseSpdef: integer, baseSpd: integer, baseTotal: number, baseHp: number, baseAtk: number, baseDef: number, baseSpatk: number, baseSpdef: number, baseSpd: number,
catchRate: integer, baseFriendship: integer, baseExp: integer, growthRate: GrowthRate, malePercent: number | null, catchRate: number, baseFriendship: number, baseExp: number, growthRate: GrowthRate, malePercent: number | null,
genderDiffs: boolean, canChangeForm?: boolean, ...forms: PokemonForm[]) { genderDiffs: boolean, canChangeForm?: boolean, ...forms: PokemonForm[]
) {
super(type1, type2, height, weight, ability1, ability2, abilityHidden, baseTotal, baseHp, baseAtk, baseDef, baseSpatk, baseSpdef, baseSpd, super(type1, type2, height, weight, ability1, ability2, abilityHidden, baseTotal, baseHp, baseAtk, baseDef, baseSpatk, baseSpdef, baseSpd,
catchRate, baseFriendship, baseExp, genderDiffs, false); catchRate, baseFriendship, baseExp, genderDiffs, false);
this.speciesId = id; this.speciesId = id;
@ -631,7 +649,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
}); });
} }
getName(formIndex?: integer): string { getName(formIndex?: number): string {
if (formIndex !== undefined && this.forms.length) { if (formIndex !== undefined && this.forms.length) {
const form = this.forms[formIndex]; const form = this.forms[formIndex];
let key: string | null; let key: string | null;
@ -662,11 +680,11 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
this.name = i18next.t(`pokemon:${Species[this.speciesId].toLowerCase()}`); this.name = i18next.t(`pokemon:${Species[this.speciesId].toLowerCase()}`);
} }
getWildSpeciesForLevel(level: integer, allowEvolving: boolean, isBoss: boolean, gameMode: GameMode): Species { getWildSpeciesForLevel(level: number, allowEvolving: boolean, isBoss: boolean, gameMode: GameMode): Species {
return this.getSpeciesForLevel(level, allowEvolving, false, (isBoss ? PartyMemberStrength.WEAKER : PartyMemberStrength.AVERAGE) + (gameMode?.isEndless ? 1 : 0)); return this.getSpeciesForLevel(level, allowEvolving, false, (isBoss ? PartyMemberStrength.WEAKER : PartyMemberStrength.AVERAGE) + (gameMode?.isEndless ? 1 : 0));
} }
getTrainerSpeciesForLevel(level: integer, allowEvolving: boolean = false, strength: PartyMemberStrength, currentWave: number = 0): Species { getTrainerSpeciesForLevel(level: number, allowEvolving: boolean = false, strength: PartyMemberStrength, currentWave: number = 0): Species {
return this.getSpeciesForLevel(level, allowEvolving, true, strength, currentWave); return this.getSpeciesForLevel(level, allowEvolving, true, strength, currentWave);
} }
@ -688,7 +706,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
* @param strength {@linkcode PartyMemberStrength} The strength of the party member in question * @param strength {@linkcode PartyMemberStrength} The strength of the party member in question
* @returns {@linkcode integer} The level difference from expected evolution level tolerated for a mon to be unevolved. Lower value = higher evolution chance. * @returns {@linkcode integer} The level difference from expected evolution level tolerated for a mon to be unevolved. Lower value = higher evolution chance.
*/ */
private getStrengthLevelDiff(strength: PartyMemberStrength): integer { private getStrengthLevelDiff(strength: PartyMemberStrength): number {
switch (Math.min(strength, PartyMemberStrength.STRONGER)) { switch (Math.min(strength, PartyMemberStrength.STRONGER)) {
case PartyMemberStrength.WEAKEST: case PartyMemberStrength.WEAKEST:
return 60; return 60;
@ -705,7 +723,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
} }
} }
getSpeciesForLevel(level: integer, allowEvolving: boolean = false, forTrainer: boolean = false, strength: PartyMemberStrength = PartyMemberStrength.WEAKER, currentWave: number = 0): Species { getSpeciesForLevel(level: number, allowEvolving: boolean = false, forTrainer: boolean = false, strength: PartyMemberStrength = PartyMemberStrength.WEAKER, currentWave: number = 0): Species {
const prevolutionLevels = this.getPrevolutionLevels(); const prevolutionLevels = this.getPrevolutionLevels();
if (prevolutionLevels.length) { if (prevolutionLevels.length) {
@ -847,7 +865,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
} }
// This could definitely be written better and more accurate to the getSpeciesForLevel logic, but it is only for generating movesets for evolved Pokemon // This could definitely be written better and more accurate to the getSpeciesForLevel logic, but it is only for generating movesets for evolved Pokemon
getSimulatedEvolutionChain(currentLevel: integer, forTrainer: boolean = false, isBoss: boolean = false, player: boolean = false): EvolutionLevel[] { getSimulatedEvolutionChain(currentLevel: number, forTrainer: boolean = false, isBoss: boolean = false, player: boolean = false): EvolutionLevel[] {
const ret: EvolutionLevel[] = []; const ret: EvolutionLevel[] = [];
if (pokemonPrevolutions.hasOwnProperty(this.speciesId)) { if (pokemonPrevolutions.hasOwnProperty(this.speciesId)) {
const prevolutionLevels = this.getPrevolutionLevels().reverse(); const prevolutionLevels = this.getPrevolutionLevels().reverse();
@ -899,7 +917,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
return variantData.hasOwnProperty(variantDataIndex) || variantData.hasOwnProperty(this.speciesId); return variantData.hasOwnProperty(variantDataIndex) || variantData.hasOwnProperty(this.speciesId);
} }
getFormSpriteKey(formIndex?: integer) { getFormSpriteKey(formIndex?: number) {
if (this.forms.length && (formIndex !== undefined && formIndex >= this.forms.length)) { if (this.forms.length && (formIndex !== undefined && formIndex >= this.forms.length)) {
console.warn(`Attempted accessing form with index ${formIndex} of species ${this.getName()} with only ${this.forms.length || 0} forms`); console.warn(`Attempted accessing form with index ${formIndex} of species ${this.getName()} with only ${this.forms.length || 0} forms`);
formIndex = Math.min(formIndex, this.forms.length - 1); formIndex = Math.min(formIndex, this.forms.length - 1);
@ -919,16 +937,17 @@ export class PokemonForm extends PokemonSpeciesForm {
private starterSelectableKeys: string[] = [ "10", "50", "10-pc", "50-pc", "red", "orange", "yellow", "green", "blue", "indigo", "violet" ]; private starterSelectableKeys: string[] = [ "10", "50", "10-pc", "50-pc", "red", "orange", "yellow", "green", "blue", "indigo", "violet" ];
constructor(formName: string, formKey: string, type1: Type, type2: Type | null, height: number, weight: number, ability1: Abilities, ability2: Abilities, abilityHidden: Abilities, constructor(formName: string, formKey: string, type1: Type, type2: Type | null, height: number, weight: number, ability1: Abilities, ability2: Abilities, abilityHidden: Abilities,
baseTotal: integer, baseHp: integer, baseAtk: integer, baseDef: integer, baseSpatk: integer, baseSpdef: integer, baseSpd: integer, baseTotal: number, baseHp: number, baseAtk: number, baseDef: number, baseSpatk: number, baseSpdef: number, baseSpd: number,
catchRate: integer, baseFriendship: integer, baseExp: integer, genderDiffs?: boolean, formSpriteKey?: string | null, isStarterSelectable?: boolean, ) { catchRate: number, baseFriendship: number, baseExp: number, genderDiffs: boolean = false, formSpriteKey: string | null = null, isStarterSelectable: boolean = false
) {
super(type1, type2, height, weight, ability1, ability2, abilityHidden, baseTotal, baseHp, baseAtk, baseDef, baseSpatk, baseSpdef, baseSpd, super(type1, type2, height, weight, ability1, ability2, abilityHidden, baseTotal, baseHp, baseAtk, baseDef, baseSpatk, baseSpdef, baseSpd,
catchRate, baseFriendship, baseExp, !!genderDiffs, (!!isStarterSelectable || !formKey)); catchRate, baseFriendship, baseExp, genderDiffs, (isStarterSelectable || !formKey));
this.formName = formName; this.formName = formName;
this.formKey = formKey; this.formKey = formKey;
this.formSpriteKey = formSpriteKey !== undefined ? formSpriteKey : null; this.formSpriteKey = formSpriteKey;
} }
getFormSpriteKey(_formIndex?: integer) { getFormSpriteKey(_formIndex?: number) {
return this.formSpriteKey !== null ? this.formSpriteKey : this.formKey; return this.formSpriteKey !== null ? this.formSpriteKey : this.formKey;
} }
} }