diff --git a/src/battle-scene.ts b/src/battle-scene.ts index f117615e5..0f4700653 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1,8 +1,8 @@ import Phaser from 'phaser'; -import UI, { Mode } from './ui/ui'; +import UI from './ui/ui'; import { NextEncounterPhase, NewBiomeEncounterPhase, SelectBiomePhase, MessagePhase, TurnInitPhase, ReturnPhase, LevelCapPhase, ShowTrainerPhase, LoginPhase, MovePhase, TitlePhase, SwitchPhase } from './phases'; import Pokemon, { PlayerPokemon, EnemyPokemon } from './field/pokemon'; -import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies, initSpecies, speciesStarters } from './data/pokemon-species'; +import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies, initSpecies } from './data/pokemon-species'; import * as Utils from './utils'; import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier } from './modifier/modifier'; import { PokeballType } from './data/pokeball'; @@ -12,7 +12,6 @@ import { initGameSpeed } from './system/game-speed'; import { Biome } from "./data/enums/biome"; import { Arena, ArenaBase } from './field/arena'; import { GameData, PlayerGender } from './system/game-data'; -import StarterSelectUiHandler from './ui/starter-select-ui-handler'; import { TextStyle, addTextObject } from './ui/text'; import { Moves } from "./data/enums/moves"; import { allMoves } from "./data/move"; @@ -20,7 +19,6 @@ import { initMoves } from './data/move'; import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getPartyLuckValue } from './modifier/modifier-type'; import AbilityBar from './ui/ability-bar'; import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from './data/ability'; -import { Abilities } from "./data/enums/abilities"; import { allAbilities } from "./data/ability"; import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle'; import { GameMode, GameModes, gameModes } from './game-mode'; @@ -33,9 +31,6 @@ import TrainerData from './system/trainer-data'; import SoundFade from 'phaser3-rex-plugins/plugins/soundfade'; import { pokemonPrevolutions } from './data/pokemon-evolutions'; import PokeballTray from './ui/pokeball-tray'; -import { Setting, settingOptions } from './system/settings'; -import SettingsUiHandler from './ui/settings-ui-handler'; -import MessageUiHandler from './ui/message-ui-handler'; import { Species } from './data/enums/species'; import InvertPostFX from './pipelines/invert'; import { Achv, ModifierAchv, MoneyAchv, achvs } from './system/achv'; @@ -60,8 +55,8 @@ import CandyBar from './ui/candy-bar'; import { Variant, variantData } from './data/variant'; import { Localizable } from './plugins/i18n'; import { STARTING_WAVE_OVERRIDE, OPP_SPECIES_OVERRIDE, SEED_OVERRIDE, STARTING_BIOME_OVERRIDE, DOUBLE_BATTLE_OVERRIDE } from './overrides'; -import {InputsController} from "./inputs-controller"; -import {UiInputs} from "./ui-inputs"; +import { InputsController } from "./inputs-controller"; +import { UiInputs } from "./ui-inputs"; export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; diff --git a/src/battle.test.ts b/src/battle.test.ts new file mode 100644 index 000000000..a5affeb4e --- /dev/null +++ b/src/battle.test.ts @@ -0,0 +1,157 @@ +import { expect, describe, it, beforeAll, vi, afterAll } from "vitest"; +import Battle, { BattleType } from "./battle"; +import { GameMode } from "./game-mode"; +import Trainer from "./field/trainer"; +import { BattleSpec } from "./enums/battle-spec"; +import BattleScene from "./battle-scene"; +import { TrainerType } from "./data/enums/trainer-type"; + +const NUM_TEST_RUNS = 10; + +describe("battle", () => { + beforeAll(() => { + // Prevent errors + vi.mock('./data/biomes', () => ({})); + vi.mock('./form-change-phase', () => ({})); + vi.mock('./data/move', () => ({ + initMoves: () => {}, + })); + vi.mock("./field/trainer", () => ({ + default: vi.fn().mockImplementation(() => ({ + getPartyLevels: (_waveIndex: integer) => [1] + })), + })); + vi.mock("./data/pokemon-forms", () => ({})); + vi.mock("./data/pokemon-evolutions", () => ({})); + }); + + afterAll(() => { + vi.clearAllMocks(); + }); + + // private method but calls in constructor and updates battleSpec + describe("initBattleSpec", () => { + const trainer = new Trainer(new BattleScene(), TrainerType.ARTIST, 0); // 0 = TrainerVariant.DEFAULT + + it("has final boss as battleSpec when wave 200 and classic mode", () => { + const battle = new Battle(new GameMode(1, { isClassic: true }), 200, BattleType.TRAINER, trainer, false); + + expect(battle.battleSpec).toBe(BattleSpec.FINAL_BOSS); + }); + + it("has default as battleSpec when not wave 200 and classic mode", () => { + const battle = new Battle(new GameMode(1, { isClassic: true }), 190, BattleType.TRAINER, trainer, false); + + expect(battle.battleSpec).toBe(BattleSpec.DEFAULT); + }); + + it("has default as battleSpec when not classic mode", () => { + const battle = new Battle(new GameMode(1, { isClassic: false }), 190, BattleType.TRAINER, trainer, false); + const battle2 = new Battle(new GameMode(1, { isClassic: false }), 200, BattleType.TRAINER, trainer, false); + + expect(battle.battleSpec).toBe(BattleSpec.DEFAULT); + expect(battle2.battleSpec).toBe(BattleSpec.DEFAULT); + }); + }); + + // private method but calls in constructor and updates enemyLevels for battleType !== BattleType.TRAINER + describe("getLevelForWave", () => { + const trainer = new Trainer(new BattleScene(), TrainerType.ARTIST, 0); // 0 = TrainerVariant.DEFAULT + + it("has 2 or 3 as enemyLevels when first wave and single battle", () => { + for (let i = 0; i < NUM_TEST_RUNS; i++) { + const battle = new Battle(new GameMode(1, { isClassic: true }), 1, BattleType.WILD, trainer, false); + + expect(battle.enemyLevels.length).toBe(1); + expect([2, 3]).toContain(battle.enemyLevels[0]); + } + }); + + it("has 2 or 3 x2 as enemyLevels when first wave and double battle", () => { + for (let i = 0; i < NUM_TEST_RUNS; i++) { + const battle = new Battle(new GameMode(1, { isClassic: true }), 1, BattleType.WILD, trainer, true); + + expect(battle.enemyLevels.length).toBe(2); + expect(battle.enemyLevels.every(level => [2, 3].includes(level))).toBeTruthy(); + } + }); + + it("has 164<=x<=184 as enemyLevels when 199th wave and single battle", () => { + for (let i = 0; i < NUM_TEST_RUNS; i++) { + const battle = new Battle(new GameMode(1, { isClassic: true }), 199, BattleType.WILD, trainer, false); + + expect(battle.enemyLevels.length).toBe(1); + expect(battle.enemyLevels[0] >= 164 && battle.enemyLevels[0] <= 184).toBeTruthy(); + } + }); + + it("has 164<=x<=184 x2 as enemyLevels when 199th wave and double battle", () => { + for (let i = 0; i < NUM_TEST_RUNS; i++) { + const battle = new Battle(new GameMode(1, { isClassic: true }), 199, BattleType.WILD, trainer, true); + + expect(battle.enemyLevels.length).toBe(2); + expect(battle.enemyLevels.every(level => level >= 164 && level <= 184)).toBeTruthy(); + } + }); + + it("has 6<=x<=8 as enemyLevels when 10th wave and single battle", () => { + for (let i = 0; i < NUM_TEST_RUNS; i++) { + const battle = new Battle(new GameMode(1, { isClassic: true }), 10, BattleType.WILD, trainer, false); + + expect(battle.enemyLevels.length).toBe(1); + expect(battle.enemyLevels[0] >= 6 && battle.enemyLevels[0] <= 8).toBeTruthy(); + } + }); + + it("has 6<=x<=8 x2 as enemyLevels when 10th wave and double battle", () => { + for (let i = 0; i < NUM_TEST_RUNS; i++) { + const battle = new Battle(new GameMode(1, { isClassic: true }), 10, BattleType.WILD, trainer, true); + + expect(battle.enemyLevels.length).toBe(2); + expect(battle.enemyLevels.every(level => level >= 6 && level <= 8)).toBeTruthy(); + } + }); + + it("has 165<=x<=203 as enemyLevels when 190th wave and single battle", () => { + for (let i = 0; i < NUM_TEST_RUNS; i++) { + const battle = new Battle(new GameMode(1, { isClassic: true }), 190, BattleType.WILD, trainer, false); + + expect(battle.enemyLevels.length).toBe(1); + expect(battle.enemyLevels[0] >= 165 && battle.enemyLevels[0] <= 203).toBeTruthy(); + } + }); + + it("has 165<=x<=203 x2 as enemyLevels when 190th wave and double battle", () => { + for (let i = 0; i < NUM_TEST_RUNS; i++) { + const battle = new Battle(new GameMode(1, { isClassic: true }), 190, BattleType.WILD, trainer, true); + + expect(battle.enemyLevels.length).toBe(2); + expect(battle.enemyLevels.every(level => level >= 165 && level <= 203)).toBeTruthy(); + } + }); + + it("has 200 as enemyLevels when 200th wave, final boss", () => { + for (let i = 0; i < NUM_TEST_RUNS; i++) { + const battle = new Battle(new GameMode(1, { isClassic: true }), 200, BattleType.WILD, trainer, false); + + expect(battle.enemyLevels).toStrictEqual([200]); + } + }); + + it("has 275 as enemyLevels when 250th wave", () => { + for (let i = 0; i < NUM_TEST_RUNS; i++) { + const battle = new Battle(new GameMode(1, { isClassic: true }), 250, BattleType.WILD, trainer, false); + + expect(battle.enemyLevels).toStrictEqual([275]); + } + }); + + it("has 800 as enemyLevels when 500th wave", () => { + for (let i = 0; i < NUM_TEST_RUNS; i++) { + const battle = new Battle(new GameMode(1, { isClassic: true }), 500, BattleType.WILD, trainer, false); + + expect(battle.enemyLevels).toStrictEqual([800]); + } + }); + }); +}); diff --git a/src/battle.ts b/src/battle.ts index 580bad9a5..d47e17bc4 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -10,7 +10,6 @@ import { GameMode } from "./game-mode"; import { BattleSpec } from "./enums/battle-spec"; import { PlayerGender } from "./system/game-data"; import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier"; -import { MoneyAchv } from "./system/achv"; export enum BattleType { WILD, @@ -89,33 +88,28 @@ export default class Battle { } private initBattleSpec(): void { - let spec = BattleSpec.DEFAULT; - if (this.gameMode.isClassic) { - if (this.waveIndex === 200) - spec = BattleSpec.FINAL_BOSS; - } - this.battleSpec = spec; + this.battleSpec = this.gameMode.isClassic && this.waveIndex === 200 + ? BattleSpec.FINAL_BOSS + : BattleSpec.DEFAULT; } private getLevelForWave(): integer { - let levelWaveIndex = this.gameMode.getWaveForDifficulty(this.waveIndex); - let baseLevel = 1 + levelWaveIndex / 2 + Math.pow(levelWaveIndex / 25, 2); + const levelWaveIndex = this.gameMode.getWaveForDifficulty(this.waveIndex); + const baseLevel = 1 + levelWaveIndex / 2 + Math.pow(levelWaveIndex / 25, 2); const bossMultiplier = 1.2; if (!(this.waveIndex % 10)) { - const ret = Math.floor(baseLevel * bossMultiplier); + const levelForWave = Math.floor(baseLevel * bossMultiplier); if (this.battleSpec === BattleSpec.FINAL_BOSS || !(this.waveIndex % 250)) - return Math.ceil(ret / 25) * 25; - let levelOffset = 0; - if (!this.gameMode.isWaveFinal(this.waveIndex)) - levelOffset = Math.round(Phaser.Math.RND.realInRange(-1, 1) * Math.floor(levelWaveIndex / 10)); - return ret + levelOffset; + return Math.ceil(levelForWave / 25) * 25; + const levelOffset = !this.gameMode.isWaveFinal(this.waveIndex) + ? Math.round(Phaser.Math.RND.realInRange(-1, 1) * Math.floor(levelWaveIndex / 10)) + : 0; + return levelForWave + levelOffset; } - let levelOffset = 0; - const deviation = 10 / levelWaveIndex; - levelOffset = Math.abs(this.randSeedGaussForLevel(deviation)); + const levelOffset = Math.abs(this.randSeedGaussForLevel(deviation)); return Math.max(Math.round(baseLevel + levelOffset), 1); } @@ -131,7 +125,7 @@ export default class Battle { return this.double ? 2 : 1; } - incrementTurn(scene: BattleScene): void { + incrementTurn(_scene: BattleScene): void { this.turn++; this.turnCommands = Object.fromEntries(Utils.getEnumValues(BattlerIndex).map(bt => [ bt, null ])); this.battleSeedState = null; @@ -218,7 +212,6 @@ export default class Battle { randSeedInt(scene: BattleScene, range: integer, min: integer = 0): integer { if (range <= 1) return min; - let ret: integer; const tempRngCounter = scene.rngCounter; const tempSeedOverride = scene.rngSeedOverride; const state = Phaser.Math.RND.state(); @@ -230,12 +223,11 @@ export default class Battle { } scene.rngCounter = this.rngCounter++; scene.rngSeedOverride = this.battleSeed; - ret = Utils.randSeedInt(range, min); this.battleSeedState = Phaser.Math.RND.state(); Phaser.Math.RND.state(state); scene.rngCounter = tempRngCounter; scene.rngSeedOverride = tempSeedOverride; - return ret; + return Utils.randSeedInt(range, min); } } diff --git a/src/data/trainer-config.test.ts b/src/data/trainer-config.test.ts new file mode 100644 index 000000000..7e18374d1 --- /dev/null +++ b/src/data/trainer-config.test.ts @@ -0,0 +1,59 @@ +import { expect, describe, it, beforeAll, vi, afterAll, beforeEach } from "vitest"; +import { TrainerConfig, TrainerSlot } from "./trainer-config"; +import { TrainerType } from "./enums/trainer-type"; +import { TrainerVariant } from "#app/field/trainer.js"; + +describe("trainer-config", () => { + describe("getTitle", () => { + let trainerConfig: TrainerConfig; + + beforeAll(() => { + // Prevent errors + vi.mock('./biomes', () => ({})); + vi.mock('../system/voucher', () => ({ + VoucherType: {}, + getVoucherTypeName: () => "", + getVoucherTypeIcon: () => "", + })); + }); + + afterAll(() => { + vi.clearAllMocks(); + }); + + beforeEach(() => { + trainerConfig = new TrainerConfig(TrainerType.ARTIST, false); + }); + + it("returns the name double when trainer variant double", () => { + trainerConfig.nameDouble = "Lae & Ticia"; + expect(trainerConfig.getTitle(TrainerSlot.NONE, TrainerVariant.DOUBLE)).toBe("Lae & Ticia"); + }); + + it("returns the trainer type name when no gender selected", () => { + expect(trainerConfig.getTitle(TrainerSlot.NONE, TrainerVariant.DEFAULT)).toBe("Artist"); + }); + + it("returns the female name when gender is female", () => { + trainerConfig.nameFemale = "Laeticia"; + trainerConfig.hasGenders = true; + expect(trainerConfig.getTitle(TrainerSlot.NONE, TrainerVariant.FEMALE)).toBe("Laeticia"); + }); + + it("returns the female name when trainer variant double and trainer partner", () => { + trainerConfig.nameFemale = "Laeticia"; + trainerConfig.hasGenders = true; + expect(trainerConfig.getTitle(TrainerSlot.TRAINER_PARTNER, TrainerVariant.DOUBLE)).toBe("Laeticia"); + }); + + it("returns the trainer type name with the female gender", () => { + trainerConfig.hasGenders = true; + expect(trainerConfig.getTitle(TrainerSlot.NONE, TrainerVariant.FEMALE)).toBe("Artist♀"); + }); + + it("returns the trainer type name with the male gender", () => { + trainerConfig.hasGenders = true; + expect(trainerConfig.getTitle(TrainerSlot.NONE, TrainerVariant.DEFAULT)).toBe("Artist♂"); + }); + }); +}); diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index 36d76edcf..cd3e78a0d 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -429,20 +429,16 @@ export class TrainerConfig { } getTitle(trainerSlot: TrainerSlot = TrainerSlot.NONE, variant: TrainerVariant): string { - let ret = this.name; - - if (!trainerSlot && variant === TrainerVariant.DOUBLE && this.nameDouble) + if (trainerSlot === TrainerSlot.NONE && variant === TrainerVariant.DOUBLE && this.nameDouble) return this.nameDouble; - if (this.hasGenders) { - if (this.nameFemale) { - if (variant === TrainerVariant.FEMALE || (variant === TrainerVariant.DOUBLE && trainerSlot === TrainerSlot.TRAINER_PARTNER)) - return this.nameFemale; - } else - ret += !variant ? '♂' : '♀'; - } + if (!this.hasGenders) + return this.name; - return ret; + if (this.nameFemale && (variant === TrainerVariant.FEMALE || (variant === TrainerVariant.DOUBLE && trainerSlot === TrainerSlot.TRAINER_PARTNER))) + return this.nameFemale; + + return `${this.name}${variant === TrainerVariant.DEFAULT ? '♂' : '♀'}`; } loadAssets(scene: BattleScene, variant: TrainerVariant): Promise { diff --git a/src/form-change-phase.ts b/src/form-change-phase.ts index db325bd3d..bbdedf998 100644 --- a/src/form-change-phase.ts +++ b/src/form-change-phase.ts @@ -27,9 +27,7 @@ export class FormChangePhase extends EvolutionPhase { } setMode(): Promise { - if (!this.modal) - return super.setMode(); - return this.scene.ui.setOverlayMode(Mode.EVOLUTION_SCENE); + return this.modal ? this.scene.ui.setOverlayMode(Mode.EVOLUTION_SCENE) : super.setMode(); } doEvolution(): void { diff --git a/src/inputs-controller.ts b/src/inputs-controller.ts index 5f5615358..323b0db89 100644 --- a/src/inputs-controller.ts +++ b/src/inputs-controller.ts @@ -142,7 +142,7 @@ export class InputsController { return gamepadMapping; } - gamepadButtonDown(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void { + gamepadButtonDown(_pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, _value: number): void { if (!this.scene.gamepadSupport) return; const actionMapping = this.getActionGamepadMapping(); const buttonDown = actionMapping.hasOwnProperty(button.index) && actionMapping[button.index]; @@ -155,7 +155,7 @@ export class InputsController { } } - gamepadButtonUp(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void { + gamepadButtonUp(_pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, _value: number): void { if (!this.scene.gamepadSupport) return; const actionMapping = this.getActionGamepadMapping(); const buttonUp = actionMapping.hasOwnProperty(button.index) && actionMapping[button.index]; diff --git a/src/messages.test.ts b/src/messages.test.ts new file mode 100644 index 000000000..b5a3b71b2 --- /dev/null +++ b/src/messages.test.ts @@ -0,0 +1,81 @@ +import { expect, describe, it } from "vitest"; +import Pokemon from "./field/pokemon"; +import { getPokemonMessage, getPokemonPrefix } from "./messages"; +import { BattleSpec } from "./enums/battle-spec"; + +describe("messages", () => { + describe("getPokemonPrefix", () => { + it("returns an empty prefix if the pokemon is a pokemon of the player", () => { + const pokemon = { + isPlayer: () => true, + hasTrainer: () => false, + scene: { + currentBattle: { + battleSpec: BattleSpec.DEFAULT + } + } + } as Pokemon; + + expect(getPokemonPrefix(pokemon)).toBe(''); + }); + + it("returns the wild prefix if the pokemon does not have a trainer", () => { + const pokemon = { + isPlayer: () => false, + hasTrainer: () => false, + scene: { + currentBattle: { + battleSpec: BattleSpec.DEFAULT + } + } + } as Pokemon; + + expect(getPokemonPrefix(pokemon)).toBe('Wild '); + }); + + it("returns the foe prefix if the pokemon has a trainer which is not the player", () => { + const pokemon = { + isPlayer: () => false, + hasTrainer: () => true, + scene: { + currentBattle: { + battleSpec: BattleSpec.DEFAULT + } + } + } as Pokemon; + + expect(getPokemonPrefix(pokemon)).toBe('Foe '); + }); + + it("returns the foe prefix if the pokemon is the final boss", () => { + const pokemon = { + isPlayer: () => false, + hasTrainer: () => false, + scene: { + currentBattle: { + battleSpec: BattleSpec.FINAL_BOSS + } + } + } as Pokemon; + + expect(getPokemonPrefix(pokemon)).toBe('Foe '); + }); + }); + + describe("getPokemonMessage", () => { + it("returns a message with pokemon prefix, pokemon name and content given", () => { + const pokemon = { + name: "Gengar", + isPlayer: () => false, + hasTrainer: () => true, + scene: { + currentBattle: { + battleSpec: BattleSpec.DEFAULT + } + } + } as Pokemon; + + expect(getPokemonMessage(pokemon, " is hurt\nby poison!")).toBe('Foe Gengar is hurt\nby poison!'); + }); + }); +}); diff --git a/src/messages.ts b/src/messages.ts index ffd9aa6ef..acb042385 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -6,14 +6,14 @@ export function getPokemonMessage(pokemon: Pokemon, content: string): string { } export function getPokemonPrefix(pokemon: Pokemon): string { - let prefix: string; + if (pokemon.isPlayer()) return ''; + switch (pokemon.scene.currentBattle.battleSpec) { case BattleSpec.DEFAULT: - prefix = !pokemon.isPlayer() ? pokemon.hasTrainer() ? 'Foe ' : 'Wild ' : ''; - break; + return pokemon.hasTrainer() ? 'Foe ' : 'Wild '; case BattleSpec.FINAL_BOSS: - prefix = !pokemon.isPlayer() ? 'Foe ' : ''; - break; + return 'Foe '; + default: + return ''; } - return prefix; } \ No newline at end of file diff --git a/src/phases.ts b/src/phases.ts index 4be1d7705..ebafd8688 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -1,8 +1,8 @@ -import BattleScene, { AnySound, bypassLogin, startingWave } from "./battle-scene"; +import BattleScene, { bypassLogin, startingWave } from "./battle-scene"; import { default as Pokemon, PlayerPokemon, EnemyPokemon, PokemonMove, MoveResult, DamageResult, FieldPosition, HitResult, TurnMove } from "./field/pokemon"; import * as Utils from './utils'; import { Moves } from "./data/enums/moves"; -import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, DelayedAttackAttr, RechargeAttr, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr } from "./data/move"; +import { allMoves, applyMoveAttrs, BypassSleepAttr, ChargeAttr, applyFilteredMoveAttrs, HitsTagAttr, MissEffectAttr, MoveAttr, MoveEffectAttr, MoveFlags, MultiHitAttr, OverrideMoveEffectAttr, VariableAccuracyAttr, MoveTarget, OneHitKOAttr, getMoveTargets, MoveTargetSet, MoveEffectTrigger, CopyMoveAttr, AttackMove, SelfStatusMove, PreMoveMessageAttr, HealStatusEffectAttr, IgnoreOpponentStatChangesAttr, NoEffectAttr, FixedDamageAttr, PostVictoryStatChangeAttr, OneHitKOAccuracyAttr, ForceSwitchOutAttr, VariableTargetAttr } from "./data/move"; import { Mode } from './ui/ui'; import { Command } from "./ui/command-ui-handler"; import { Stat } from "./data/pokemon-stat"; @@ -55,7 +55,7 @@ import { OptionSelectConfig, OptionSelectItem } from "./ui/abstact-option-select import { SaveSlotUiMode } from "./ui/save-slot-select-ui-handler"; import { fetchDailyRunSeed, getDailyRunStarters } from "./data/daily-run"; import { GameModes, gameModes } from "./game-mode"; -import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm, speciesStarters } from "./data/pokemon-species"; +import PokemonSpecies, { getPokemonSpecies, speciesStarters } from "./data/pokemon-species"; import i18next from './plugins/i18n'; import { Abilities } from "./data/enums/abilities"; import { STARTER_FORM_OVERRIDE, STARTER_SPECIES_OVERRIDE } from './overrides'; diff --git a/src/system/game-data.test.ts b/src/system/game-data.test.ts new file mode 100644 index 000000000..c6a3c8745 --- /dev/null +++ b/src/system/game-data.test.ts @@ -0,0 +1,42 @@ +import { expect, describe, it, beforeAll, vi, afterAll } from "vitest"; +import { GameDataType, getDataTypeKey } from "./game-data"; + +describe("game-data", () => { + describe("getDataTypeKey", () => { + beforeAll(() => { + // Prevent errors + vi.mock('../data/biomes', () => ({})); + }); + + afterAll(() => { + vi.clearAllMocks(); + }); + + it("returns sessionData for session data type", () => { + expect(getDataTypeKey(GameDataType.SESSION)).toBe("sessionData"); + expect(getDataTypeKey(GameDataType.SESSION, 0)).toBe("sessionData"); + }); + + it("returns sessionData with the slot id given for session data type", () => { + expect(getDataTypeKey(GameDataType.SESSION, 1)).toBe("sessionData1"); + }); + + it("returns data for system data type", () => { + expect(getDataTypeKey(GameDataType.SYSTEM)).toBe("data"); + expect(getDataTypeKey(GameDataType.SYSTEM, 0)).toBe("data"); + expect(getDataTypeKey(GameDataType.SYSTEM, 1)).toBe("data"); + }); + + it("returns settings for settings data type", () => { + expect(getDataTypeKey(GameDataType.SETTINGS)).toBe("settings"); + expect(getDataTypeKey(GameDataType.SETTINGS, 0)).toBe("settings"); + expect(getDataTypeKey(GameDataType.SETTINGS, 1)).toBe("settings"); + }); + + it("returns tutorials for tutorials data type", () => { + expect(getDataTypeKey(GameDataType.TUTORIALS)).toBe("tutorials"); + expect(getDataTypeKey(GameDataType.TUTORIALS, 0)).toBe("tutorials"); + expect(getDataTypeKey(GameDataType.TUTORIALS, 1)).toBe("tutorials"); + }); + }); +}); diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 2be2ee155..59a0c8293 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -55,10 +55,7 @@ export function getDataTypeKey(dataType: GameDataType, slotId: integer = 0): str case GameDataType.SYSTEM: return 'data'; case GameDataType.SESSION: - let ret = 'sessionData'; - if (slotId) - ret += slotId; - return ret; + return `sessionData${slotId ? slotId : ''}`; case GameDataType.SETTINGS: return 'settings'; case GameDataType.TUTORIALS: @@ -1192,7 +1189,7 @@ export class GameData { return ret; } - getSpeciesDexAttrProps(species: PokemonSpecies, dexAttr: bigint): DexAttrProps { + getSpeciesDexAttrProps(_species: PokemonSpecies, dexAttr: bigint): DexAttrProps { const shiny = !(dexAttr & DexAttr.NON_SHINY); const female = !(dexAttr & DexAttr.MALE); const variant = dexAttr & DexAttr.DEFAULT_VARIANT ? 0 : dexAttr & DexAttr.VARIANT_2 ? 1 : dexAttr & DexAttr.VARIANT_3 ? 2 : 0; diff --git a/src/system/voucher.ts b/src/system/voucher.ts index 276e74eeb..e29e4b6d9 100644 --- a/src/system/voucher.ts +++ b/src/system/voucher.ts @@ -1,6 +1,5 @@ import BattleScene from "../battle-scene"; import { TrainerType } from "../data/enums/trainer-type"; -import { ModifierTier } from "../modifier/modifier-tier"; import { Achv, AchvTier, achvs } from "./achv"; export enum VoucherType { diff --git a/src/ui/egg-gacha-ui-handler.ts b/src/ui/egg-gacha-ui-handler.ts index 315dfdbd3..4695bc03c 100644 --- a/src/ui/egg-gacha-ui-handler.ts +++ b/src/ui/egg-gacha-ui-handler.ts @@ -9,7 +9,7 @@ import { getPokemonSpecies } from "../data/pokemon-species"; import { addWindow } from "./ui-theme"; import { Tutorial, handleTutorial } from "../tutorial"; import { EggTier } from "../data/enums/egg-type"; -import {Button} from "../enums/buttons"; +import { Button } from "../enums/buttons"; const defaultText = 'Select a machine.';