From 57a3efd9e2e5106c5ebee015921982535cf08446 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Thu, 5 Sep 2024 16:51:05 -0700 Subject: [PATCH 01/22] [Bug] Fix off-by-one errors in some random number calls (#3665) * Fix off-by-one error in some random number calls * Fix mock RNG function used by tests Also remove unnecessary extra RNG mock from Glaive Rush test * Just some github UI manipulation don't mind me * Update Glaive Rush test * Remove unnecessary `Math.floor()` * Remove resolved comment * Add tsdocs to various functions * Remove `src/rng.md` file * Update tsdoc --- src/battle-scene.ts | 17 ++++- src/battle.ts | 6 ++ src/data/ability.ts | 2 +- src/data/battler-tags.ts | 2 +- src/data/move.ts | 2 +- src/field/pokemon.ts | 22 ++++++- src/phases/move-effect-phase.ts | 6 +- src/test/moves/glaive_rush.test.ts | 102 ++++++++++++++++------------- src/test/utils/gameManager.ts | 2 +- src/utils.ts | 8 ++- 10 files changed, 110 insertions(+), 59 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index d4c33663c14..9123a213f4c 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -855,7 +855,7 @@ export default class BattleScene extends SceneBase { overrideModifiers(this, false); overrideHeldItems(this, pokemon, false); if (boss && !dataSource) { - const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967295)); + const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967296)); for (let s = 0; s < pokemon.ivs.length; s++) { pokemon.ivs[s] = Math.round(Phaser.Math.Linear(Math.min(pokemon.ivs[s], secondaryIvs[s]), Math.max(pokemon.ivs[s], secondaryIvs[s]), 0.75)); @@ -961,6 +961,16 @@ export default class BattleScene extends SceneBase { this.offsetGym = this.gameMode.isClassic && this.getGeneratedOffsetGym(); } + /** + * Generates a random number using the current battle's seed + * + * This calls {@linkcode Battle.randSeedInt}(`scene`, {@linkcode range}, {@linkcode min}) in `src/battle.ts` + * which calls {@linkcode Utils.randSeedInt randSeedInt}({@linkcode range}, {@linkcode min}) in `src/utils.ts` + * + * @param range How large of a range of random numbers to choose from. If {@linkcode range} <= 1, returns {@linkcode min} + * @param min The minimum integer to pick, default `0` + * @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1) + */ randBattleSeedInt(range: integer, min: integer = 0): integer { return this.currentBattle?.randSeedInt(this, range, min); } @@ -1112,7 +1122,8 @@ export default class BattleScene extends SceneBase { doubleTrainer = false; } } - newTrainer = trainerData !== undefined ? trainerData.toTrainer(this) : new Trainer(this, trainerType, doubleTrainer ? TrainerVariant.DOUBLE : Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT); + const variant = doubleTrainer ? TrainerVariant.DOUBLE : (Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT); + newTrainer = trainerData !== undefined ? trainerData.toTrainer(this) : new Trainer(this, trainerType, variant); this.field.add(newTrainer); } } @@ -2620,7 +2631,7 @@ export default class BattleScene extends SceneBase { if (mods.length < 1) { return mods; } - const rand = Math.floor(Utils.randSeedInt(mods.length)); + const rand = Utils.randSeedInt(mods.length); return [mods[rand], ...shuffleModifiers(mods.filter((_, i) => i !== rand))]; }; modifiers = shuffleModifiers(modifiers); diff --git a/src/battle.ts b/src/battle.ts index 0f1245a4397..b80caa9e679 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -354,6 +354,12 @@ export default class Battle { return null; } + /** + * Generates a random number using the current battle's seed. Calls {@linkcode Utils.randSeedInt} + * @param range How large of a range of random numbers to choose from. If {@linkcode range} <= 1, returns {@linkcode min} + * @param min The minimum integer to pick, default `0` + * @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1) + */ randSeedInt(scene: BattleScene, range: number, min: number = 0): number { if (range <= 1) { return min; diff --git a/src/data/ability.ts b/src/data/ability.ts index fde39ebb152..2407460b87d 100755 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -2642,7 +2642,7 @@ export class ConfusionOnStatusEffectAbAttr extends PostAttackAbAttr { if (simulated) { return defender.canAddTag(BattlerTagType.CONFUSED); } else { - return defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedInt(3, 2), move.id, defender.id); + return defender.addTag(BattlerTagType.CONFUSED, pokemon.randSeedIntRange(2, 5), move.id, defender.id); } } return false; diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index ef91dda7b63..ddb85600c18 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -486,7 +486,7 @@ export class ConfusedTag extends BattlerTag { if (pokemon.randSeedInt(3) === 0) { const atk = pokemon.getEffectiveStat(Stat.ATK); const def = pokemon.getEffectiveStat(Stat.DEF); - const damage = Utils.toDmgValue(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * (pokemon.randSeedInt(15, 85) / 100)); + const damage = Utils.toDmgValue(((((2 * pokemon.level / 5 + 2) * 40 * atk / def) / 50) + 2) * (pokemon.randSeedIntRange(85, 100) / 100)); pokemon.scene.queueMessage(i18next.t("battlerTags:confusedLapseHurtItself")); pokemon.damageAndUpdate(damage); pokemon.battleData.hitCount++; diff --git a/src/data/move.ts b/src/data/move.ts index 252c474864c..96b780a8330 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -4400,7 +4400,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr { const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { - return (this.selfTarget ? user : target).addTag(this.tagType, user.randSeedInt(this.turnCountMax - this.turnCountMin, this.turnCountMin), move.id, user.id); + return (this.selfTarget ? user : target).addTag(this.tagType, user.randSeedIntRange(this.turnCountMin, this.turnCountMax), move.id, user.id); } return false; diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 269d0b1dba5..f522d50f357 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1720,7 +1720,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { }; this.fusionSpecies = this.scene.randomSpecies(this.scene.currentBattle?.waveIndex || 0, this.level, false, filter, true); - this.fusionAbilityIndex = (this.fusionSpecies.abilityHidden && hasHiddenAbility ? this.fusionSpecies.ability2 ? 2 : 1 : this.fusionSpecies.ability2 ? randAbilityIndex : 0); + this.fusionAbilityIndex = (this.fusionSpecies.abilityHidden && hasHiddenAbility ? 2 : this.fusionSpecies.ability2 !== this.fusionSpecies.ability1 ? randAbilityIndex : 0); this.fusionShiny = this.shiny; this.fusionVariant = this.variant; @@ -2278,7 +2278,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!isTypeImmune) { const levelMultiplier = (2 * source.level / 5 + 2); - const randomMultiplier = ((this.scene.randBattleSeedInt(16) + 85) / 100); + const randomMultiplier = (this.randSeedIntRange(85, 100) / 100); damage.value = Utils.toDmgValue((((levelMultiplier * power * sourceAtk.value / targetDef.value) / 50) + 2) * stabMultiplier.value * typeMultiplier @@ -3448,12 +3448,30 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { fusionCanvas.remove(); } + /** + * Generates a random number using the current battle's seed, or the global seed if `this.scene.currentBattle` is falsy + * + * This calls either {@linkcode BattleScene.randBattleSeedInt}({@linkcode range}, {@linkcode min}) in `src/battle-scene.ts` + * which calls {@linkcode Battle.randSeedInt}(`scene`, {@linkcode range}, {@linkcode min}) in `src/battle.ts` + * which calls {@linkcode Utils.randSeedInt randSeedInt}({@linkcode range}, {@linkcode min}) in `src/utils.ts`, + * or it directly calls {@linkcode Utils.randSeedInt randSeedInt}({@linkcode range}, {@linkcode min}) in `src/utils.ts` if there is no current battle + * + * @param range How large of a range of random numbers to choose from. If {@linkcode range} <= 1, returns {@linkcode min} + * @param min The minimum integer to pick, default `0` + * @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1) + */ randSeedInt(range: integer, min: integer = 0): integer { return this.scene.currentBattle ? this.scene.randBattleSeedInt(range, min) : Utils.randSeedInt(range, min); } + /** + * Generates a random number using the current battle's seed, or the global seed if `this.scene.currentBattle` is falsy + * @param min The minimum integer to generate + * @param max The maximum integer to generate + * @returns a random integer between {@linkcode min} and {@linkcode max} inclusive + */ randSeedIntRange(min: integer, max: integer): integer { return this.randSeedInt((max - min) + 1, min); } diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index f100a763219..9b22c520e19 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -377,16 +377,16 @@ export class MoveEffectPhase extends PokemonPhase { return false; } - const moveAccuracy = this.move.getMove().calculateBattleAccuracy(user!, target); // TODO: is the bang correct here? + const moveAccuracy = this.move.getMove().calculateBattleAccuracy(user, target); if (moveAccuracy === -1) { return true; } const accuracyMultiplier = user.getAccuracyMultiplier(target, this.move.getMove()); - const rand = user.randSeedInt(100, 1); + const rand = user.randSeedInt(100); - return rand <= moveAccuracy * (accuracyMultiplier!); // TODO: is this bang correct? + return rand < (moveAccuracy * accuracyMultiplier); } /** Returns the {@linkcode Pokemon} using this phase's invoked move */ diff --git a/src/test/moves/glaive_rush.test.ts b/src/test/moves/glaive_rush.test.ts index 1eac3c32bb4..5867ef751b8 100644 --- a/src/test/moves/glaive_rush.test.ts +++ b/src/test/moves/glaive_rush.test.ts @@ -1,13 +1,12 @@ import { allMoves } from "#app/data/move"; import { Abilities } from "#app/enums/abilities"; -import { DamagePhase } from "#app/phases/damage-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { Moves } from "#enums/moves"; -import { Species } from "#enums/species"; +import { Moves } from "#app/enums/moves"; +import { Species } from "#app/enums/species"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +const TIMEOUT = 20 * 1000; describe("Moves - Glaive Rush", () => { let phaserGame: Phaser.Game; @@ -25,131 +24,142 @@ describe("Moves - Glaive Rush", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.battleType("single"); - game.override.disableCrits(); - game.override.enemySpecies(Species.MAGIKARP); - game.override.enemyAbility(Abilities.BALL_FETCH); - game.override.enemyMoveset(Array(4).fill(Moves.GLAIVE_RUSH)); - game.override.starterSpecies(Species.KLINK); - game.override.ability(Abilities.UNNERVE); - game.override.passiveAbility(Abilities.FUR_COAT); - game.override.moveset([Moves.SHADOW_SNEAK, Moves.AVALANCHE, Moves.SPLASH, Moves.GLAIVE_RUSH]); + game.override + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Array(4).fill(Moves.GLAIVE_RUSH)) + .starterSpecies(Species.KLINK) + .ability(Abilities.BALL_FETCH) + .moveset([Moves.SHADOW_SNEAK, Moves.AVALANCHE, Moves.SPLASH, Moves.GLAIVE_RUSH]); }); it("takes double damage from attacks", async () => { - await game.startBattle(); + await game.classicMode.startBattle(); + const enemy = game.scene.getEnemyPokemon()!; enemy.hp = 1000; - vi.spyOn(game.scene, "randBattleSeedInt").mockReturnValue(0); game.move.select(Moves.SHADOW_SNEAK); - await game.phaseInterceptor.to(DamagePhase); + await game.phaseInterceptor.to("DamagePhase"); const damageDealt = 1000 - enemy.hp; - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); game.move.select(Moves.SHADOW_SNEAK); - await game.phaseInterceptor.to(DamagePhase); + await game.phaseInterceptor.to("DamagePhase"); expect(enemy.hp).toBeLessThanOrEqual(1001 - (damageDealt * 3)); - }, 5000); // TODO: revert back to 20s + }, TIMEOUT); it("always gets hit by attacks", async () => { - await game.startBattle(); + await game.classicMode.startBattle(); + const enemy = game.scene.getEnemyPokemon()!; enemy.hp = 1000; allMoves[Moves.AVALANCHE].accuracy = 0; game.move.select(Moves.AVALANCHE); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); expect(enemy.hp).toBeLessThan(1000); - }, 20000); + }, TIMEOUT); it("interacts properly with multi-lens", async () => { - game.override.startingHeldItems([{ name: "MULTI_LENS", count: 2 }]); - game.override.enemyMoveset(Array(4).fill(Moves.AVALANCHE)); - await game.startBattle(); + game.override + .startingHeldItems([{ name: "MULTI_LENS", count: 2 }]) + .enemyMoveset(Array(4).fill(Moves.AVALANCHE)); + await game.classicMode.startBattle(); + const player = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; + enemy.hp = 1000; player.hp = 1000; allMoves[Moves.AVALANCHE].accuracy = 0; game.move.select(Moves.GLAIVE_RUSH); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); expect(player.hp).toBeLessThan(1000); player.hp = 1000; game.move.select(Moves.SPLASH); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); expect(player.hp).toBe(1000); - }, 20000); + }, TIMEOUT); it("secondary effects only last until next move", async () => { game.override.enemyMoveset(Array(4).fill(Moves.SHADOW_SNEAK)); - await game.startBattle(); + await game.classicMode.startBattle(); + const player = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; + enemy.hp = 1000; player.hp = 1000; allMoves[Moves.SHADOW_SNEAK].accuracy = 0; game.move.select(Moves.GLAIVE_RUSH); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); expect(player.hp).toBe(1000); game.move.select(Moves.SPLASH); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); const damagedHp = player.hp; expect(player.hp).toBeLessThan(1000); game.move.select(Moves.SPLASH); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); expect(player.hp).toBe(damagedHp); - }, 20000); + }, TIMEOUT); it("secondary effects are removed upon switching", async () => { - game.override.enemyMoveset(Array(4).fill(Moves.SHADOW_SNEAK)); - game.override.starterSpecies(0); - await game.startBattle([Species.KLINK, Species.FEEBAS]); + game.override + .enemyMoveset(Array(4).fill(Moves.SHADOW_SNEAK)) + .starterSpecies(0); + await game.classicMode.startBattle([Species.KLINK, Species.FEEBAS]); + const player = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; + enemy.hp = 1000; allMoves[Moves.SHADOW_SNEAK].accuracy = 0; game.move.select(Moves.GLAIVE_RUSH); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); expect(player.hp).toBe(player.getMaxHp()); game.doSwitchPokemon(1); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); game.doSwitchPokemon(1); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); expect(player.hp).toBe(player.getMaxHp()); - }, 20000); + }, TIMEOUT); it("secondary effects don't activate if move fails", async () => { game.override.moveset([Moves.SHADOW_SNEAK, Moves.PROTECT, Moves.SPLASH, Moves.GLAIVE_RUSH]); - await game.startBattle(); + await game.classicMode.startBattle(); + const player = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; + enemy.hp = 1000; player.hp = 1000; game.move.select(Moves.PROTECT); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); game.move.select(Moves.SHADOW_SNEAK); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); game.override.enemyMoveset(Array(4).fill(Moves.SPLASH)); const damagedHP1 = 1000 - enemy.hp; enemy.hp = 1000; game.move.select(Moves.SHADOW_SNEAK); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); const damagedHP2 = 1000 - enemy.hp; expect(damagedHP2).toBeGreaterThanOrEqual((damagedHP1 * 2) - 1); - }, 20000); + }, TIMEOUT); }); diff --git a/src/test/utils/gameManager.ts b/src/test/utils/gameManager.ts index f367fc70936..ade33aa1148 100644 --- a/src/test/utils/gameManager.ts +++ b/src/test/utils/gameManager.ts @@ -76,7 +76,7 @@ export default class GameManager { constructor(phaserGame: Phaser.Game, bypassLogin: boolean = true) { localStorage.clear(); ErrorInterceptor.getInstance().clear(); - BattleScene.prototype.randBattleSeedInt = (arg) => arg-1; + BattleScene.prototype.randBattleSeedInt = (range, min: number = 0) => min + range - 1; // This simulates a max roll this.gameWrapper = new GameWrapper(phaserGame, bypassLogin); this.scene = new BattleScene(); this.phaseInterceptor = new PhaseInterceptor(this.scene); diff --git a/src/utils.ts b/src/utils.ts index 173ea25b17c..fd5430d7276 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,5 +1,5 @@ -import i18next from "i18next"; import { MoneyFormat } from "#enums/money-format"; +import i18next from "i18next"; export const MissingTextureKey = "__MISSING"; @@ -82,6 +82,12 @@ export function randInt(range: integer, min: integer = 0): integer { return Math.floor(Math.random() * range) + min; } +/** + * Generates a random number using the global seed, or the current battle's seed if called via `Battle.randSeedInt` + * @param range How large of a range of random numbers to choose from. If {@linkcode range} <= 1, returns {@linkcode min} + * @param min The minimum integer to pick, default `0` + * @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1) + */ export function randSeedInt(range: integer, min: integer = 0): integer { if (range <= 1) { return min; From 39f3572c1bda83a1f91911364a5f0ed240503d96 Mon Sep 17 00:00:00 2001 From: "Adrian T." <68144167+torranx@users.noreply.github.com> Date: Fri, 6 Sep 2024 07:51:47 +0800 Subject: [PATCH 02/22] [Test] Add Dragon Cheer tests (#4013) * add dragon cheer tests * Update src/test/moves/dragon_cheer.test.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * update tests --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- src/test/moves/dragon_cheer.test.ts | 101 ++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/test/moves/dragon_cheer.test.ts diff --git a/src/test/moves/dragon_cheer.test.ts b/src/test/moves/dragon_cheer.test.ts new file mode 100644 index 00000000000..747d71bd000 --- /dev/null +++ b/src/test/moves/dragon_cheer.test.ts @@ -0,0 +1,101 @@ +import { BattlerIndex } from "#app/battle"; +import { Type } from "#app/data/type"; +import { Moves } from "#app/enums/moves"; +import { Species } from "#app/enums/species"; +import { Abilities } from "#enums/abilities"; +import GameManager from "#test/utils/gameManager"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; + +describe("Moves - Dragon Cheer", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + const TIMEOUT = 20 * 1000; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .battleType("double") + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(SPLASH_ONLY) + .enemyLevel(20) + .moveset([Moves.DRAGON_CHEER, Moves.TACKLE, Moves.SPLASH]); + }); + + it("increases the user's allies' critical hit ratio by one stage", async () => { + await game.classicMode.startBattle([Species.DRAGONAIR, Species.MAGIKARP]); + + const enemy = game.scene.getEnemyField()[0]; + + vi.spyOn(enemy, "getCritStage"); + + game.move.select(Moves.DRAGON_CHEER, 0); + game.move.select(Moves.TACKLE, 1, BattlerIndex.ENEMY); + + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + + // After Tackle + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemy.getCritStage).toHaveReturnedWith(1); // getCritStage is called on defender + }, TIMEOUT); + + it("increases the user's Dragon-type allies' critical hit ratio by two stages", async () => { + await game.classicMode.startBattle([Species.MAGIKARP, Species.DRAGONAIR]); + + const enemy = game.scene.getEnemyField()[0]; + + vi.spyOn(enemy, "getCritStage"); + + game.move.select(Moves.DRAGON_CHEER, 0); + game.move.select(Moves.TACKLE, 1, BattlerIndex.ENEMY); + + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + + // After Tackle + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemy.getCritStage).toHaveReturnedWith(2); // getCritStage is called on defender + }, TIMEOUT); + + it("applies the effect based on the allies' type upon use of the move, and do not change if the allies' type changes later in battle", async () => { + await game.classicMode.startBattle([Species.DRAGONAIR, Species.MAGIKARP]); + + const magikarp = game.scene.getPlayerField()[1]; + const enemy = game.scene.getEnemyField()[0]; + + vi.spyOn(enemy, "getCritStage"); + + game.move.select(Moves.DRAGON_CHEER, 0); + game.move.select(Moves.TACKLE, 1, BattlerIndex.ENEMY); + + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + + // After Tackle + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemy.getCritStage).toHaveReturnedWith(1); // getCritStage is called on defender + + await game.toNextTurn(); + + // Change Magikarp's type to Dragon + vi.spyOn(magikarp, "getTypes").mockReturnValue([Type.DRAGON]); + expect(magikarp.getTypes()).toEqual([Type.DRAGON]); + + game.move.select(Moves.SPLASH, 0); + game.move.select(Moves.TACKLE, 1, BattlerIndex.ENEMY); + + await game.setTurnOrder([BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + + await game.phaseInterceptor.to("MoveEndPhase"); + expect(enemy.getCritStage).toHaveReturnedWith(1); // getCritStage is called on defender + }, TIMEOUT); +}); From f3bdaa12cadd7f1447acf08e84bab4603f74a0a2 Mon Sep 17 00:00:00 2001 From: flx-sta <50131232+flx-sta@users.noreply.github.com> Date: Thu, 5 Sep 2024 17:07:24 -0700 Subject: [PATCH 03/22] [Bug][Refactor] fix username-finder issues + code & visual improvements (#4055) * fix username-finder issues & refactor `login-form-ui-handler` - reduce redundancy - add hover effect for interactable game objects - add error handler for "No save files found!" - Make user finder errors support i18n * add `disableInteractive` to mockContainer --- src/locales/en/menu.json | 4 +- .../mocks/mocksContainer/mockContainer.ts | 1 + src/ui/login-form-ui-handler.ts | 121 +++++++++++------- src/ui/modal-ui-handler.ts | 56 +++++--- src/ui/ui-handler.ts | 9 ++ 5 files changed, 127 insertions(+), 64 deletions(-) diff --git a/src/locales/en/menu.json b/src/locales/en/menu.json index 97cfc0b019d..91888e9db31 100644 --- a/src/locales/en/menu.json +++ b/src/locales/en/menu.json @@ -51,5 +51,7 @@ "renamePokemon": "Rename Pokémon", "rename": "Rename", "nickname": "Nickname", - "errorServerDown": "Oops! There was an issue contacting the server.\n\nYou may leave this window open,\nthe game will automatically reconnect." + "errorServerDown": "Oops! There was an issue contacting the server.\n\nYou may leave this window open,\nthe game will automatically reconnect.", + "noSaves": "You don't have any save files on record!", + "tooManySaves": "You have too many save files on record!" } \ No newline at end of file diff --git a/src/test/utils/mocks/mocksContainer/mockContainer.ts b/src/test/utils/mocks/mocksContainer/mockContainer.ts index 5babd9e71b2..d2cdd852257 100644 --- a/src/test/utils/mocks/mocksContainer/mockContainer.ts +++ b/src/test/utils/mocks/mocksContainer/mockContainer.ts @@ -208,4 +208,5 @@ export default class MockContainer implements MockGameObject { return this.list; } + disableInteractive = vi.fn(); } diff --git a/src/ui/login-form-ui-handler.ts b/src/ui/login-form-ui-handler.ts index 87b7730e8df..631b2e50b02 100644 --- a/src/ui/login-form-ui-handler.ts +++ b/src/ui/login-form-ui-handler.ts @@ -8,7 +8,21 @@ import { addTextObject, TextStyle } from "./text"; import { addWindow } from "./ui-theme"; import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; +interface BuildInteractableImageOpts { + scale?: number; + x?: number; + y?: number; + origin?: { x: number; y: number }; +} + export default class LoginFormUiHandler extends FormModalUiHandler { + private readonly ERR_USERNAME: string = "invalid username"; + private readonly ERR_PASSWORD: string = "invalid password"; + private readonly ERR_ACCOUNT_EXIST: string = "account doesn't exist"; + private readonly ERR_PASSWORD_MATCH: string = "password doesn't match"; + private readonly ERR_NO_SAVES: string = "No save files found"; + private readonly ERR_TOO_MANY_SAVES: string = "Too many save files found"; + private googleImage: Phaser.GameObjects.Image; private discordImage: Phaser.GameObjects.Image; private usernameInfoImage: Phaser.GameObjects.Image; @@ -21,8 +35,23 @@ export default class LoginFormUiHandler extends FormModalUiHandler { } setup(): void { - super.setup(); + this.buildExternalPartyContainer(); + + this.infoContainer = this.scene.add.container(0, 0); + + this.usernameInfoImage = this.buildInteractableImage("settings_icon", "username-info-icon", { + x: 20, + scale: 0.5 + }); + + this.infoContainer.add(this.usernameInfoImage); + this.getUi().add(this.infoContainer); + this.infoContainer.setVisible(false); + this.infoContainer.disableInteractive(); + } + + private buildExternalPartyContainer() { this.externalPartyContainer = this.scene.add.container(0, 0); this.externalPartyContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 12, this.scene.game.canvas.height / 12), Phaser.Geom.Rectangle.Contains); this.externalPartyTitle = addTextObject(this.scene, 0, 4, "", TextStyle.SETTINGS_LABEL); @@ -31,23 +60,8 @@ export default class LoginFormUiHandler extends FormModalUiHandler { this.externalPartyContainer.add(this.externalPartyBg); this.externalPartyContainer.add(this.externalPartyTitle); - this.infoContainer = this.scene.add.container(0, 0); - this.infoContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 12, this.scene.game.canvas.height / 12), Phaser.Geom.Rectangle.Contains); - - const googleImage = this.scene.add.image(0, 0, "google"); - googleImage.setOrigin(0, 0); - googleImage.setScale(0.07); - googleImage.setInteractive(); - googleImage.setName("google-icon"); - this.googleImage = googleImage; - - const discordImage = this.scene.add.image(20, 0, "discord"); - discordImage.setOrigin(0, 0); - discordImage.setScale(0.07); - discordImage.setInteractive(); - discordImage.setName("discord-icon"); - - this.discordImage = discordImage; + this.googleImage = this.buildInteractableImage("google", "google-icon"); + this.discordImage = this.buildInteractableImage("discord", "discord-icon"); this.externalPartyContainer.add(this.googleImage); this.externalPartyContainer.add(this.discordImage); @@ -55,59 +69,52 @@ export default class LoginFormUiHandler extends FormModalUiHandler { this.externalPartyContainer.add(this.googleImage); this.externalPartyContainer.add(this.discordImage); this.externalPartyContainer.setVisible(false); - - const usernameInfoImage = this.scene.add.image(20, 0, "settings_icon"); - usernameInfoImage.setOrigin(0, 0); - usernameInfoImage.setScale(0.5); - usernameInfoImage.setInteractive(); - usernameInfoImage.setName("username-info-icon"); - this.usernameInfoImage = usernameInfoImage; - - this.infoContainer.add(this.usernameInfoImage); - this.getUi().add(this.infoContainer); - this.infoContainer.setVisible(false); } - getModalTitle(config?: ModalConfig): string { + override getModalTitle(_config?: ModalConfig): string { return i18next.t("menu:login"); } - getFields(config?: ModalConfig): string[] { + override getFields(_config?: ModalConfig): string[] { return [ i18next.t("menu:username"), i18next.t("menu:password") ]; } - getWidth(config?: ModalConfig): number { + override getWidth(_config?: ModalConfig): number { return 160; } - getMargin(config?: ModalConfig): [number, number, number, number] { + override getMargin(_config?: ModalConfig): [number, number, number, number] { return [ 0, 0, 48, 0 ]; } - getButtonLabels(config?: ModalConfig): string[] { + override getButtonLabels(_config?: ModalConfig): string[] { return [ i18next.t("menu:login"), i18next.t("menu:register")]; } - getReadableErrorMessage(error: string): string { + override getReadableErrorMessage(error: string): string { const colonIndex = error?.indexOf(":"); if (colonIndex > 0) { error = error.slice(0, colonIndex); } switch (error) { - case "invalid username": + case this.ERR_USERNAME: return i18next.t("menu:invalidLoginUsername"); - case "invalid password": + case this.ERR_PASSWORD: return i18next.t("menu:invalidLoginPassword"); - case "account doesn't exist": + case this.ERR_ACCOUNT_EXIST: return i18next.t("menu:accountNonExistent"); - case "password doesn't match": + case this.ERR_PASSWORD_MATCH: return i18next.t("menu:unmatchingPassword"); + case this.ERR_NO_SAVES: + return i18next.t("menu:noSaves"); + case this.ERR_TOO_MANY_SAVES: + return i18next.t("menu:tooManySaves"); } return super.getReadableErrorMessage(error); } - show(args: any[]): boolean { + override show(args: any[]): boolean { if (super.show(args)) { const config = args[0] as ModalConfig; @@ -148,17 +155,16 @@ export default class LoginFormUiHandler extends FormModalUiHandler { return false; } - clear() { + override clear() { super.clear(); this.externalPartyContainer.setVisible(false); this.infoContainer.setVisible(false); + this.setMouseCursorStyle("default"); //reset cursor - this.discordImage.off("pointerdown"); - this.googleImage.off("pointerdown"); - this.usernameInfoImage.off("pointerdown"); + [this.discordImage, this.googleImage, this.usernameInfoImage].forEach((img) => img.off("pointerdown")); } - processExternalProvider(config: ModalConfig) : void { + private processExternalProvider(config: ModalConfig) : void { this.externalPartyTitle.setText(i18next.t("menu:orUse") ?? ""); this.externalPartyTitle.setX(20+this.externalPartyTitle.text.length); this.externalPartyTitle.setVisible(true); @@ -205,6 +211,7 @@ export default class LoginFormUiHandler extends FormModalUiHandler { label: dataKeys[i].replace(keyToFind, ""), handler: () => { this.scene.ui.revertMode(); + this.infoContainer.disableInteractive(); return true; } }); @@ -213,8 +220,13 @@ export default class LoginFormUiHandler extends FormModalUiHandler { options: options, delay: 1000 }); + this.infoContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width, this.scene.game.canvas.height), Phaser.Geom.Rectangle.Contains); } else { - return onFail("You have too many save files to use this"); + if (dataKeys.length > 2) { + return onFail(this.ERR_TOO_MANY_SAVES); + } else { + return onFail(this.ERR_NO_SAVES); + } } }); @@ -236,4 +248,21 @@ export default class LoginFormUiHandler extends FormModalUiHandler { alpha: 1 }); } + + private buildInteractableImage(texture: string, name: string, opts: BuildInteractableImageOpts = {}) { + const { + scale = 0.07, + x = 0, + y = 0, + origin = { x: 0, y: 0 } + } = opts; + const img = this.scene.add.image(x, y, texture); + img.setName(name); + img.setOrigin(origin.x, origin.y); + img.setScale(scale); + img.setInteractive(); + this.addInteractionHoverEffect(img); + + return img; + } } diff --git a/src/ui/modal-ui-handler.ts b/src/ui/modal-ui-handler.ts index cecdacc1eb9..5f586ec8db7 100644 --- a/src/ui/modal-ui-handler.ts +++ b/src/ui/modal-ui-handler.ts @@ -57,29 +57,35 @@ export abstract class ModalUiHandler extends UiHandler { const buttonLabels = this.getButtonLabels(); - const buttonTopMargin = this.getButtonTopMargin(); - for (const label of buttonLabels) { - const buttonLabel = addTextObject(this.scene, 0, 8, label, TextStyle.TOOLTIP_CONTENT); - buttonLabel.setOrigin(0.5, 0.5); - - const buttonBg = addWindow(this.scene, 0, 0, buttonLabel.getBounds().width + 8, 16, false, false, 0, 0, WindowVariant.THIN); - buttonBg.setOrigin(0.5, 0); - buttonBg.setInteractive(new Phaser.Geom.Rectangle(0, 0, buttonBg.width, buttonBg.height), Phaser.Geom.Rectangle.Contains); - - const buttonContainer = this.scene.add.container(0, buttonTopMargin); - - this.buttonBgs.push(buttonBg); - this.buttonContainers.push(buttonContainer); - - buttonContainer.add(buttonBg); - buttonContainer.add(buttonLabel); - this.modalContainer.add(buttonContainer); + this.addButton(label); } this.modalContainer.setVisible(false); } + private addButton(label: string) { + const buttonTopMargin = this.getButtonTopMargin(); + const buttonLabel = addTextObject(this.scene, 0, 8, label, TextStyle.TOOLTIP_CONTENT); + buttonLabel.setOrigin(0.5, 0.5); + + const buttonBg = addWindow(this.scene, 0, 0, buttonLabel.getBounds().width + 8, 16, false, false, 0, 0, WindowVariant.THIN); + buttonBg.setOrigin(0.5, 0); + buttonBg.setInteractive(new Phaser.Geom.Rectangle(0, 0, buttonBg.width, buttonBg.height), Phaser.Geom.Rectangle.Contains); + + const buttonContainer = this.scene.add.container(0, buttonTopMargin); + + this.buttonBgs.push(buttonBg); + this.buttonContainers.push(buttonContainer); + + buttonContainer.add(buttonBg); + buttonContainer.add(buttonLabel); + + this.addInteractionHoverEffect(buttonBg); + + this.modalContainer.add(buttonContainer); + } + show(args: any[]): boolean { if (args.length >= 1 && "buttonActions" in args[0]) { super.show(args); @@ -135,4 +141,20 @@ export abstract class ModalUiHandler extends UiHandler { this.buttonBgs.map(bg => bg.off("pointerdown")); } + + /** + * Adds a hover effect to a game object which changes the cursor to a `pointer` and tints it slighly + * @param gameObject the game object to add hover events/effects to + */ + protected addInteractionHoverEffect(gameObject: Phaser.GameObjects.Image | Phaser.GameObjects.NineSlice | Phaser.GameObjects.Sprite) { + gameObject.on("pointerover", () => { + this.setMouseCursorStyle("pointer"); + gameObject.setTint(0xbbbbbb); + }); + + gameObject.on("pointerout", () => { + this.setMouseCursorStyle("default"); + gameObject.clearTint(); + }); + } } diff --git a/src/ui/ui-handler.ts b/src/ui/ui-handler.ts index 94625efaa75..d9f0a876b71 100644 --- a/src/ui/ui-handler.ts +++ b/src/ui/ui-handler.ts @@ -52,6 +52,15 @@ export default abstract class UiHandler { return changed; } + /** + * Changes the style of the mouse cursor. + * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/cursor} + * @param cursorStyle cursor style to apply + */ + protected setMouseCursorStyle(cursorStyle: "pointer" | "default") { + this.scene.input.manager.canvas.style.cursor = cursorStyle; + } + clear() { this.active = false; } From f1650d251594307e75170b8f0954b4e87bc3a5d4 Mon Sep 17 00:00:00 2001 From: chaosgrimmon <31082757+chaosgrimmon@users.noreply.github.com> Date: Thu, 5 Sep 2024 22:32:13 -0400 Subject: [PATCH 04/22] [Sprite] Fix Tangrowth Variants (#4059) * [Sprite] Front Tangrowth male variants * [Sprite] Front Tangrowth female variants * [Sprite] Back Tangrowth female variants * [Sprite] Back Tangrowth male epic palette * Delete public/images/pokemon/variant/465_2.png * Delete public/images/pokemon/variant/back/465_3.png * Delete public/images/pokemon/variant/465_3.png * Delete public/images/pokemon/variant/465_2.json * Delete public/images/pokemon/variant/465_3.json * Delete public/images/pokemon/variant/back/465_3.json * [Sprite] Update Tangrowth variants with females --- public/images/pokemon/variant/465.json | 22 + public/images/pokemon/variant/465_2.json | 4094 ----------------- public/images/pokemon/variant/465_2.png | Bin 38802 -> 0 bytes public/images/pokemon/variant/465_3.json | 4094 ----------------- public/images/pokemon/variant/465_3.png | Bin 43995 -> 0 bytes .../images/pokemon/variant/_masterlist.json | 16 +- public/images/pokemon/variant/back/465.json | 11 +- public/images/pokemon/variant/back/465_3.json | 4094 ----------------- public/images/pokemon/variant/back/465_3.png | Bin 34654 -> 0 bytes .../pokemon/variant/back/female/465.json | 21 + public/images/pokemon/variant/female/465.json | 22 + 11 files changed, 88 insertions(+), 12286 deletions(-) create mode 100644 public/images/pokemon/variant/465.json delete mode 100644 public/images/pokemon/variant/465_2.json delete mode 100644 public/images/pokemon/variant/465_2.png delete mode 100644 public/images/pokemon/variant/465_3.json delete mode 100644 public/images/pokemon/variant/465_3.png delete mode 100644 public/images/pokemon/variant/back/465_3.json delete mode 100644 public/images/pokemon/variant/back/465_3.png create mode 100644 public/images/pokemon/variant/back/female/465.json create mode 100644 public/images/pokemon/variant/female/465.json diff --git a/public/images/pokemon/variant/465.json b/public/images/pokemon/variant/465.json new file mode 100644 index 00000000000..a7ff2338057 --- /dev/null +++ b/public/images/pokemon/variant/465.json @@ -0,0 +1,22 @@ +{ + "1": { + "529cc5": "8153c7", + "d65a94": "5ad662", + "3a73ad": "6b3aad", + "bd216b": "21bd69", + "5a193a": "195a2a", + "193a63": "391963", + "295a84": "472984" + }, + "2": { + "529cc5": "ffedb6", + "d65a94": "e67d2f", + "3a73ad": "ebc582", + "bd216b": "b35131", + "31313a": "3d1519", + "5a193a": "752e2e", + "193a63": "705040", + "295a84": "ad875a", + "4a4a52": "57211a" + } +} \ No newline at end of file diff --git a/public/images/pokemon/variant/465_2.json b/public/images/pokemon/variant/465_2.json deleted file mode 100644 index 7c6d5ea081a..00000000000 --- a/public/images/pokemon/variant/465_2.json +++ /dev/null @@ -1,4094 +0,0 @@ -{ - "textures": [ - { - "image": "465_2.png", - "format": "RGBA8888", - "size": { - "w": 407, - "h": 407 - }, - "scale": 1, - "frames": [ - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0139.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0140.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0171.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0172.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0137.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0138.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0169.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0170.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0153.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0154.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0185.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0186.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0155.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0156.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0187.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0188.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0129.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0130.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0131.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0132.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0147.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0148.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0163.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0164.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0179.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0180.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0141.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0142.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0173.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0174.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 98, - "h": 65 - }, - "frame": { - "x": 64, - "y": 65, - "w": 98, - "h": 65 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 98, - "h": 65 - }, - "frame": { - "x": 64, - "y": 65, - "w": 98, - "h": 65 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 98, - "h": 65 - }, - "frame": { - "x": 64, - "y": 65, - "w": 98, - "h": 65 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 98, - "h": 65 - }, - "frame": { - "x": 64, - "y": 65, - "w": 98, - "h": 65 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0133.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0134.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0165.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0166.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0157.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0158.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0189.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0190.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0135.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0136.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0167.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0168.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0145.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0146.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0177.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0178.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0161.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0162.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0193.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0194.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0149.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0150.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0181.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0182.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0143.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0144.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0175.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0176.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0151.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0152.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0183.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0184.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 86, - "h": 66 - }, - "frame": { - "x": 0, - "y": 196, - "w": 86, - "h": 66 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 86, - "h": 66 - }, - "frame": { - "x": 0, - "y": 196, - "w": 86, - "h": 66 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 90, - "h": 66 - }, - "frame": { - "x": 86, - "y": 197, - "w": 90, - "h": 66 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 90, - "h": 66 - }, - "frame": { - "x": 86, - "y": 197, - "w": 90, - "h": 66 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 90, - "h": 66 - }, - "frame": { - "x": 86, - "y": 197, - "w": 90, - "h": 66 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 90, - "h": 66 - }, - "frame": { - "x": 86, - "y": 197, - "w": 90, - "h": 66 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 94, - "h": 66 - }, - "frame": { - "x": 176, - "y": 198, - "w": 94, - "h": 66 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 94, - "h": 66 - }, - "frame": { - "x": 176, - "y": 198, - "w": 94, - "h": 66 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 270, - "y": 198, - "w": 97, - "h": 66 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 270, - "y": 198, - "w": 97, - "h": 66 - } - }, - { - "filename": "0127.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 86, - "h": 66 - }, - "frame": { - "x": 0, - "y": 262, - "w": 86, - "h": 66 - } - }, - { - "filename": "0128.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 86, - "h": 66 - }, - "frame": { - "x": 0, - "y": 262, - "w": 86, - "h": 66 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0159.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0160.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0191.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0192.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 98, - "h": 66 - }, - "frame": { - "x": 156, - "y": 264, - "w": 98, - "h": 66 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 98, - "h": 66 - }, - "frame": { - "x": 156, - "y": 264, - "w": 98, - "h": 66 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 98, - "h": 66 - }, - "frame": { - "x": 156, - "y": 264, - "w": 98, - "h": 66 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 98, - "h": 66 - }, - "frame": { - "x": 156, - "y": 264, - "w": 98, - "h": 66 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 254, - "y": 264, - "w": 97, - "h": 66 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 254, - "y": 264, - "w": 97, - "h": 66 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 98, - "h": 66 - }, - "frame": { - "x": 0, - "y": 330, - "w": 98, - "h": 66 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 98, - "h": 66 - }, - "frame": { - "x": 0, - "y": 330, - "w": 98, - "h": 66 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 98, - "y": 330, - "w": 97, - "h": 66 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 98, - "y": 330, - "w": 97, - "h": 66 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 195, - "y": 330, - "w": 97, - "h": 66 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 195, - "y": 330, - "w": 97, - "h": 66 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 94, - "h": 66 - }, - "frame": { - "x": 292, - "y": 330, - "w": 94, - "h": 66 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 94, - "h": 66 - }, - "frame": { - "x": 292, - "y": 330, - "w": 94, - "h": 66 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:9fb6238f8e585be9be5e520abb59e23d:2204e0edc6a9e184240a16c4ee5faa7c:06d67de9e8d7f60fc986e0c00145d6b1$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/465_2.png b/public/images/pokemon/variant/465_2.png deleted file mode 100644 index db25e88ad987fbad282a87365e121b0f2755af87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38802 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 acmjR-T^1VC^$#3i9C|uN+GUz{VgCiM=7Yij diff --git a/public/images/pokemon/variant/465_3.json b/public/images/pokemon/variant/465_3.json deleted file mode 100644 index c092ec585e7..00000000000 --- a/public/images/pokemon/variant/465_3.json +++ /dev/null @@ -1,4094 +0,0 @@ -{ - "textures": [ - { - "image": "465_3.png", - "format": "RGBA8888", - "size": { - "w": 407, - "h": 407 - }, - "scale": 1, - "frames": [ - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0139.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0140.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0171.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0172.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 3, - "w": 74, - "h": 64 - }, - "frame": { - "x": 0, - "y": 0, - "w": 74, - "h": 64 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0137.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0138.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0169.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0170.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 74, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0153.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0154.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0185.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0186.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 1, - "w": 83, - "h": 65 - }, - "frame": { - "x": 157, - "y": 0, - "w": 83, - "h": 65 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0155.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0156.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0187.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0188.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 12, - "y": 2, - "w": 74, - "h": 65 - }, - "frame": { - "x": 240, - "y": 0, - "w": 74, - "h": 65 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0129.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0130.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0131.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0132.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0147.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0148.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0163.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0164.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0179.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0180.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 83, - "h": 66 - }, - "frame": { - "x": 314, - "y": 0, - "w": 83, - "h": 66 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0141.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0142.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0173.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0174.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 0, - "y": 64, - "w": 64, - "h": 66 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 98, - "h": 65 - }, - "frame": { - "x": 64, - "y": 65, - "w": 98, - "h": 65 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 98, - "h": 65 - }, - "frame": { - "x": 64, - "y": 65, - "w": 98, - "h": 65 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 98, - "h": 65 - }, - "frame": { - "x": 64, - "y": 65, - "w": 98, - "h": 65 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 98, - "h": 65 - }, - "frame": { - "x": 64, - "y": 65, - "w": 98, - "h": 65 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0133.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0134.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0165.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0166.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 162, - "y": 65, - "w": 88, - "h": 66 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0157.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0158.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0189.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0190.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 17, - "y": 1, - "w": 64, - "h": 66 - }, - "frame": { - "x": 250, - "y": 65, - "w": 64, - "h": 66 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0135.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0136.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0167.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0168.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 314, - "y": 66, - "w": 93, - "h": 66 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0145.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0146.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0177.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0178.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 0, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0161.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0162.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0193.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0194.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 76, - "h": 66 - }, - "frame": { - "x": 76, - "y": 130, - "w": 76, - "h": 66 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0149.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0150.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0181.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0182.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 88, - "h": 66 - }, - "frame": { - "x": 152, - "y": 131, - "w": 88, - "h": 66 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0143.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0144.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0175.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0176.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 240, - "y": 131, - "w": 70, - "h": 67 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0151.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0152.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0183.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0184.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 93, - "h": 66 - }, - "frame": { - "x": 310, - "y": 132, - "w": 93, - "h": 66 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 86, - "h": 66 - }, - "frame": { - "x": 0, - "y": 196, - "w": 86, - "h": 66 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 86, - "h": 66 - }, - "frame": { - "x": 0, - "y": 196, - "w": 86, - "h": 66 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 90, - "h": 66 - }, - "frame": { - "x": 86, - "y": 197, - "w": 90, - "h": 66 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 90, - "h": 66 - }, - "frame": { - "x": 86, - "y": 197, - "w": 90, - "h": 66 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 90, - "h": 66 - }, - "frame": { - "x": 86, - "y": 197, - "w": 90, - "h": 66 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 90, - "h": 66 - }, - "frame": { - "x": 86, - "y": 197, - "w": 90, - "h": 66 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 94, - "h": 66 - }, - "frame": { - "x": 176, - "y": 198, - "w": 94, - "h": 66 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 94, - "h": 66 - }, - "frame": { - "x": 176, - "y": 198, - "w": 94, - "h": 66 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 270, - "y": 198, - "w": 97, - "h": 66 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 270, - "y": 198, - "w": 97, - "h": 66 - } - }, - { - "filename": "0127.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 86, - "h": 66 - }, - "frame": { - "x": 0, - "y": 262, - "w": 86, - "h": 66 - } - }, - { - "filename": "0128.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 86, - "h": 66 - }, - "frame": { - "x": 0, - "y": 262, - "w": 86, - "h": 66 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0159.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0160.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0191.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0192.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 14, - "y": 0, - "w": 70, - "h": 67 - }, - "frame": { - "x": 86, - "y": 263, - "w": 70, - "h": 67 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 98, - "h": 66 - }, - "frame": { - "x": 156, - "y": 264, - "w": 98, - "h": 66 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 98, - "h": 66 - }, - "frame": { - "x": 156, - "y": 264, - "w": 98, - "h": 66 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 98, - "h": 66 - }, - "frame": { - "x": 156, - "y": 264, - "w": 98, - "h": 66 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 98, - "h": 66 - }, - "frame": { - "x": 156, - "y": 264, - "w": 98, - "h": 66 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 254, - "y": 264, - "w": 97, - "h": 66 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 254, - "y": 264, - "w": 97, - "h": 66 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 98, - "h": 66 - }, - "frame": { - "x": 0, - "y": 330, - "w": 98, - "h": 66 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 98, - "h": 66 - }, - "frame": { - "x": 0, - "y": 330, - "w": 98, - "h": 66 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 98, - "y": 330, - "w": 97, - "h": 66 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 98, - "y": 330, - "w": 97, - "h": 66 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 195, - "y": 330, - "w": 97, - "h": 66 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 97, - "h": 66 - }, - "frame": { - "x": 195, - "y": 330, - "w": 97, - "h": 66 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 94, - "h": 66 - }, - "frame": { - "x": 292, - "y": 330, - "w": 94, - "h": 66 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 98, - "h": 67 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 94, - "h": 66 - }, - "frame": { - "x": 292, - "y": 330, - "w": 94, - "h": 66 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:9fb6238f8e585be9be5e520abb59e23d:2204e0edc6a9e184240a16c4ee5faa7c:06d67de9e8d7f60fc986e0c00145d6b1$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/465_3.png b/public/images/pokemon/variant/465_3.png deleted file mode 100644 index fe8e764028b87c1e1e5cc7148976b299c5cb583d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43995 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

GW16L@n!k&t zT@5-HTNuveUiFs*EAZ5F^r|9CgZ=cT?^MhmK17-d$pBaE`U6)Tt%h8Gt+&F0axJz1 zxsYKdBOmwgbNQ7f$%oN5!Gwg5a>wlXQ&qqMWc`@?Rb}mWNg@Ur*e#=Lrr0zoxEre^ zMh0!`z@IH9)mb4Js#9lu%*`LFv_kCX7MOL_JF1u+;cyCD20z)wgjwM53^m{P(3nxy zLXXh|XWgP7xQ_I&HYcEs2KH(v)=#cq+wxsr6Z#8PF!&5gX$@)`@x6?Mhd^iOBNJCcsB+sOz0HMh<*~gks3^-w>UU2b zFtA7}Ka>|O{Tu(+4wJn_xp%HSp2o(8il{Hf)3vsqZNJJ~lNW_P`Pt!`0X#9&l(YFq za&Ch70S_K#4E8pBBE1zI0^%W>=}rNj5uKAW?jRIMGV6HJ!(A%Oy{U3-)7btDR>Qj5 zwNRhrg+zn%;u%3^Zkf>Z?9fIDzvt~{lydD)>qcfRn=QM)MEz!5fjcN?qZq1B0q zQRq=n8%sXK9zv5EulXHrR-Oecj^v$P{^cY@bDT<9c5mVyATajX+XX&kWZB zP!I%<^(f>0+a2czeV>p~y2oFmmE0llVv}G<@tN!8=^1~?;D?JF*tK~cO*)HjNEt;> zCDcqsYU`3Ro&T3@Q71p*ax(rR8{u$z`z-|0b9rrmgjvwsTq6XRvVD4%b9wQ+l0F(* zG4?@V)k-M_v_kAW+rA0SW1J3N1{-^FA@X9Y>TG>qs?0>_J~I3}d=_$}l{07O9Q@Qi z7_jHX(cL|@(uLntLCUQW{PToBA7YW=GfMlHPB(Qf_>>x9aZxu8w{GUK_uNS%>>KmE*S!F7bGmAy;eu_I-+S1o|TZ?^tm?Z@afxw_iP+poYh` z-!K?NtPI*9B$p;-Z z4mNSKPlWd8gAg+#p+}AkE5!5ughhh{j&&_ljjpo7Bzla#&&|ixQ#Hk(A8A6;u5GC- z4o}42>?8-j71<;~NR|pa;x$FW|L Date: Fri, 6 Sep 2024 00:59:22 -0700 Subject: [PATCH 05/22] [Bug] Fix Aura Break applying without Dark/Fairy Aura present (#4057) * Fix Aura Break ignoring active Dark/Fairy Aura condition * Add conditional post-summon message --------- Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> --- src/data/ability.ts | 6 ++++-- src/data/move.ts | 5 ++++- src/locales/en/ability-trigger.json | 1 + src/test/abilities/aura_break.test.ts | 27 ++++++++++++++++++++------- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 2407460b87d..10aba1f030e 100755 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -5333,8 +5333,10 @@ export function initAbilities() { .attr(FieldMoveTypePowerBoostAbAttr, Type.FAIRY, 4 / 3), new Ability(Abilities.AURA_BREAK, 6) .ignorable() - .conditionalAttr(target => target.hasAbility(Abilities.DARK_AURA), FieldMoveTypePowerBoostAbAttr, Type.DARK, 9 / 16) - .conditionalAttr(target => target.hasAbility(Abilities.FAIRY_AURA), FieldMoveTypePowerBoostAbAttr, Type.FAIRY, 9 / 16), + .conditionalAttr(pokemon => pokemon.scene.getField(true).some(p => p.hasAbility(Abilities.DARK_AURA)), FieldMoveTypePowerBoostAbAttr, Type.DARK, 9 / 16) + .conditionalAttr(pokemon => pokemon.scene.getField(true).some(p => p.hasAbility(Abilities.FAIRY_AURA)), FieldMoveTypePowerBoostAbAttr, Type.FAIRY, 9 / 16) + .conditionalAttr(pokemon => pokemon.scene.getField(true).some(p => p.hasAbility(Abilities.DARK_AURA) || p.hasAbility(Abilities.FAIRY_AURA)), + PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonAuraBreak", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })), new Ability(Abilities.PRIMORDIAL_SEA, 6) .attr(PostSummonWeatherChangeAbAttr, WeatherType.HEAVY_RAIN) .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HEAVY_RAIN) diff --git a/src/data/move.ts b/src/data/move.ts index 96b780a8330..19014c0eb30 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -757,7 +757,10 @@ export default class Move implements Localizable { const fieldAuras = new Set( source.scene.getField(true) - .map((p) => p.getAbilityAttrs(FieldMoveTypePowerBoostAbAttr) as FieldMoveTypePowerBoostAbAttr[]) + .map((p) => p.getAbilityAttrs(FieldMoveTypePowerBoostAbAttr).filter(attr => { + const condition = attr.getCondition(); + return (!condition || condition(p)); + }) as FieldMoveTypePowerBoostAbAttr[]) .flat(), ); for (const aura of fieldAuras) { diff --git a/src/locales/en/ability-trigger.json b/src/locales/en/ability-trigger.json index 4f1d4dac766..a7383cea16b 100644 --- a/src/locales/en/ability-trigger.json +++ b/src/locales/en/ability-trigger.json @@ -52,6 +52,7 @@ "postSummonTeravolt": "{{pokemonNameWithAffix}} is radiating a bursting aura!", "postSummonDarkAura": "{{pokemonNameWithAffix}} is radiating a Dark Aura!", "postSummonFairyAura": "{{pokemonNameWithAffix}} is radiating a Fairy Aura!", + "postSummonAuraBreak": "{{pokemonNameWithAffix}} reversed all other Pokémon's auras!", "postSummonNeutralizingGas": "{{pokemonNameWithAffix}}'s Neutralizing Gas filled the area!", "postSummonAsOneGlastrier": "{{pokemonNameWithAffix}} has two Abilities!", "postSummonAsOneSpectrier": "{{pokemonNameWithAffix}} has two Abilities!", diff --git a/src/test/abilities/aura_break.test.ts b/src/test/abilities/aura_break.test.ts index 7de300c157a..0fb2212d817 100644 --- a/src/test/abilities/aura_break.test.ts +++ b/src/test/abilities/aura_break.test.ts @@ -1,5 +1,4 @@ import { allMoves } from "#app/data/move"; -import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; @@ -33,31 +32,45 @@ describe("Abilities - Aura Break", () => { game.override.enemySpecies(Species.SHUCKLE); }); - it("reverses the effect of fairy aura", async () => { + it("reverses the effect of Fairy Aura", async () => { const moveToCheck = allMoves[Moves.MOONBLAST]; const basePower = moveToCheck.power; game.override.ability(Abilities.FAIRY_AURA); vi.spyOn(moveToCheck, "calculateBattlePower"); - await game.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([Species.PIKACHU]); game.move.select(Moves.MOONBLAST); - await game.phaseInterceptor.to(MoveEffectPhase); + await game.phaseInterceptor.to("MoveEffectPhase"); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(expect.closeTo(basePower * auraBreakMultiplier)); }); - it("reverses the effect of dark aura", async () => { + it("reverses the effect of Dark Aura", async () => { const moveToCheck = allMoves[Moves.DARK_PULSE]; const basePower = moveToCheck.power; game.override.ability(Abilities.DARK_AURA); vi.spyOn(moveToCheck, "calculateBattlePower"); - await game.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([Species.PIKACHU]); game.move.select(Moves.DARK_PULSE); - await game.phaseInterceptor.to(MoveEffectPhase); + await game.phaseInterceptor.to("MoveEffectPhase"); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(expect.closeTo(basePower * auraBreakMultiplier)); }); + + it("has no effect if neither Fairy Aura nor Dark Aura are present", async () => { + const moveToCheck = allMoves[Moves.MOONBLAST]; + const basePower = moveToCheck.power; + + game.override.ability(Abilities.BALL_FETCH); + vi.spyOn(moveToCheck, "calculateBattlePower"); + + await game.classicMode.startBattle([Species.PIKACHU]); + game.move.select(Moves.MOONBLAST); + await game.phaseInterceptor.to("MoveEffectPhase"); + + expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(basePower); + }); }); From d58f03528776a56e0fc1b8cfc6d1a99ae3561038 Mon Sep 17 00:00:00 2001 From: "Adrian T." <68144167+torranx@users.noreply.github.com> Date: Fri, 6 Sep 2024 17:41:48 +0800 Subject: [PATCH 06/22] [Misc] Migrate REROLL_TARGET to SHOP_CURSOR_TARGET (#4016) * migrate reroll target to shop cursor target * delete key after migrating --- src/system/game-data.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 1a47294906e..746af4d47a5 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -857,6 +857,14 @@ export class GameData { const settings = JSON.parse(localStorage.getItem("settings")!); // TODO: is this bang correct? + // TODO: Remove this block after save migration is implemented + if (settings.hasOwnProperty("REROLL_TARGET") && !settings.hasOwnProperty(SettingKeys.Shop_Cursor_Target)) { + settings[SettingKeys.Shop_Cursor_Target] = settings["REROLL_TARGET"]; + delete settings["REROLL_TARGET"]; + localStorage.setItem("settings", JSON.stringify(settings)); + } + // End of block to remove + for (const setting of Object.keys(settings)) { setSetting(this.scene, setting, settings[setting]); } From d8304421cf145f0b714ec77908a72db5fb137562 Mon Sep 17 00:00:00 2001 From: flx-sta <50131232+flx-sta@users.noreply.github.com> Date: Fri, 6 Sep 2024 10:23:19 -0700 Subject: [PATCH 07/22] fix endless end dialogue (#4069) It was only displaying `ending_endless` because the `PGM` prefix was still present --- src/phases/game-over-phase.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/phases/game-over-phase.ts b/src/phases/game-over-phase.ts index ebe58b20d3e..17805e90f0f 100644 --- a/src/phases/game-over-phase.ts +++ b/src/phases/game-over-phase.ts @@ -49,7 +49,9 @@ export class GameOverPhase extends BattlePhase { } if (this.victory && this.scene.gameMode.isEndless) { - this.scene.ui.showDialogue(i18next.t("PGMmiscDialogue:ending_endless"), i18next.t("PGMmiscDialogue:ending_name"), 0, () => this.handleGameOver()); + const genderIndex = this.scene.gameData.gender ?? PlayerGender.UNSET; + const genderStr = PlayerGender[genderIndex].toLowerCase(); + this.scene.ui.showDialogue(i18next.t("miscDialogue:ending_endless", { context: genderStr }), i18next.t("miscDialogue:ending_name"), 0, () => this.handleGameOver()); } else if (this.victory || !this.scene.enableRetries) { this.handleGameOver(); } else { From acda34c2e4d040aba44908691b23e1005dfdb1a6 Mon Sep 17 00:00:00 2001 From: "Adrian T." <68144167+torranx@users.noreply.github.com> Date: Sat, 7 Sep 2024 02:15:15 +0800 Subject: [PATCH 08/22] [P2 Bug] Underwater and underground Pokemond do not take sand/hail damage (#4047) * fix sandstorm/hail interaction with semi invulnerable state * cant fly high enough to avoid sandstorm/hail damage --- src/phases/weather-effect-phase.ts | 15 +++--- src/test/arena/weather_hail.test.ts | 62 ++++++++++++++++++++++++ src/test/arena/weather_sandstorm.test.ts | 59 ++++++++++++++++++++++ 3 files changed, 129 insertions(+), 7 deletions(-) create mode 100644 src/test/arena/weather_hail.test.ts create mode 100644 src/test/arena/weather_sandstorm.test.ts diff --git a/src/phases/weather-effect-phase.ts b/src/phases/weather-effect-phase.ts index 71ca7f9b505..ccfc9abb64f 100644 --- a/src/phases/weather-effect-phase.ts +++ b/src/phases/weather-effect-phase.ts @@ -1,10 +1,11 @@ -import BattleScene from "#app/battle-scene.js"; +import BattleScene from "#app/battle-scene"; import { applyPreWeatherEffectAbAttrs, SuppressWeatherEffectAbAttr, PreWeatherDamageAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPostWeatherLapseAbAttrs, PostWeatherLapseAbAttr } from "#app/data/ability.js"; -import { CommonAnim } from "#app/data/battle-anims.js"; -import { Weather, getWeatherDamageMessage, getWeatherLapseMessage } from "#app/data/weather.js"; -import { WeatherType } from "#app/enums/weather-type.js"; -import Pokemon, { HitResult } from "#app/field/pokemon.js"; -import * as Utils from "#app/utils.js"; +import { CommonAnim } from "#app/data/battle-anims"; +import { Weather, getWeatherDamageMessage, getWeatherLapseMessage } from "#app/data/weather"; +import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { WeatherType } from "#app/enums/weather-type"; +import Pokemon, { HitResult } from "#app/field/pokemon"; +import * as Utils from "#app/utils"; import { CommonAnimPhase } from "./common-anim-phase"; export class WeatherEffectPhase extends CommonAnimPhase { @@ -39,7 +40,7 @@ export class WeatherEffectPhase extends CommonAnimPhase { applyPreWeatherEffectAbAttrs(PreWeatherDamageAbAttr, pokemon, this.weather, cancelled); applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled); - if (cancelled.value) { + if (cancelled.value || pokemon.getTag(BattlerTagType.UNDERGROUND) || pokemon.getTag(BattlerTagType.UNDERWATER)) { return; } diff --git a/src/test/arena/weather_hail.test.ts b/src/test/arena/weather_hail.test.ts new file mode 100644 index 00000000000..75125b3448c --- /dev/null +++ b/src/test/arena/weather_hail.test.ts @@ -0,0 +1,62 @@ +import { WeatherType } from "#app/data/weather"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "../utils/testUtils"; +import { BattlerIndex } from "#app/battle"; + +describe("Weather - Hail", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .weather(WeatherType.HAIL) + .battleType("single") + .moveset(SPLASH_ONLY) + .enemyMoveset(SPLASH_ONLY) + .enemySpecies(Species.MAGIKARP); + }); + + it("inflicts damage equal to 1/16 of Pokemon's max HP at turn end", async () => { + await game.classicMode.startBattle([Species.MAGIKARP]); + + game.move.select(Moves.SPLASH); + await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + + await game.phaseInterceptor.to("TurnEndPhase"); + + game.scene.getField(true).forEach(pokemon => { + expect(pokemon.hp).toBeLessThan(pokemon.getMaxHp() - Math.floor(pokemon.getMaxHp() / 16)); + }); + }); + + it("does not inflict damage to a Pokemon that is underwater (Dive) or underground (Dig)", async () => { + game.override.moveset([Moves.DIG]); + await game.classicMode.startBattle([Species.MAGIKARP]); + + game.move.select(Moves.DIG); + await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + + await game.phaseInterceptor.to("TurnEndPhase"); + + const playerPokemon = game.scene.getPlayerPokemon()!; + const enemyPokemon = game.scene.getEnemyPokemon()!; + + expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp()); + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp() - Math.floor(enemyPokemon.getMaxHp() / 16)); + }); +}); diff --git a/src/test/arena/weather_sandstorm.test.ts b/src/test/arena/weather_sandstorm.test.ts new file mode 100644 index 00000000000..978774ba4c1 --- /dev/null +++ b/src/test/arena/weather_sandstorm.test.ts @@ -0,0 +1,59 @@ +import { WeatherType } from "#app/data/weather"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "../utils/testUtils"; + +describe("Weather - Sandstorm", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .weather(WeatherType.SANDSTORM) + .battleType("single") + .moveset(SPLASH_ONLY) + .enemyMoveset(SPLASH_ONLY) + .enemySpecies(Species.MAGIKARP); + }); + + it("inflicts damage equal to 1/16 of Pokemon's max HP at turn end", async () => { + await game.classicMode.startBattle([Species.MAGIKARP]); + + game.move.select(Moves.SPLASH); + + await game.phaseInterceptor.to("TurnEndPhase"); + + game.scene.getField(true).forEach(pokemon => { + expect(pokemon.hp).toBeLessThan(pokemon.getMaxHp() - Math.floor(pokemon.getMaxHp() / 16)); + }); + }); + + it("does not inflict damage to a Pokemon that is underwater (Dive) or underground (Dig)", async () => { + game.override.moveset([Moves.DIVE]); + await game.classicMode.startBattle([Species.MAGIKARP]); + + game.move.select(Moves.DIVE); + + await game.phaseInterceptor.to("TurnEndPhase"); + + const playerPokemon = game.scene.getPlayerPokemon()!; + const enemyPokemon = game.scene.getEnemyPokemon()!; + + expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp()); + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp() - Math.floor(enemyPokemon.getMaxHp() / 16)); + }); +}); From 33cb99977493c6b7bd03a07ae20ddc574b7800bf Mon Sep 17 00:00:00 2001 From: Chapybara-jp Date: Fri, 6 Sep 2024 20:51:32 +0200 Subject: [PATCH 09/22] [Localization] [JA] Translated bgm-name.json (#4066) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Translated bgm-name.json Song titles from Bulbapedia and https://w.atwiki.jp/gamemusicbest100/ Kept mainline game abbrevs., changed PMD to ポケダン for clarity Added translations for the original songs * Update bgm-name.json * Update bgm-name.json * Update bgm-name.json --- src/locales/ja/bgm-name.json | 292 +++++++++++++++++------------------ 1 file changed, 146 insertions(+), 146 deletions(-) diff --git a/src/locales/ja/bgm-name.json b/src/locales/ja/bgm-name.json index 8838942c8a6..fc3d4c0fdd2 100644 --- a/src/locales/ja/bgm-name.json +++ b/src/locales/ja/bgm-name.json @@ -1,150 +1,150 @@ { - "music": "Music: ", + "music": "BGM: ", "missing_entries": "{{name}}", - "battle_kanto_champion": "B2W2 Kanto Champion Battle", - "battle_johto_champion": "B2W2 Johto Champion Battle", - "battle_hoenn_champion_g5": "B2W2 Hoenn Champion Battle", - "battle_hoenn_champion_g6": "ORAS Hoenn Champion Battle", - "battle_sinnoh_champion": "B2W2 Sinnoh Champion Battle", - "battle_champion_alder": "BW Unova Champion Battle", - "battle_champion_iris": "B2W2 Unova Champion Battle", - "battle_kalos_champion": "XY Kalos Champion Battle", - "battle_alola_champion": "USUM Alola Champion Battle", - "battle_galar_champion": "SWSH Galar Champion Battle", - "battle_champion_geeta": "SV Champion Geeta Battle", - "battle_champion_nemona": "SV Champion Nemona Battle", - "battle_champion_kieran": "SV Champion Kieran Battle", - "battle_hoenn_elite": "ORAS Elite Four Battle", - "battle_unova_elite": "BW Elite Four Battle", - "battle_kalos_elite": "XY Elite Four Battle", - "battle_alola_elite": "SM Elite Four Battle", - "battle_galar_elite": "SWSH League Tournament Battle", - "battle_paldea_elite": "SV Elite Four Battle", - "battle_bb_elite": "SV BB League Elite Four Battle", - "battle_final_encounter": "PMD RTDX Rayquaza's Domain", - "battle_final": "BW Ghetsis Battle", - "battle_kanto_gym": "B2W2 Kanto Gym Battle", - "battle_johto_gym": "B2W2 Johto Gym Battle", - "battle_hoenn_gym": "B2W2 Hoenn Gym Battle", - "battle_sinnoh_gym": "B2W2 Sinnoh Gym Battle", - "battle_unova_gym": "BW Unova Gym Battle", - "battle_kalos_gym": "XY Kalos Gym Battle", - "battle_galar_gym": "SWSH Galar Gym Battle", - "battle_paldea_gym": "SV Paldea Gym Battle", - "battle_legendary_kanto": "XY Kanto Legendary Battle", - "battle_legendary_raikou": "HGSS Raikou Battle", - "battle_legendary_entei": "HGSS Entei Battle", - "battle_legendary_suicune": "HGSS Suicune Battle", - "battle_legendary_lugia": "HGSS Lugia Battle", - "battle_legendary_ho_oh": "HGSS Ho-oh Battle", - "battle_legendary_regis_g5": "B2W2 Legendary Titan Battle", - "battle_legendary_regis_g6": "ORAS Legendary Titan Battle", - "battle_legendary_gro_kyo": "ORAS Groudon & Kyogre Battle", - "battle_legendary_rayquaza": "ORAS Rayquaza Battle", - "battle_legendary_deoxys": "ORAS Deoxys Battle", - "battle_legendary_lake_trio": "ORAS Lake Guardians Battle", - "battle_legendary_sinnoh": "ORAS Sinnoh Legendary Battle", - "battle_legendary_dia_pal": "ORAS Dialga & Palkia Battle", - "battle_legendary_origin_forme": "LA Origin Dialga & Palkia Battle", - "battle_legendary_giratina": "ORAS Giratina Battle", - "battle_legendary_arceus": "HGSS Arceus Battle", - "battle_legendary_unova": "BW Unova Legendary Battle", - "battle_legendary_kyurem": "BW Kyurem Battle", - "battle_legendary_res_zek": "BW Reshiram & Zekrom Battle", - "battle_legendary_xern_yvel": "XY Xerneas & Yveltal Battle", - "battle_legendary_tapu": "SM Tapu Battle", - "battle_legendary_sol_lun": "SM Solgaleo & Lunala Battle", - "battle_legendary_ub": "SM Ultra Beast Battle", - "battle_legendary_dusk_dawn": "USUM Dusk Mane & Dawn Wings Necrozma Battle", - "battle_legendary_ultra_nec": "USUM Ultra Necrozma Battle", - "battle_legendary_zac_zam": "SWSH Zacian & Zamazenta Battle", - "battle_legendary_glas_spec": "SWSH Glastrier & Spectrier Battle", - "battle_legendary_calyrex": "SWSH Calyrex Battle", - "battle_legendary_riders": "SWSH Ice & Shadow Rider Calyrex Battle", - "battle_legendary_birds_galar": "SWSH Galarian Legendary Birds Battle", - "battle_legendary_ruinous": "SV Treasures of Ruin Battle", - "battle_legendary_kor_mir": "SV Depths of Area Zero Battle", - "battle_legendary_loyal_three": "SV Loyal Three Battle", - "battle_legendary_ogerpon": "SV Ogerpon Battle", - "battle_legendary_terapagos": "SV Terapagos Battle", - "battle_legendary_pecharunt": "SV Pecharunt Battle", - "battle_rival": "BW Rival Battle", - "battle_rival_2": "BW N Battle", - "battle_rival_3": "BW Final N Battle", - "battle_trainer": "BW Trainer Battle", - "battle_wild": "BW Wild Battle", - "battle_wild_strong": "BW Strong Wild Battle", - "end_summit": "PMD RTDX Sky Tower Summit", - "battle_rocket_grunt": "HGSS Team Rocket Battle", - "battle_aqua_magma_grunt": "ORAS Team Aqua & Magma Battle", - "battle_galactic_grunt": "BDSP Team Galactic Battle", - "battle_plasma_grunt": "BW Team Plasma Battle", - "battle_flare_grunt": "XY Team Flare Battle", - "battle_aether_grunt": "SM Aether Foundation Battle", - "battle_skull_grunt": "SM Team Skull Battle", - "battle_macro_grunt": "SWSH Trainer Battle", - "battle_galactic_admin": "BDSP Team Galactic Admin Battle", - "battle_skull_admin": "SM Team Skull Admin Battle", - "battle_oleana": "SWSH Oleana Battle", - "battle_rocket_boss": "USUM Giovanni Battle", - "battle_aqua_magma_boss": "ORAS Archie & Maxie Battle", - "battle_galactic_boss": "BDSP Cyrus Battle", - "battle_plasma_boss": "B2W2 Ghetsis Battle", - "battle_flare_boss": "XY Lysandre Battle", - "battle_aether_boss": "SM Lusamine Battle", - "battle_skull_boss": "SM Guzma Battle", - "battle_macro_boss": "SWSH Rose Battle", + "battle_kanto_champion": "B2W2 戦闘!チャンピオン(カントー)", + "battle_johto_champion": "B2W2 戦闘!チャンピオン(ジョウト)", + "battle_hoenn_champion_g5": "B2W2 戦闘!チャンピオン(ホウエン)", + "battle_hoenn_champion_g6": "ORAS 決戦!ダイゴ", + "battle_sinnoh_champion": "B2W2 戦闘!チャンピオン(シンオウ)", + "battle_champion_alder": "BW チャンピオン アデク", + "battle_champion_iris": "B2W2 戦闘!チャンピオンアイリス", + "battle_kalos_champion": "XY 戦闘!チャンピオン", + "battle_alola_champion": "USUM 頂上決戦!ハウ", + "battle_galar_champion": "SWSH 決戦!チャンピオンダンデ", + "battle_champion_geeta": "SV 戦闘!トップチャンピオン", + "battle_champion_nemona": "SV 戦闘!チャンピオンネモ", + "battle_champion_kieran": "SV 戦闘!チャンピオンスグリ", + "battle_hoenn_elite": "ORAS 戦闘!四天王", + "battle_unova_elite": "BW 戦闘!四天王", + "battle_kalos_elite": "XY 戦闘!四天王", + "battle_alola_elite": "SM 戦闘!四天王", + "battle_galar_elite": "SWSH 戦闘!ファイナルトーナメント!", + "battle_paldea_elite": "SV 戦闘!四天王", + "battle_bb_elite": "SV 戦闘!ブルベリーグ四天王", + "battle_final_encounter": "ポケダンDX レックウザ登場", + "battle_final": "BW 戦闘!ゲーチス", + "battle_kanto_gym": "B2W2 戦闘!ジムリーダー(カントー)", + "battle_johto_gym": "B2W2 戦闘!ジムリーダー(ジョウト)", + "battle_hoenn_gym": "B2W2 戦闘!ジムリーダー(ホウエン)", + "battle_sinnoh_gym": "B2W2 戦闘!ジムリーダー(シンオウ)", + "battle_unova_gym": "BW 戦闘!ジムリーダー", + "battle_kalos_gym": "XY 戦闘!ジムリーダー", + "battle_galar_gym": "SWSH 戦闘!ジムリーダー", + "battle_paldea_gym": "SV 戦闘!ジムリーダー", + "battle_legendary_kanto": "XY 戦闘!ミュウツー", + "battle_legendary_raikou": "HGSS 戦闘!ライコウ", + "battle_legendary_entei": "HGSS 戦闘!エンテイ", + "battle_legendary_suicune": "HGSS 戦闘!スイクン", + "battle_legendary_lugia": "HGSS 戦闘!ルギア", + "battle_legendary_ho_oh": "HGSS 戦闘!ホウオウ", + "battle_legendary_regis_g5": "B2W2 戦闘!レジロック・レジアイス・レジスチル", + "battle_legendary_regis_g6": "ORAS 戦闘!レジロック・レジアイス・レジスチル", + "battle_legendary_gro_kyo": "ORAS 戦闘!ゲンシカイキ", + "battle_legendary_rayquaza": "ORAS 戦闘!超古代ポケモン", + "battle_legendary_deoxys": "ORAS 戦闘!デオキシス", + "battle_legendary_lake_trio": "ORAS 戦闘!ユクシー・エムリット・アグノム", + "battle_legendary_sinnoh": "ORAS 戦闘!伝説のポケモン(シンオウ)", + "battle_legendary_dia_pal": "ORAS 戦闘!ディアルガ・パルキア", + "battle_legendary_origin_forme": "LA 戦い:ディアルガ・パルキア(オリジンフォルム)", + "battle_legendary_giratina": "ORAS 戦闘!ギラティナ", + "battle_legendary_arceus": "HGSS アルセウス", + "battle_legendary_unova": "BW 戦闘!伝説のポケモン", + "battle_legendary_kyurem": "BW 戦闘!キュレム", + "battle_legendary_res_zek": "BW 戦闘!ゼクロム・レシラム", + "battle_legendary_xern_yvel": "XY 戦闘!ゼルネアス・イベルタル・ジガルデ", + "battle_legendary_tapu": "SM 戦闘!カプ", + "battle_legendary_sol_lun": "SM 戦闘!ソルガレオ・ルナアーラ", + "battle_legendary_ub": "SM 戦闘!ウルトラビースト", + "battle_legendary_dusk_dawn": "USUM 戦闘!日食・月食ネクロズマ", + "battle_legendary_ultra_nec": "USUM 戦闘!ウルトラネクロズマ", + "battle_legendary_zac_zam": "SWSH 戦闘!ザシアン・ザマゼンタ", + "battle_legendary_glas_spec": "SWSH 戦闘!ブリザポス・レイスポス", + "battle_legendary_calyrex": "SWSH 戦闘!バドレックス", + "battle_legendary_riders": "SWSH 戦闘!豊穣の王", + "battle_legendary_birds_galar": "SWSH 戦闘!伝説のとりポケモン", + "battle_legendary_ruinous": "SV 戦闘!災厄ポケモン", + "battle_legendary_kor_mir": "SV 戦闘!エリアゼロのポケモン", + "battle_legendary_loyal_three": "SV 戦闘!ともっこ", + "battle_legendary_ogerpon": "SV 戦闘!オーガポン", + "battle_legendary_terapagos": "SV 戦闘!テラパゴス", + "battle_legendary_pecharunt": "SV 戦闘!モモワロウ", + "battle_rival": "BW 戦闘!チェレン・ベル", + "battle_rival_2": "BW 戦闘!N", + "battle_rival_3": "BW 決戦!N", + "battle_trainer": "BW 戦闘!トレーナー", + "battle_wild": "BW 戦闘!野生ポケモン", + "battle_wild_strong": "BW 戦闘!強い野生ポケモン", + "end_summit": "ポケダンDX 天空の塔 最上階", + "battle_rocket_grunt": "HGSS 戦闘!ロケット団", + "battle_aqua_magma_grunt": "ORAS 戦闘!アクア団・マグマ団", + "battle_galactic_grunt": "BDSP 戦闘!ギンガ団", + "battle_plasma_grunt": "BW 戦闘!プラズマ団", + "battle_flare_grunt": "XY 戦闘!フレア団", + "battle_aether_grunt": "SM 戦闘!エーテル財団トレーナー", + "battle_skull_grunt": "SM 戦闘!スカル団", + "battle_macro_grunt": "SWSH 戦闘!トレーナー", + "battle_galactic_admin": "BDSP 戦闘!ギンガ団幹部", + "battle_skull_admin": "SM 戦闘!スカル団幹部", + "battle_oleana": "SWSH 戦闘!オリーヴ", + "battle_rocket_boss": "USUM 戦闘!レインボーロケット団ボス", + "battle_aqua_magma_boss": "ORAS 戦闘!アクア団・マグマ団のリーダー", + "battle_galactic_boss": "BDSP 戦闘!ギンガ団ボス", + "battle_plasma_boss": "B2W2 戦闘!ゲーチス", + "battle_flare_boss": "XY 戦闘!フラダリ", + "battle_aether_boss": "SM 戦闘!ルザミーネ", + "battle_skull_boss": "SM 戦闘!スカル団ボス", + "battle_macro_boss": "SWSH 戦闘!ローズ", - "abyss": "PMD EoS Dark Crater", - "badlands": "PMD EoS Barren Valley", - "beach": "PMD EoS Drenched Bluff", - "cave": "PMD EoS Sky Peak Cave", - "construction_site": "PMD EoS Boulder Quarry", - "desert": "PMD EoS Northern Desert", - "dojo": "PMD EoS Marowak Dojo", - "end": "PMD RTDX Sky Tower", - "factory": "PMD EoS Concealed Ruins", - "fairy_cave": "PMD EoS Star Cave", - "forest": "PMD EoS Dusk Forest", - "grass": "PMD EoS Apple Woods", - "graveyard": "PMD EoS Mystifying Forest", - "ice_cave": "PMD EoS Vast Ice Mountain", - "island": "PMD EoS Craggy Coast", - "jungle": "Lmz - Jungle", - "laboratory": "Firel - Laboratory", - "lake": "PMD EoS Crystal Cave", - "meadow": "PMD EoS Sky Peak Forest", - "metropolis": "Firel - Metropolis", - "mountain": "PMD EoS Mt. Horn", - "plains": "PMD EoS Sky Peak Prairie", - "power_plant": "PMD EoS Far Amp Plains", - "ruins": "PMD EoS Deep Sealed Ruin", - "sea": "Andr06 - Marine Mystique", - "seabed": "Firel - Seabed", - "slum": "Andr06 - Sneaky Snom", - "snowy_forest": "PMD EoS Sky Peak Snowfield", - "space": "Firel - Aether", - "swamp": "PMD EoS Surrounded Sea", - "tall_grass": "PMD EoS Foggy Forest", - "temple": "PMD EoS Aegis Cave", - "town": "PMD EoS Random Dungeon Theme 3", - "volcano": "PMD EoS Steam Cave", - "wasteland": "PMD EoS Hidden Highland", - "encounter_ace_trainer": "BW Trainers' Eyes Meet (Ace Trainer)", - "encounter_backpacker": "BW Trainers' Eyes Meet (Backpacker)", - "encounter_clerk": "BW Trainers' Eyes Meet (Clerk)", - "encounter_cyclist": "BW Trainers' Eyes Meet (Cyclist)", - "encounter_lass": "BW Trainers' Eyes Meet (Lass)", - "encounter_parasol_lady": "BW Trainers' Eyes Meet (Parasol Lady)", - "encounter_pokefan": "BW Trainers' Eyes Meet (Poke Fan)", - "encounter_psychic": "BW Trainers' Eyes Meet (Psychic)", - "encounter_rich": "BW Trainers' Eyes Meet (Gentleman)", - "encounter_rival": "BW Cheren", - "encounter_roughneck": "BW Trainers' Eyes Meet (Roughneck)", - "encounter_scientist": "BW Trainers' Eyes Meet (Scientist)", - "encounter_twins": "BW Trainers' Eyes Meet (Twins)", - "encounter_youngster": "BW Trainers' Eyes Meet (Youngster)", - "heal": "BW Pokémon Heal", - "menu": "PMD EoS Welcome to the World of Pokémon!", - "title": "PMD EoS Top Menu Theme" + "abyss": "ポケダン空 やみのかこう", + "badlands": "ポケダン空 こかつのたに", + "beach": "ポケダン空 しめったいわば", + "cave": "ポケダン空 そらのいただき(どうくつ)", + "construction_site": "ポケダン空 きょだいがんせきぐん", + "desert": "ポケダン空 きたのさばく", + "dojo": "ポケダン空 ガラガラどうじょう", + "end": "ポケダンDX 天空の塔", + "factory": "ポケダン空 かくされたいせき", + "fairy_cave": "ポケダン空 ほしのどうくつ", + "forest": "ポケダン空 くろのもり", + "grass": "ポケダン空 リンゴのもり", + "graveyard": "ポケダン空 しんぴのもり", + "ice_cave": "ポケダン空 だいひょうざん", + "island": "ポケダン空 えんがんのいわば", + "jungle": "Lmz - Jungle(ジャングル)", + "laboratory": "Firel - Laboratory(ラボラトリー)", + "lake": "ポケダン空 すいしょうのどうくつ", + "meadow": "ポケダン空 そらのいただき(もり)", + "metropolis": "Firel - Metropolis(大都市)", + "mountain": "ポケダン空 ツノやま", + "plains": "ポケダン空 そらのいただき(そうげん)", + "power_plant": "ポケダン空 エレキへいげん", + "ruins": "ポケダン空 ふういんのいわば", + "sea": "Andr06 - Marine Mystique(海の神秘性)", + "seabed": "Firel - Seabed(海底)", + "slum": "Andr06 - Sneaky Snom(ずるいユキハミ)", + "snowy_forest": "ポケダン空 そらのいただき(ゆきやま)", + "space": "Firel - Aether(エーテル)", + "swamp": "ポケダン空 とざされたうみ", + "tall_grass": "ポケダン空 のうむのもり", + "temple": "ポケダン空 ばんにんのどうくつ", + "town": "ポケダン空 ランダムダンジョン3", + "volcano": "ポケダン空 ねっすいのどうくつ", + "wasteland": "ポケダン空 まぼろしのだいち", + "encounter_ace_trainer": "BW 視線!エリートトレーナー", + "encounter_backpacker": "BW 視線!バックパッカー", + "encounter_clerk": "BW 視線!ビジネスマン", + "encounter_cyclist": "BW 視線!サイクリング", + "encounter_lass": "BW 視線!ミニスカート", + "encounter_parasol_lady": "BW 視線!パラソルおねえさん", + "encounter_pokefan": "BW 視線!だいすきクラブ", + "encounter_psychic": "BW 視線!サイキッカー", + "encounter_rich": "BW 視線!ジェントルマン", + "encounter_rival": "BW チェレンのテーマ", + "encounter_roughneck": "BW 視線!スキンヘッズ", + "encounter_scientist": "BW 視線!けんきゅういん", + "encounter_twins": "BW 視線!ふたごちゃん", + "encounter_youngster": "BW 視線!たんぱんこぞう", + "heal": "BW 回復", + "menu": "ポケダン空 ようこそ! ポケモンたちのせかいへ!", + "title": "ポケダン空 トップメニュー" } From e6a574c48f3627b7ec6283cbd1772213c372851d Mon Sep 17 00:00:00 2001 From: "Adrian T." <68144167+torranx@users.noreply.github.com> Date: Sat, 7 Sep 2024 03:17:08 +0800 Subject: [PATCH 10/22] =?UTF-8?q?[P2=20Bug]=20Revert=20to=20normal=20form?= =?UTF-8?q?=20when=20Pok=C3=A9mon=20is=20fainted=20(#4049)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * revert to normal forms when fainted * Remove `.js` from import Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> --- src/phases/faint-phase.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/phases/faint-phase.ts b/src/phases/faint-phase.ts index d5dd9f61340..48366afaad4 100644 --- a/src/phases/faint-phase.ts +++ b/src/phases/faint-phase.ts @@ -17,6 +17,7 @@ import { ToggleDoublePositionPhase } from "./toggle-double-position-phase"; import { GameOverPhase } from "./game-over-phase"; import { SwitchPhase } from "./switch-phase"; import { VictoryPhase } from "./victory-phase"; +import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms"; export class FaintPhase extends PokemonPhase { private preventEndure: boolean; @@ -59,6 +60,7 @@ export class FaintPhase extends PokemonPhase { } this.scene.queueMessage(i18next.t("battle:fainted", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }), null, true); + this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeActiveTrigger, true); if (pokemon.turnData?.attacksReceived?.length) { const lastAttack = pokemon.turnData.attacksReceived[0]; From ae50db7710ce371eb806f93c7dde386bee45e948 Mon Sep 17 00:00:00 2001 From: flx-sta <50131232+flx-sta@users.noreply.github.com> Date: Fri, 6 Sep 2024 16:24:38 -0700 Subject: [PATCH 11/22] [Optimization] parallel testing (#4075) * add: vitest projects (multiple) preparations for parallel testing * update: tests workflow better parallel testing --- .github/workflows/tests.yml | 78 +++++++++++++++++++++++++++++++++++-- vitest.config.ts | 59 +++++++++++++++------------- vitest.workspace.ts | 54 +++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 31 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index adac45519ab..2a78ec252b8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,8 +15,8 @@ on: types: [checks_requested] jobs: - run-tests: # Define a job named "run-tests" - name: Run tests # Human-readable name for the job + run-misc-tests: # Define a job named "run-tests" + name: Run misc tests # Human-readable name for the job runs-on: ubuntu-latest # Specify the latest Ubuntu runner for the job steps: @@ -31,5 +31,75 @@ jobs: - name: Install Node.js dependencies # Step to install Node.js dependencies run: npm ci # Use 'npm ci' to install dependencies - - name: tests # Step to run tests - run: npm run test:silent \ No newline at end of file + - name: pre-test # pre-test to check overrides + run: npx vitest run --project pre + - name: test misc + run: npx vitest --project misc + + run-abilities-tests: + name: Run abilities tests + runs-on: ubuntu-latest + steps: + - name: Check out Git repository + uses: actions/checkout@v4 + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Install Node.js dependencies + run: npm ci + - name: pre-test + run: npx vitest run --project pre + - name: test abilities + run: npx vitest --project abilities + + run-items-tests: + name: Run items tests + runs-on: ubuntu-latest + steps: + - name: Check out Git repository + uses: actions/checkout@v4 + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Install Node.js dependencies + run: npm ci + - name: pre-test + run: npx vitest run --project pre + - name: test items + run: npx vitest --project items + + run-moves-tests: + name: Run moves tests + runs-on: ubuntu-latest + steps: + - name: Check out Git repository + uses: actions/checkout@v4 + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Install Node.js dependencies + run: npm ci + - name: pre-test + run: npx vitest run --project pre + - name: test moves + run: npx vitest --project moves + + run-battle-tests: + name: Run battle tests + runs-on: ubuntu-latest + steps: + - name: Check out Git repository + uses: actions/checkout@v4 + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Install Node.js dependencies + run: npm ci + - name: pre-test + run: npx vitest run --project pre + - name: test battle + run: npx vitest --project battle \ No newline at end of file diff --git a/vitest.config.ts b/vitest.config.ts index d1827103807..9a765a89ae7 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,38 +1,43 @@ -import { defineProject } from 'vitest/config'; +import { defineProject, UserWorkspaceConfig } from 'vitest/config'; import { defaultConfig } from './vite.config'; +export const defaultProjectTestConfig: UserWorkspaceConfig["test"] = { + setupFiles: ['./src/test/vitest.setup.ts'], + server: { + deps: { + inline: ['vitest-canvas-mock'], + //@ts-ignore + optimizer: { + web: { + include: ['vitest-canvas-mock'], + } + } + } + }, + environment: 'jsdom' as const, + environmentOptions: { + jsdom: { + resources: 'usable', + }, + }, + threads: false, + trace: true, + restoreMocks: true, + watch: false, + coverage: { + provider: 'istanbul' as const, + reportsDirectory: 'coverage' as const, + reporters: ['text-summary', 'html'], + }, +} + export default defineProject(({ mode }) => ({ ...defaultConfig, test: { + ...defaultProjectTestConfig, name: "main", include: ["./src/test/**/*.{test,spec}.ts"], exclude: ["./src/test/pre.test.ts"], - setupFiles: ['./src/test/vitest.setup.ts'], - server: { - deps: { - inline: ['vitest-canvas-mock'], - optimizer: { - web: { - include: ['vitest-canvas-mock'], - } - } - } - }, - environment: 'jsdom' as const, - environmentOptions: { - jsdom: { - resources: 'usable', - }, - }, - threads: false, - trace: true, - restoreMocks: true, - watch: false, - coverage: { - provider: 'istanbul' as const, - reportsDirectory: 'coverage' as const, - reporters: ['text-summary', 'html'], - }, }, esbuild: { pure: mode === 'production' ? [ 'console.log' ] : [], diff --git a/vitest.workspace.ts b/vitest.workspace.ts index 38121942004..a885b77dc9d 100644 --- a/vitest.workspace.ts +++ b/vitest.workspace.ts @@ -1,5 +1,6 @@ import { defineWorkspace } from "vitest/config"; import { defaultConfig } from "./vite.config"; +import { defaultProjectTestConfig } from "./vitest.config"; export default defineWorkspace([ { @@ -10,5 +11,58 @@ export default defineWorkspace([ environment: "jsdom", }, }, + { + ...defaultConfig, + test: { + ...defaultProjectTestConfig, + name: "misc", + include: [ + "src/test/achievements/**/*.{test,spec}.ts", + "src/test/arena/**/*.{test,spec}.ts", + "src/test/battlerTags/**/*.{test,spec}.ts", + "src/test/eggs/**/*.{test,spec}.ts", + "src/test/field/**/*.{test,spec}.ts", + "src/test/inputs/**/*.{test,spec}.ts", + "src/test/localization/**/*.{test,spec}.ts", + "src/test/phases/**/*.{test,spec}.ts", + "src/test/settingMenu/**/*.{test,spec}.ts", + "src/test/sprites/**/*.{test,spec}.ts", + "src/test/ui/**/*.{test,spec}.ts", + "src/test/*.{test,spec}.ts", + ], + }, + }, + { + ...defaultConfig, + test: { + ...defaultProjectTestConfig, + name: "abilities", + include: ["src/test/abilities/**/*.{test,spec}.ts"], + }, + }, + { + ...defaultConfig, + test: { + ...defaultProjectTestConfig, + name: "battle", + include: ["src/test/battle/**/*.{test,spec}.ts"], + }, + }, + { + ...defaultConfig, + test: { + ...defaultProjectTestConfig, + name: "items", + include: ["src/test/items/**/*.{test,spec}.ts"], + }, + }, + { + ...defaultConfig, + test: { + ...defaultProjectTestConfig, + name: "moves", + include: ["src/test/moves/**/*.{test,spec}.ts"], + }, + }, "./vitest.config.ts", ]); From ba212945deb7c48ad843ac939d4e43531c100c2f Mon Sep 17 00:00:00 2001 From: James Diefenbach <105332964+j-diefenbach@users.noreply.github.com> Date: Sat, 7 Sep 2024 10:34:13 +1000 Subject: [PATCH 12/22] [Enhancement] Darker egg summary background image (#4076) * darker egg-summary background * reset old background for beta * darker egg summary bg --------- Co-authored-by: James Diefenbach --- public/images/ui/egg_summary_bg.png | Bin 1064 -> 2209 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/public/images/ui/egg_summary_bg.png b/public/images/ui/egg_summary_bg.png index 658f5df0e96bd901d105690d73500b965788df5c..b4ee3d86a507bfb99b4f9af2d71b5065e4ac943b 100644 GIT binary patch literal 2209 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 Date: Fri, 6 Sep 2024 22:54:54 -0400 Subject: [PATCH 13/22] [Item/Balance] Overhaul Lapsing Modifiers (#4032) * Refactor Lapsing Modifiers, Lerp Hue of Count * Fix Unit Tests * Add Documentation to `hslToHex` Function * Change Descriptions for New Behavior * Add Documentation to Lapsing Modifiers * Add Unit Tests for Lures * Update Unit Tests for X Items and Lures * Update Boilerplate Error Message * Update Boilerplate Docs --- create-test-boilerplate.js | 12 +- src/locales/en/modifier-type.json | 8 +- src/modifier/modifier-type.ts | 44 ++-- src/modifier/modifier.ts | 207 +++++++++--------- src/test/items/dire_hit.test.ts | 4 +- .../double_battle_chance_booster.test.ts | 105 +++++++++ .../items/temp_stat_stage_booster.test.ts | 28 +-- src/utils.ts | 20 ++ 8 files changed, 285 insertions(+), 143 deletions(-) create mode 100644 src/test/items/double_battle_chance_booster.test.ts diff --git a/create-test-boilerplate.js b/create-test-boilerplate.js index bf68258f321..3c53eb1125b 100644 --- a/create-test-boilerplate.js +++ b/create-test-boilerplate.js @@ -4,7 +4,8 @@ import { fileURLToPath } from 'url'; /** * This script creates a test boilerplate file for a move or ability. - * @param {string} type - The type of test to create. Either "move" or "ability". + * @param {string} type - The type of test to create. Either "move", "ability", + * or "item". * @param {string} fileName - The name of the file to create. * @example npm run create-test move tackle */ @@ -19,7 +20,7 @@ const type = args[0]; // "move" or "ability" let fileName = args[1]; // The file name if (!type || !fileName) { - console.error('Please provide both a type ("move" or "ability") and a file name.'); + console.error('Please provide both a type ("move", "ability", or "item") and a file name.'); process.exit(1); } @@ -40,8 +41,11 @@ if (type === 'move') { } else if (type === 'ability') { dir = path.join(__dirname, 'src', 'test', 'abilities'); description = `Abilities - ${formattedName}`; +} else if (type === "item") { + dir = path.join(__dirname, 'src', 'test', 'items'); + description = `Items - ${formattedName}`; } else { - console.error('Invalid type. Please use "move" or "ability".'); + console.error('Invalid type. Please use "move", "ability", or "item".'); process.exit(1); } @@ -98,4 +102,4 @@ describe("${description}", () => { // Write the template content to the file fs.writeFileSync(filePath, content, 'utf8'); -console.log(`File created at: ${filePath}`); \ No newline at end of file +console.log(`File created at: ${filePath}`); diff --git a/src/locales/en/modifier-type.json b/src/locales/en/modifier-type.json index f73a3dcccae..babad57b81b 100644 --- a/src/locales/en/modifier-type.json +++ b/src/locales/en/modifier-type.json @@ -47,10 +47,14 @@ "description": "Changes a Pokémon's nature to {{natureName}} and permanently unlocks the nature for the starter." }, "DoubleBattleChanceBoosterModifierType": { - "description": "Doubles the chance of an encounter being a double battle for {{battleCount}} battles." + "description": "Quadruples the chance of an encounter being a double battle for up to {{battleCount}} battles." }, "TempStatStageBoosterModifierType": { - "description": "Increases the {{stat}} of all party members by 1 stage for 5 battles." + "description": "Increases the {{stat}} of all party members by {{amount}} for up to 5 battles.", + "extra": { + "stage": "1 stage", + "percentage": "30%" + } }, "AttackTypeBoosterModifierType": { "description": "Increases the power of a Pokémon's {{moveType}}-type moves by 20%." diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index fe586074c79..d6cfd017829 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -433,37 +433,44 @@ export class RememberMoveModifierType extends PokemonModifierType { } export class DoubleBattleChanceBoosterModifierType extends ModifierType { - public battleCount: integer; + private maxBattles: number; - constructor(localeKey: string, iconImage: string, battleCount: integer) { - super(localeKey, iconImage, (_type, _args) => new Modifiers.DoubleBattleChanceBoosterModifier(this, this.battleCount), "lure"); + constructor(localeKey: string, iconImage: string, maxBattles: number) { + super(localeKey, iconImage, (_type, _args) => new Modifiers.DoubleBattleChanceBoosterModifier(this, maxBattles), "lure"); - this.battleCount = battleCount; + this.maxBattles = maxBattles; } - getDescription(scene: BattleScene): string { - return i18next.t("modifierType:ModifierType.DoubleBattleChanceBoosterModifierType.description", { battleCount: this.battleCount }); + getDescription(_scene: BattleScene): string { + return i18next.t("modifierType:ModifierType.DoubleBattleChanceBoosterModifierType.description", { + battleCount: this.maxBattles + }); } } export class TempStatStageBoosterModifierType extends ModifierType implements GeneratedPersistentModifierType { private stat: TempBattleStat; - private key: string; + private nameKey: string; + private quantityKey: string; constructor(stat: TempBattleStat) { - const key = TempStatStageBoosterModifierTypeGenerator.items[stat]; - super("", key, (_type, _args) => new Modifiers.TempStatStageBoosterModifier(this, this.stat)); + const nameKey = TempStatStageBoosterModifierTypeGenerator.items[stat]; + super("", nameKey, (_type, _args) => new Modifiers.TempStatStageBoosterModifier(this, this.stat, 5)); this.stat = stat; - this.key = key; + this.nameKey = nameKey; + this.quantityKey = (stat !== Stat.ACC) ? "percentage" : "stage"; } get name(): string { - return i18next.t(`modifierType:TempStatStageBoosterItem.${this.key}`); + return i18next.t(`modifierType:TempStatStageBoosterItem.${this.nameKey}`); } getDescription(_scene: BattleScene): string { - return i18next.t("modifierType:ModifierType.TempStatStageBoosterModifierType.description", { stat: i18next.t(getStatKey(this.stat)) }); + return i18next.t("modifierType:ModifierType.TempStatStageBoosterModifierType.description", { + stat: i18next.t(getStatKey(this.stat)), + amount: i18next.t(`modifierType:ModifierType.TempStatStageBoosterModifierType.extra.${this.quantityKey}`) + }); } getPregenArgs(): any[] { @@ -1348,9 +1355,9 @@ export const modifierTypes = { SUPER_REPEL: () => new DoubleBattleChanceBoosterModifierType('Super Repel', 10), MAX_REPEL: () => new DoubleBattleChanceBoosterModifierType('Max Repel', 25),*/ - LURE: () => new DoubleBattleChanceBoosterModifierType("modifierType:ModifierType.LURE", "lure", 5), - SUPER_LURE: () => new DoubleBattleChanceBoosterModifierType("modifierType:ModifierType.SUPER_LURE", "super_lure", 10), - MAX_LURE: () => new DoubleBattleChanceBoosterModifierType("modifierType:ModifierType.MAX_LURE", "max_lure", 25), + LURE: () => new DoubleBattleChanceBoosterModifierType("modifierType:ModifierType.LURE", "lure", 10), + SUPER_LURE: () => new DoubleBattleChanceBoosterModifierType("modifierType:ModifierType.SUPER_LURE", "super_lure", 15), + MAX_LURE: () => new DoubleBattleChanceBoosterModifierType("modifierType:ModifierType.MAX_LURE", "max_lure", 30), SPECIES_STAT_BOOSTER: () => new SpeciesStatBoosterModifierTypeGenerator(), @@ -1358,9 +1365,12 @@ export const modifierTypes = { DIRE_HIT: () => new class extends ModifierType { getDescription(_scene: BattleScene): string { - return i18next.t("modifierType:ModifierType.TempStatStageBoosterModifierType.description", { stat: i18next.t("modifierType:ModifierType.DIRE_HIT.extra.raises") }); + return i18next.t("modifierType:ModifierType.TempStatStageBoosterModifierType.description", { + stat: i18next.t("modifierType:ModifierType.DIRE_HIT.extra.raises"), + amount: i18next.t("modifierType:ModifierType.TempStatStageBoosterModifierType.extra.stage") + }); } - }("modifierType:ModifierType.DIRE_HIT", "dire_hit", (type, _args) => new Modifiers.TempCritBoosterModifier(type)), + }("modifierType:ModifierType.DIRE_HIT", "dire_hit", (type, _args) => new Modifiers.TempCritBoosterModifier(type, 5)), BASE_STAT_BOOSTER: () => new BaseStatBoosterModifierTypeGenerator(), diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index f3219c8bf73..c1d58a7bf39 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -292,70 +292,131 @@ export class AddVoucherModifier extends ConsumableModifier { } } +/** + * Modifier used for party-wide or passive items that start an initial + * {@linkcode battleCount} equal to {@linkcode maxBattles} that, for every + * battle, decrements. Typically, when {@linkcode battleCount} reaches 0, the + * modifier will be removed. If a modifier of the same type is to be added, it + * will reset {@linkcode battleCount} back to {@linkcode maxBattles} of the + * existing modifier instead of adding that modifier directly. + * @extends PersistentModifier + * @abstract + * @see {@linkcode add} + */ export abstract class LapsingPersistentModifier extends PersistentModifier { - protected battlesLeft: integer; + /** The maximum amount of battles the modifier will exist for */ + private maxBattles: number; + /** The current amount of battles the modifier will exist for */ + private battleCount: number; - constructor(type: ModifierTypes.ModifierType, battlesLeft?: integer, stackCount?: integer) { + constructor(type: ModifierTypes.ModifierType, maxBattles: number, battleCount?: number, stackCount?: integer) { super(type, stackCount); - this.battlesLeft = battlesLeft!; // TODO: is this bang correct? + this.maxBattles = maxBattles; + this.battleCount = battleCount ?? this.maxBattles; } - lapse(args: any[]): boolean { - return !!--this.battlesLeft; + /** + * Goes through existing modifiers for any that match the selected modifier, + * which will then either add it to the existing modifiers if none were found + * or, if one was found, it will refresh {@linkcode battleCount}. + * @param modifiers {@linkcode PersistentModifier} array of the player's modifiers + * @param _virtual N/A + * @param _scene N/A + * @returns true if the modifier was successfully added or applied, false otherwise + */ + add(modifiers: PersistentModifier[], _virtual: boolean, scene: BattleScene): boolean { + for (const modifier of modifiers) { + if (this.match(modifier)) { + const modifierInstance = modifier as LapsingPersistentModifier; + if (modifierInstance.getBattleCount() < modifierInstance.getMaxBattles()) { + modifierInstance.resetBattleCount(); + scene.playSound("se/restore"); + return true; + } + // should never get here + return false; + } + } + + modifiers.push(this); + return true; + } + + lapse(_args: any[]): boolean { + this.battleCount--; + return this.battleCount > 0; } getIcon(scene: BattleScene): Phaser.GameObjects.Container { const container = super.getIcon(scene); - const battleCountText = addTextObject(scene, 27, 0, this.battlesLeft.toString(), TextStyle.PARTY, { fontSize: "66px", color: "#f89890" }); + // Linear interpolation on hue + const hue = Math.floor(120 * (this.battleCount / this.maxBattles) + 5); + + // Generates the color hex code with a constant saturation and lightness but varying hue + const typeHex = Utils.hslToHex(hue, 0.50, 0.90); + const strokeHex = Utils.hslToHex(hue, 0.70, 0.30); + + const battleCountText = addTextObject(scene, 27, 0, this.battleCount.toString(), TextStyle.PARTY, { fontSize: "66px", color: typeHex }); battleCountText.setShadow(0, 0); - battleCountText.setStroke("#984038", 16); + battleCountText.setStroke(strokeHex, 16); battleCountText.setOrigin(1, 0); container.add(battleCountText); return container; } - getBattlesLeft(): integer { - return this.battlesLeft; + getBattleCount(): number { + return this.battleCount; } - getMaxStackCount(scene: BattleScene, forThreshold?: boolean): number { - return 99; - } -} - -export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier { - constructor(type: ModifierTypes.DoubleBattleChanceBoosterModifierType, battlesLeft: integer, stackCount?: integer) { - super(type, battlesLeft, stackCount); + resetBattleCount(): void { + this.battleCount = this.maxBattles; } - match(modifier: Modifier): boolean { - if (modifier instanceof DoubleBattleChanceBoosterModifier) { - // Check type id to not match different tiers of lures - return modifier.type.id === this.type.id && modifier.battlesLeft === this.battlesLeft; - } - return false; - } - - clone(): DoubleBattleChanceBoosterModifier { - return new DoubleBattleChanceBoosterModifier(this.type as ModifierTypes.DoubleBattleChanceBoosterModifierType, this.battlesLeft, this.stackCount); + getMaxBattles(): number { + return this.maxBattles; } getArgs(): any[] { - return [ this.battlesLeft ]; + return [ this.maxBattles, this.battleCount ]; } + + getMaxStackCount(_scene: BattleScene, _forThreshold?: boolean): number { + return 1; + } +} + +/** + * Modifier used for passive items, specifically lures, that + * temporarily increases the chance of a double battle. + * @extends LapsingPersistentModifier + * @see {@linkcode apply} + */ +export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier { + constructor(type: ModifierType, maxBattles:number, battleCount?: number, stackCount?: integer) { + super(type, maxBattles, battleCount, stackCount); + } + + match(modifier: Modifier): boolean { + return (modifier instanceof DoubleBattleChanceBoosterModifier) && (modifier.getMaxBattles() === this.getMaxBattles()); + } + + clone(): DoubleBattleChanceBoosterModifier { + return new DoubleBattleChanceBoosterModifier(this.type as ModifierTypes.DoubleBattleChanceBoosterModifierType, this.getMaxBattles(), this.getBattleCount(), this.stackCount); + } + /** * Modifies the chance of a double battle occurring - * @param args A single element array containing the double battle chance as a NumberHolder - * @returns {boolean} Returns true if the modifier was applied + * @param args [0] {@linkcode Utils.NumberHolder} for double battle chance + * @returns true if the modifier was applied */ apply(args: any[]): boolean { const doubleBattleChance = args[0] as Utils.NumberHolder; // This is divided because the chance is generated as a number from 0 to doubleBattleChance.value using Utils.randSeedInt // A double battle will initiate if the generated number is 0 - doubleBattleChance.value = Math.ceil(doubleBattleChance.value / 2); + doubleBattleChance.value = Math.ceil(doubleBattleChance.value / 4); return true; } @@ -369,16 +430,18 @@ export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier * @see {@linkcode apply} */ export class TempStatStageBoosterModifier extends LapsingPersistentModifier { + /** The stat whose stat stage multiplier will be temporarily increased */ private stat: TempBattleStat; - private multiplierBoost: number; + /** The amount by which the stat stage itself or its multiplier will be increased by */ + private boost: number; - constructor(type: ModifierType, stat: TempBattleStat, battlesLeft?: number, stackCount?: number) { - super(type, battlesLeft ?? 5, stackCount); + constructor(type: ModifierType, stat: TempBattleStat, maxBattles: number, battleCount?: number, stackCount?: number) { + super(type, maxBattles, battleCount, stackCount); this.stat = stat; // Note that, because we want X Accuracy to maintain its original behavior, // it will increment as it did previously, directly to the stat stage. - this.multiplierBoost = stat !== Stat.ACC ? 0.3 : 1; + this.boost = (stat !== Stat.ACC) ? 0.3 : 1; } match(modifier: Modifier): boolean { @@ -390,11 +453,11 @@ export class TempStatStageBoosterModifier extends LapsingPersistentModifier { } clone() { - return new TempStatStageBoosterModifier(this.type, this.stat, this.battlesLeft, this.stackCount); + return new TempStatStageBoosterModifier(this.type, this.stat, this.getMaxBattles(), this.getBattleCount(), this.stackCount); } getArgs(): any[] { - return [ this.stat, this.battlesLeft ]; + return [ this.stat, ...super.getArgs() ]; } /** @@ -409,44 +472,14 @@ export class TempStatStageBoosterModifier extends LapsingPersistentModifier { } /** - * Increases the incoming stat stage matching {@linkcode stat} by {@linkcode multiplierBoost}. + * Increases the incoming stat stage matching {@linkcode stat} by {@linkcode boost}. * @param args [0] {@linkcode TempBattleStat} N/A * [1] {@linkcode Utils.NumberHolder} that holds the resulting value of the stat stage multiplier */ apply(args: any[]): boolean { - (args[1] as Utils.NumberHolder).value += this.multiplierBoost; + (args[1] as Utils.NumberHolder).value += this.boost; return true; } - - /** - * Goes through existing modifiers for any that match the selected modifier, - * which will then either add it to the existing modifiers if none were found - * or, if one was found, it will refresh {@linkcode battlesLeft}. - * @param modifiers {@linkcode PersistentModifier} array of the player's modifiers - * @param _virtual N/A - * @param _scene N/A - * @returns true if the modifier was successfully added or applied, false otherwise - */ - add(modifiers: PersistentModifier[], _virtual: boolean, _scene: BattleScene): boolean { - for (const modifier of modifiers) { - if (this.match(modifier)) { - const modifierInstance = modifier as TempStatStageBoosterModifier; - if (modifierInstance.getBattlesLeft() < 5) { - modifierInstance.battlesLeft = 5; - return true; - } - // should never get here - return false; - } - } - - modifiers.push(this); - return true; - } - - getMaxStackCount(_scene: BattleScene, _forThreshold?: boolean): number { - return 1; - } } /** @@ -456,12 +489,12 @@ export class TempStatStageBoosterModifier extends LapsingPersistentModifier { * @see {@linkcode apply} */ export class TempCritBoosterModifier extends LapsingPersistentModifier { - constructor(type: ModifierType, battlesLeft?: integer, stackCount?: number) { - super(type, battlesLeft || 5, stackCount); + constructor(type: ModifierType, maxBattles: number, battleCount?: number, stackCount?: number) { + super(type, maxBattles, battleCount, stackCount); } clone() { - return new TempCritBoosterModifier(this.type, this.stackCount); + return new TempCritBoosterModifier(this.type, this.getMaxBattles(), this.getBattleCount(), this.stackCount); } match(modifier: Modifier): boolean { @@ -486,36 +519,6 @@ export class TempCritBoosterModifier extends LapsingPersistentModifier { (args[0] as Utils.NumberHolder).value++; return true; } - - /** - * Goes through existing modifiers for any that match the selected modifier, - * which will then either add it to the existing modifiers if none were found - * or, if one was found, it will refresh {@linkcode battlesLeft}. - * @param modifiers {@linkcode PersistentModifier} array of the player's modifiers - * @param _virtual N/A - * @param _scene N/A - * @returns true if the modifier was successfully added or applied, false otherwise - */ - add(modifiers: PersistentModifier[], _virtual: boolean, _scene: BattleScene): boolean { - for (const modifier of modifiers) { - if (this.match(modifier)) { - const modifierInstance = modifier as TempCritBoosterModifier; - if (modifierInstance.getBattlesLeft() < 5) { - modifierInstance.battlesLeft = 5; - return true; - } - // should never get here - return false; - } - } - - modifiers.push(this); - return true; - } - - getMaxStackCount(_scene: BattleScene, _forThreshold?: boolean): number { - return 1; - } } export class MapModifier extends PersistentModifier { diff --git a/src/test/items/dire_hit.test.ts b/src/test/items/dire_hit.test.ts index 02f7c0d06a4..4b5988294f3 100644 --- a/src/test/items/dire_hit.test.ts +++ b/src/test/items/dire_hit.test.ts @@ -72,7 +72,7 @@ describe("Items - Dire Hit", () => { await game.phaseInterceptor.to(BattleEndPhase); const modifier = game.scene.findModifier(m => m instanceof TempCritBoosterModifier) as TempCritBoosterModifier; - expect(modifier.getBattlesLeft()).toBe(4); + expect(modifier.getBattleCount()).toBe(4); // Forced DIRE_HIT to spawn in the first slot with override game.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => { @@ -90,7 +90,7 @@ describe("Items - Dire Hit", () => { for (const m of game.scene.modifiers) { if (m instanceof TempCritBoosterModifier) { count++; - expect((m as TempCritBoosterModifier).getBattlesLeft()).toBe(5); + expect((m as TempCritBoosterModifier).getBattleCount()).toBe(5); } } expect(count).toBe(1); diff --git a/src/test/items/double_battle_chance_booster.test.ts b/src/test/items/double_battle_chance_booster.test.ts new file mode 100644 index 00000000000..808d4c7ca51 --- /dev/null +++ b/src/test/items/double_battle_chance_booster.test.ts @@ -0,0 +1,105 @@ +import { Moves } from "#app/enums/moves.js"; +import { Species } from "#app/enums/species.js"; +import { DoubleBattleChanceBoosterModifier } from "#app/modifier/modifier"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "../utils/testUtils"; +import { ShopCursorTarget } from "#app/enums/shop-cursor-target.js"; +import { Mode } from "#app/ui/ui.js"; +import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler.js"; +import { Button } from "#app/enums/buttons.js"; + +describe("Items - Double Battle Chance Boosters", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + const TIMEOUT = 20 * 1000; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + }); + + it("should guarantee double battle with 2 unique tiers", async () => { + game.override + .startingModifier([ + { name: "LURE" }, + { name: "SUPER_LURE" } + ]) + .startingWave(2); + + await game.classicMode.startBattle(); + + expect(game.scene.getEnemyField().length).toBe(2); + }, TIMEOUT); + + it("should guarantee double boss battle with 3 unique tiers", async () => { + game.override + .startingModifier([ + { name: "LURE" }, + { name: "SUPER_LURE" }, + { name: "MAX_LURE" } + ]) + .startingWave(10); + + await game.classicMode.startBattle(); + + const enemyField = game.scene.getEnemyField(); + + expect(enemyField.length).toBe(2); + expect(enemyField[0].isBoss()).toBe(true); + expect(enemyField[1].isBoss()).toBe(true); + }, TIMEOUT); + + it("should renew how many battles are left of existing booster when picking up new booster of same tier", async() => { + game.override + .startingModifier([{ name: "LURE" }]) + .itemRewards([{ name: "LURE" }]) + .moveset(SPLASH_ONLY) + .startingLevel(200); + + await game.classicMode.startBattle([ + Species.PIKACHU + ]); + + game.move.select(Moves.SPLASH); + + await game.doKillOpponents(); + + await game.phaseInterceptor.to("BattleEndPhase"); + + const modifier = game.scene.findModifier(m => m instanceof DoubleBattleChanceBoosterModifier) as DoubleBattleChanceBoosterModifier; + expect(modifier.getBattleCount()).toBe(9); + + // Forced LURE to spawn in the first slot with override + game.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => { + const handler = game.scene.ui.getHandler() as ModifierSelectUiHandler; + // Traverse to first modifier slot + handler.setCursor(0); + handler.setRowCursor(ShopCursorTarget.REWARDS); + handler.processInput(Button.ACTION); + }, () => game.isCurrentPhase("CommandPhase") || game.isCurrentPhase("NewBattlePhase"), true); + + await game.phaseInterceptor.to("TurnInitPhase"); + + // Making sure only one booster is in the modifier list even after picking up another + let count = 0; + for (const m of game.scene.modifiers) { + if (m instanceof DoubleBattleChanceBoosterModifier) { + count++; + const modifierInstance = m as DoubleBattleChanceBoosterModifier; + expect(modifierInstance.getBattleCount()).toBe(modifierInstance.getMaxBattles()); + } + } + expect(count).toBe(1); + }, TIMEOUT); +}); diff --git a/src/test/items/temp_stat_stage_booster.test.ts b/src/test/items/temp_stat_stage_booster.test.ts index c81703220db..3e32fa13a04 100644 --- a/src/test/items/temp_stat_stage_booster.test.ts +++ b/src/test/items/temp_stat_stage_booster.test.ts @@ -10,12 +10,7 @@ import { Abilities } from "#app/enums/abilities"; import { TempStatStageBoosterModifier } from "#app/modifier/modifier"; import { Mode } from "#app/ui/ui"; import { Button } from "#app/enums/buttons"; -import { CommandPhase } from "#app/phases/command-phase"; -import { NewBattlePhase } from "#app/phases/new-battle-phase"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; -import { TurnInitPhase } from "#app/phases/turn-init-phase"; -import { BattleEndPhase } from "#app/phases/battle-end-phase"; -import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; import { ShopCursorTarget } from "#app/enums/shop-cursor-target"; @@ -46,7 +41,7 @@ describe("Items - Temporary Stat Stage Boosters", () => { }); it("should provide a x1.3 stat stage multiplier", async() => { - await game.startBattle([ + await game.classicMode.startBattle([ Species.PIKACHU ]); @@ -56,7 +51,7 @@ describe("Items - Temporary Stat Stage Boosters", () => { game.move.select(Moves.TACKLE); - await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnEndPhase); + await game.phaseInterceptor.runFrom("EnemyCommandPhase").to(TurnEndPhase); expect(partyMember.getStatStageMultiplier).toHaveReturnedWith(1.3); }, 20000); @@ -66,7 +61,7 @@ describe("Items - Temporary Stat Stage Boosters", () => { .startingModifier([{ name: "TEMP_STAT_STAGE_BOOSTER", type: Stat.ACC }]) .ability(Abilities.SIMPLE); - await game.startBattle([ + await game.classicMode.startBattle([ Species.PIKACHU ]); @@ -89,7 +84,7 @@ describe("Items - Temporary Stat Stage Boosters", () => { it("should increase existing stat stage multiplier by 3/10 for the rest of the boosters", async() => { - await game.startBattle([ + await game.classicMode.startBattle([ Species.PIKACHU ]); @@ -113,7 +108,7 @@ describe("Items - Temporary Stat Stage Boosters", () => { it("should not increase past maximum stat stage multiplier", async() => { game.override.startingModifier([{ name: "TEMP_STAT_STAGE_BOOSTER", type: Stat.ACC }, { name: "TEMP_STAT_STAGE_BOOSTER", type: Stat.ATK }]); - await game.startBattle([ + await game.classicMode.startBattle([ Species.PIKACHU ]); @@ -138,7 +133,7 @@ describe("Items - Temporary Stat Stage Boosters", () => { .startingLevel(200) .itemRewards([{ name: "TEMP_STAT_STAGE_BOOSTER", type: Stat.ATK }]); - await game.startBattle([ + await game.classicMode.startBattle([ Species.PIKACHU ]); @@ -146,10 +141,10 @@ describe("Items - Temporary Stat Stage Boosters", () => { await game.doKillOpponents(); - await game.phaseInterceptor.to(BattleEndPhase); + await game.phaseInterceptor.to("BattleEndPhase"); const modifier = game.scene.findModifier(m => m instanceof TempStatStageBoosterModifier) as TempStatStageBoosterModifier; - expect(modifier.getBattlesLeft()).toBe(4); + expect(modifier.getBattleCount()).toBe(4); // Forced X_ATTACK to spawn in the first slot with override game.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => { @@ -158,16 +153,17 @@ describe("Items - Temporary Stat Stage Boosters", () => { handler.setCursor(0); handler.setRowCursor(ShopCursorTarget.REWARDS); handler.processInput(Button.ACTION); - }, () => game.isCurrentPhase(CommandPhase) || game.isCurrentPhase(NewBattlePhase), true); + }, () => game.isCurrentPhase("CommandPhase") || game.isCurrentPhase("NewBattlePhase"), true); - await game.phaseInterceptor.to(TurnInitPhase); + await game.phaseInterceptor.to("TurnInitPhase"); // Making sure only one booster is in the modifier list even after picking up another let count = 0; for (const m of game.scene.modifiers) { if (m instanceof TempStatStageBoosterModifier) { count++; - expect((m as TempStatStageBoosterModifier).getBattlesLeft()).toBe(5); + const modifierInstance = m as TempStatStageBoosterModifier; + expect(modifierInstance.getBattleCount()).toBe(modifierInstance.getMaxBattles()); } } expect(count).toBe(1); diff --git a/src/utils.ts b/src/utils.ts index fd5430d7276..592981c7643 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -455,6 +455,26 @@ export function rgbaToInt(rgba: integer[]): integer { return (rgba[0] << 24) + (rgba[1] << 16) + (rgba[2] << 8) + rgba[3]; } +/** + * Provided valid HSV values, calculates and stitches together a string of that + * HSV color's corresponding hex code. + * + * Sourced from {@link https://stackoverflow.com/a/44134328}. + * @param h Hue in degrees, must be in a range of [0, 360] + * @param s Saturation percentage, must be in a range of [0, 1] + * @param l Ligthness percentage, must be in a range of [0, 1] + * @returns a string of the corresponding color hex code with a "#" prefix + */ +export function hslToHex(h: number, s: number, l: number): string { + const a = s * Math.min(l, 1 - l); + const f = (n: number) => { + const k = (n + h / 30) % 12; + const rgb = l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1)); + return Math.round(rgb * 255).toString(16).padStart(2, "0"); + }; + return `#${f(0)}${f(8)}${f(4)}`; +} + /*This function returns true if the current lang is available for some functions If the lang is not in the function, it usually means that lang is going to use the default english version This function is used in: From dfa399386460d2657695e76faf13d52a33a93c62 Mon Sep 17 00:00:00 2001 From: James Diefenbach <105332964+j-diefenbach@users.noreply.github.com> Date: Sun, 8 Sep 2024 09:32:49 +1000 Subject: [PATCH 14/22] Egg summary background touchup (#4091) * darker egg-summary background * reset old background for beta * update egg summary bg * reset overrides --------- Co-authored-by: James Diefenbach --- public/images/ui/egg_summary_bg.png | Bin 2209 -> 2247 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/public/images/ui/egg_summary_bg.png b/public/images/ui/egg_summary_bg.png index b4ee3d86a507bfb99b4f9af2d71b5065e4ac943b..e81934b9d75b3acbed35b113f803dfa119a78631 100644 GIT binary patch literal 2247 zcmeH}{a;dd8^@2xRGMkvYeuEyW6ssYRV$W{iB6ruc?k;777XhDvtLxCg(9dFEvZxN%}<6DSC;`;R8hVF<&pLM2`nb!n|hMu|jFgY++ zF@1B7BJ3@irr`ENBMJ_Wj*gxTQ*fDsTy&plfyON~EL6~*jQ(+c(eVB2Dz3?7Dwpi! ztGvCIv|4`qx>lAzTaDh|TjIB;F_+5q8fQiJW#4W}pMur4hlrCB?UQ2pa;wEdMTu-rw>!2(k`mYcE#m;Q^# z!R~haj4N|s)K)z&;kLHR8GmTVZYUH-Q1-2plhY#=tzcq#s|UZXJ$*nXlX0Vqs&9TH zU!;s4zmi3To&3r8WYP4Ne()M+K5g#P0@L;J@l?m5++FiaNCau?ImczRclRF7x8m8l z>gwwH_csxUL|122a3(dr;ojlb#IxIL2mf_@T0=4$$?tEfR>Eb}2czz%?CtFzvuGy6 zQB_h?oKz)nsw9Fbme2MXyXH{0BphmwJHemMXbbkj(GKRaw8yWUy?WOh7OW0AKg7c( zLa^=#OsQfk$w7~ojOU+%CUnvZW2Dd?%Bm)4@vgSsHD3qc!slwS92UZ>N) z_R0C;P5Q+E*o71YrDJ}sCngVg58t#2b^#xUzZ?hgyT5B=R*)fJuX_;!c{vv1H-&6UFaBoNJ(s zQKz8AxHcbkUOKt{z~KgGP6KtV1P<5egSS=+!{gIb5BLT|r#>6Ws44`-LP@Te&iha6 z=p+D6p4zz|Hq0=f2_3$HBffN(BP#+3OuyZ-C*36r=9m{Ny@s1UnSJQtX)x+(-Dwc) zKE&TD)~Ke9;0v|F#5!ogk9nbE#HD>;cm6N?KWM^72wlrU@dBevmR5)(I?J;qg2^+L zLjN6iD+1_DkdgjxSfCA^lM&tZqUqx#X>q01A<@@{&?nD{rgxe~%3YaJk&fOQRARej zf-hZli+wXso3%sXgayxjqF$Kq%Tn-^UrE<2SRGiR@=@=*J$>SxPYw*?XOb78`~4Wl z`r3m4&_2V|0Cj)=Zp9JVo;RFj4D~xToCX5u#q_YFTsGUqQLNXKwVtmuHMY*?E?;sh z67RGyOG?-+mP|_Ok7;3`#6$y{QS*$KF$@s0V0-w$1X>cVQ&Y?IZHkzlj`p7eW(st1opF4XfoH z2vF(;fx6F&gqh@(R9+ywHo~?U#QYzTG0*pWK7U??IhNHz6T<%qI(--%NGr9AGT6m+ zSG5$Q`oI)%Wx!Pmg_(MR5T+A=X&ibnN|4AmMG!w}>dRBl=fB(k3wOYcw=$N7ebv)U z=9px%oIg3K^niAYc+fK?)^$nAl=#C6hjW{&&EGDJ(Ol_pX9C1VB}BGG;J^3_=!8=B literal 2209 zcmeHJdsLEV9R5VSkQ8Pv%jHbd%;kmVQp*BU4DCW4b7h*ru=JEBT3VVYQkk?;OgqsE zrQ0bTLo{zF1YdcZV`-fdFsH03OEb|lykNqrK|eYGD^H;ZQHf65;B8 zXB(?7pFHn@d*8aYzMLLz`-^o-w%nqz9mg-e_Mjy#wz;q87M_VQ0pUl2aBMcaN}NY| zu2fPo5V!JQh)-3le%X3|imEFetXFh)9-@ZS3Izg26M4;4;7DJeQ*$Qqfr7_znUK>+ z!yS~0iC47@hA#%AmhhAwWj$i;I9K1T9pWnWPl(q%Wy9Q?BISYw3%nDQ<61Ds^%1E-LSea)-zIS_?CY_w{*9rcY0e?%4N- zy%&HJOj;gvsVUgB(Z1&^Dm7U29*WH#RHcU4+gTZ#M5T(7K%O3>nm#eylOfkX4%>I1 zFXKrl{2rRh(oL*kE&BanDaKTh5;eH>&`%;%Gu1#Pa*(o2*hGG!wc6~^kYN&C8}5d& z&!Y5*4rRD2t7>a)_(VxU#?tL}c6Lol{dkGyp#RBsqL?A)6KQF1-)oN|_P6hGXGvu& z^w&})R)US8{n%MEV<%KZNRl!$zl!$av`=r$h8I7Ixuuhus|(V{rrtfBo*0hyzScA~ zm9`;uPVMPY?tIrZz7T z9Y(9@^s7#Zr`+i`JP_>gL2CKXYoXvcP_~=PrP$6#AfHuT1f!klLPkEgQ(6rd4|t)x z2!?F(YDY4K;`vQJ=)ZlUN1QS3N*N4+fy^ghp~CZ# z5a~~_T0oSH8}dJc8URIs=+BWtQ3j3vpZ0Sj{P)`SFG{W3*G#TpFy7qe*gb(fy#(@f zZv-s8aSg$z+jG`6E9k%torZr(e7#56S*hJOEq*cj7r99*^ho zv$3Tq7{&4NsQ4f%L0ME(L}Gh*cxYWpvQDZWy&T)20@xBQ5r<=Ab@*N>xmydl`9({b zL-MS>A?LmQ1$Ct$7aqfQLO*k+FN!Nd)f8peOc;}HIwitB=@1GW2poq|avgUxVVYTD9;FVM^C zWK*QB&J#~uMp~p&g|a($rn_6W94?S*;dzYrV+Nz}=`JP=kAnq9$*of3()|d89n+6e zXS+0)X|#Sa%k_=h2W+DO{j=4AXu$C(n+s2KDl26y;6x|~q|FT6mB}BvW7tI@q>|u| z?f)*4M7n37R(}~(?JD!iG{_zRGcHtRKSrcFeEUqbcaBEWW*AK*dRtna)jBdzZUyx? z3r_giAo?UV3p|jv*w+YwObMAw$hHYEE`)^qBr^D8&5sL?1p>M4GMwNK@wD=-Fv#NY zk7Ng$7ydGAMn>m0{GM7YLBQ%Db!Y)2(?du5rcu1YduCAn`C!bTAxgQAIElf&I zu9{loZ)T5nE;jjq{rv`V`n0j8>VTj1&>w&0mNev`2f4V^iFkRSrCEP! Date: Sun, 8 Sep 2024 11:33:33 +1000 Subject: [PATCH 15/22] Fixed small RNG misusage (#4092) --- src/phases/attempt-run-phase.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/phases/attempt-run-phase.ts b/src/phases/attempt-run-phase.ts index 9cf86fed592..46d68f6005a 100644 --- a/src/phases/attempt-run-phase.ts +++ b/src/phases/attempt-run-phase.ts @@ -28,7 +28,7 @@ export class AttemptRunPhase extends PokemonPhase { applyAbAttrs(RunSuccessAbAttr, playerPokemon, null, false, escapeChance); - if (Utils.randSeedInt(100) < escapeChance.value) { + if (playerPokemon.randSeedInt(100) < escapeChance.value) { this.scene.playSound("se/flee"); this.scene.queueMessage(i18next.t("battle:runAwaySuccess"), null, true, 500); From ffcedfd9a4b9f35ad61c035ebe22a494ecf45500 Mon Sep 17 00:00:00 2001 From: "Amani H." <109637146+xsn34kzx@users.noreply.github.com> Date: Sat, 7 Sep 2024 21:40:45 -0400 Subject: [PATCH 16/22] [Dev] Save Data Version Migration (#4080) * Initial Draft * Successfuly Migration with Vitamins and White Herb * Apply Session Data Patches Earlier * Remove Stray `console.log` --- src/system/game-data.ts | 138 ++++++-------------------------- src/system/modifier-data.ts | 10 +-- src/system/version-converter.ts | 137 +++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 120 deletions(-) create mode 100644 src/system/version-converter.ts diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 746af4d47a5..800b8baecff 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -1,7 +1,7 @@ import i18next from "i18next"; import BattleScene, { PokeballCounts, bypassLogin } from "../battle-scene"; import Pokemon, { EnemyPokemon, PlayerPokemon } from "../field/pokemon"; -import { pokemonEvolutions, pokemonPrevolutions } from "../data/pokemon-evolutions"; +import { pokemonPrevolutions } from "../data/pokemon-evolutions"; import PokemonSpecies, { allSpecies, getPokemonSpecies, noStarterFormKeys, speciesStarters } from "../data/pokemon-species"; import * as Utils from "../utils"; import Overrides from "#app/overrides"; @@ -27,7 +27,7 @@ import { Tutorial } from "../tutorial"; import { speciesEggMoves } from "../data/egg-moves"; import { allMoves } from "../data/move"; import { TrainerVariant } from "../field/trainer"; -import { Variant, variantData } from "#app/data/variant"; +import { Variant } from "#app/data/variant"; import {setSettingGamepad, SettingGamepad, settingGamepadDefaults} from "./settings/settings-gamepad"; import {setSettingKeyboard, SettingKeyboard} from "#app/system/settings/settings-keyboard"; import { TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena.js"; @@ -45,6 +45,7 @@ import { TerrainType } from "#app/data/terrain.js"; import { OutdatedPhase } from "#app/phases/outdated-phase.js"; import { ReloadSessionPhase } from "#app/phases/reload-session-phase.js"; import { RUN_HISTORY_LIMIT } from "#app/ui/run-history-ui-handler"; +import { applySessionDataPatches, applySettingsDataPatches, applySystemDataPatches } from "./version-converter"; export const defaultStarterSpecies: Species[] = [ Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, @@ -93,7 +94,7 @@ export function decrypt(data: string, bypassLogin: boolean): string { : (data: string) => AES.decrypt(data, saveKey).toString(enc.Utf8))(data); } -interface SystemSaveData { +export interface SystemSaveData { trainerId: integer; secretId: integer; gender: PlayerGender; @@ -456,17 +457,14 @@ export class GameData { localStorage.setItem(`data_${loggedInUser?.username}`, encrypt(systemDataStr, bypassLogin)); - /*const versions = [ this.scene.game.config.gameVersion, data.gameVersion || '0.0.0' ]; - - if (versions[0] !== versions[1]) { - const [ versionNumbers, oldVersionNumbers ] = versions.map(ver => ver.split('.').map(v => parseInt(v))); - }*/ const lsItemKey = `runHistoryData_${loggedInUser?.username}`; const lsItem = localStorage.getItem(lsItemKey); if (!lsItem) { localStorage.setItem(lsItemKey, ""); } + applySystemDataPatches(systemData); + this.trainerId = systemData.trainerId; this.secretId = systemData.secretId; @@ -474,9 +472,7 @@ export class GameData { this.saveSetting(SettingKeys.Player_Gender, systemData.gender === PlayerGender.FEMALE ? 1 : 0); - const initStarterData = !systemData.starterData; - - if (initStarterData) { + if (!systemData.starterData) { this.initStarterData(); if (systemData["starterMoveData"]) { @@ -494,25 +490,20 @@ export class GameData { } this.migrateStarterAbilities(systemData, this.starterData); - } else { - if ([ "1.0.0", "1.0.1" ].includes(systemData.gameVersion)) { - this.migrateStarterAbilities(systemData); - } - //this.fixVariantData(systemData); - this.fixStarterData(systemData); - // Migrate ability starter data if empty for caught species - Object.keys(systemData.starterData).forEach(sd => { - if (systemData.dexData[sd].caughtAttr && !systemData.starterData[sd].abilityAttr) { - systemData.starterData[sd].abilityAttr = 1; + + const starterIds = Object.keys(this.starterData).map(s => parseInt(s) as Species); + for (const s of starterIds) { + this.starterData[s].candyCount += this.dexData[s].caughtCount; + this.starterData[s].candyCount += this.dexData[s].hatchedCount * 2; + if (this.dexData[s].caughtAttr & DexAttr.SHINY) { + this.starterData[s].candyCount += 4; } - }); + } + } else { this.starterData = systemData.starterData; } if (systemData.gameStats) { - if (systemData.gameStats.legendaryPokemonCaught !== undefined && systemData.gameStats.subLegendaryPokemonCaught === undefined) { - this.fixLegendaryStats(systemData); - } this.gameStats = systemData.gameStats; } @@ -558,17 +549,6 @@ export class GameData { this.consolidateDexData(this.dexData); this.defaultDexData = null; - if (initStarterData) { - const starterIds = Object.keys(this.starterData).map(s => parseInt(s) as Species); - for (const s of starterIds) { - this.starterData[s].candyCount += this.dexData[s].caughtCount; - this.starterData[s].candyCount += this.dexData[s].hatchedCount * 2; - if (this.dexData[s].caughtAttr & DexAttr.SHINY) { - this.starterData[s].candyCount += 4; - } - } - } - resolve(true); } catch (err) { console.error(err); @@ -747,6 +727,7 @@ export class GameData { setSetting(this.scene, setting, valueIndex); settings[setting] = valueIndex; + settings["gameVersion"] = this.scene.game.config.gameVersion; localStorage.setItem("settings", JSON.stringify(settings)); @@ -857,13 +838,7 @@ export class GameData { const settings = JSON.parse(localStorage.getItem("settings")!); // TODO: is this bang correct? - // TODO: Remove this block after save migration is implemented - if (settings.hasOwnProperty("REROLL_TARGET") && !settings.hasOwnProperty(SettingKeys.Shop_Cursor_Target)) { - settings[SettingKeys.Shop_Cursor_Target] = settings["REROLL_TARGET"]; - delete settings["REROLL_TARGET"]; - localStorage.setItem("settings", JSON.stringify(settings)); - } - // End of block to remove + applySettingsDataPatches(settings); for (const setting of Object.keys(settings)) { setSetting(this.scene, setting, settings[setting]); @@ -1226,7 +1201,7 @@ export class GameData { } parseSessionData(dataStr: string): SessionSaveData { - return JSON.parse(dataStr, (k: string, v: any) => { + const sessionData = JSON.parse(dataStr, (k: string, v: any) => { /*const versions = [ scene.game.config.gameVersion, sessionData.gameVersion || '0.0.0' ]; if (versions[0] !== versions[1]) { @@ -1283,6 +1258,10 @@ export class GameData { return v; }) as SessionSaveData; + + applySessionDataPatches(sessionData); + + return sessionData; } saveAll(scene: BattleScene, skipVerification: boolean = false, sync: boolean = false, useCachedSession: boolean = false, useCachedSystem: boolean = false): Promise { @@ -1885,75 +1864,4 @@ export class GameData { } } } - - fixVariantData(systemData: SystemSaveData): void { - const starterIds = Object.keys(this.starterData).map(s => parseInt(s) as Species); - const starterData = systemData.starterData; - const dexData = systemData.dexData; - if (starterIds.find(id => (dexData[id].caughtAttr & DexAttr.VARIANT_2 || dexData[id].caughtAttr & DexAttr.VARIANT_3) && !variantData[id])) { - for (const s of starterIds) { - const species = getPokemonSpecies(s); - if (variantData[s]) { - const tempCaughtAttr = dexData[s].caughtAttr; - let seenVariant2 = false; - let seenVariant3 = false; - const checkEvoSpecies = (es: Species) => { - seenVariant2 ||= !!(dexData[es].seenAttr & DexAttr.VARIANT_2); - seenVariant3 ||= !!(dexData[es].seenAttr & DexAttr.VARIANT_3); - if (pokemonEvolutions.hasOwnProperty(es)) { - for (const pe of pokemonEvolutions[es]) { - checkEvoSpecies(pe.speciesId); - } - } - }; - checkEvoSpecies(s); - if (dexData[s].caughtAttr & DexAttr.VARIANT_2 && !seenVariant2) { - dexData[s].caughtAttr ^= DexAttr.VARIANT_2; - } - if (dexData[s].caughtAttr & DexAttr.VARIANT_3 && !seenVariant3) { - dexData[s].caughtAttr ^= DexAttr.VARIANT_3; - } - starterData[s].abilityAttr = (tempCaughtAttr & DexAttr.DEFAULT_VARIANT ? AbilityAttr.ABILITY_1 : 0) - | (tempCaughtAttr & DexAttr.VARIANT_2 && species.ability2 ? AbilityAttr.ABILITY_2 : 0) - | (tempCaughtAttr & DexAttr.VARIANT_3 && species.abilityHidden ? AbilityAttr.ABILITY_HIDDEN : 0); - } else { - const tempCaughtAttr = dexData[s].caughtAttr; - if (dexData[s].caughtAttr & DexAttr.VARIANT_2) { - dexData[s].caughtAttr ^= DexAttr.VARIANT_2; - } - if (dexData[s].caughtAttr & DexAttr.VARIANT_3) { - dexData[s].caughtAttr ^= DexAttr.VARIANT_3; - } - starterData[s].abilityAttr = (tempCaughtAttr & DexAttr.DEFAULT_VARIANT ? AbilityAttr.ABILITY_1 : 0) - | (tempCaughtAttr & DexAttr.VARIANT_2 && species.ability2 ? AbilityAttr.ABILITY_2 : 0) - | (tempCaughtAttr & DexAttr.VARIANT_3 && species.abilityHidden ? AbilityAttr.ABILITY_HIDDEN : 0); - } - } - } - } - - fixStarterData(systemData: SystemSaveData): void { - for (const starterId of defaultStarterSpecies) { - systemData.starterData[starterId].abilityAttr |= AbilityAttr.ABILITY_1; - systemData.dexData[starterId].caughtAttr |= DexAttr.FEMALE; - } - } - - fixLegendaryStats(systemData: SystemSaveData): void { - systemData.gameStats.subLegendaryPokemonSeen = 0; - systemData.gameStats.subLegendaryPokemonCaught = 0; - systemData.gameStats.subLegendaryPokemonHatched = 0; - allSpecies.filter(s => s.subLegendary).forEach(s => { - const dexEntry = systemData.dexData[s.speciesId]; - systemData.gameStats.subLegendaryPokemonSeen += dexEntry.seenCount; - systemData.gameStats.legendaryPokemonSeen = Math.max(systemData.gameStats.legendaryPokemonSeen - dexEntry.seenCount, 0); - systemData.gameStats.subLegendaryPokemonCaught += dexEntry.caughtCount; - systemData.gameStats.legendaryPokemonCaught = Math.max(systemData.gameStats.legendaryPokemonCaught - dexEntry.caughtCount, 0); - systemData.gameStats.subLegendaryPokemonHatched += dexEntry.hatchedCount; - systemData.gameStats.legendaryPokemonHatched = Math.max(systemData.gameStats.legendaryPokemonHatched - dexEntry.hatchedCount, 0); - }); - systemData.gameStats.subLegendaryPokemonSeen = Math.max(systemData.gameStats.subLegendaryPokemonSeen, systemData.gameStats.subLegendaryPokemonCaught); - systemData.gameStats.legendaryPokemonSeen = Math.max(systemData.gameStats.legendaryPokemonSeen, systemData.gameStats.legendaryPokemonCaught); - systemData.gameStats.mythicalPokemonSeen = Math.max(systemData.gameStats.mythicalPokemonSeen, systemData.gameStats.mythicalPokemonCaught); - } } diff --git a/src/system/modifier-data.ts b/src/system/modifier-data.ts index 0f3e28fe11c..1514f7e3fb3 100644 --- a/src/system/modifier-data.ts +++ b/src/system/modifier-data.ts @@ -3,11 +3,11 @@ import { PersistentModifier } from "../modifier/modifier"; import { GeneratedPersistentModifierType, ModifierType, ModifierTypeGenerator, getModifierTypeFuncById } from "../modifier/modifier-type"; export default class ModifierData { - private player: boolean; - private typeId: string; - private typePregenArgs: any[]; - private args: any[]; - private stackCount: integer; + public player: boolean; + public typeId: string; + public typePregenArgs: any[]; + public args: any[]; + public stackCount: integer; public className: string; diff --git a/src/system/version-converter.ts b/src/system/version-converter.ts new file mode 100644 index 00000000000..ed65fcd99b8 --- /dev/null +++ b/src/system/version-converter.ts @@ -0,0 +1,137 @@ +import { allSpecies } from "#app/data/pokemon-species.js"; +import { AbilityAttr, defaultStarterSpecies, DexAttr, SessionSaveData, SystemSaveData } from "./game-data"; +import { SettingKeys } from "./settings/settings"; + +const LATEST_VERSION = "1.0.5"; + +export function applySessionDataPatches(data: SessionSaveData) { + const curVersion = data.gameVersion; + if (curVersion !== LATEST_VERSION) { + switch (curVersion) { + case "1.0.0": + case "1.0.1": + case "1.0.2": + case "1.0.3": + case "1.0.4": + // --- PATCHES --- + + // Fix Battle Items, Vitamins, and Lures + data.modifiers.forEach((m) => { + if (m.className === "PokemonBaseStatModifier") { + m.className = "BaseStatModifier"; + } else if (m.className === "PokemonResetNegativeStatStageModifier") { + m.className = "ResetNegativeStatStageModifier"; + } else if (m.className === "TempBattleStatBoosterModifier") { + m.className = "TempStatStageBoosterModifier"; + m.typeId = "TEMP_STAT_STAGE_BOOSTER"; + + // Migration from TempBattleStat to Stat + const newStat = m.typePregenArgs[0] + 1; + m.typePregenArgs[0] = newStat; + + // From [ stat, battlesLeft ] to [ stat, maxBattles, battleCount ] + m.args = [ newStat, 5, m.args[1] ]; + } else if (m.className === "DoubleBattleChanceBoosterModifier") { + let maxBattles: number; + switch (m.typeId) { + case "MAX_LURE": + maxBattles = 30; + break; + case "SUPER_LURE": + maxBattles = 15; + break; + default: + maxBattles = 10; + break; + } + + // From [ battlesLeft ] to [ maxBattles, battleCount ] + m.args = [ maxBattles, m.args[0] ]; + } + }); + + data.enemyModifiers.forEach((m) => { + if (m.className === "PokemonBaseStatModifier") { + m.className = "BaseStatModifier"; + } + }); + } + + data.gameVersion = LATEST_VERSION; + } +} + +export function applySystemDataPatches(data: SystemSaveData) { + const curVersion = data.gameVersion; + if (curVersion !== LATEST_VERSION) { + switch (curVersion) { + case "1.0.0": + case "1.0.1": + case "1.0.2": + case "1.0.3": + case "1.0.4": + // --- LEGACY PATCHES --- + if (data.starterData) { + // Migrate ability starter data if empty for caught species + Object.keys(data.starterData).forEach(sd => { + if (data.dexData[sd].caughtAttr && !data.starterData[sd].abilityAttr) { + data.starterData[sd].abilityAttr = 1; + } + }); + } + + // Fix Legendary Stats + if (data.gameStats && (data.gameStats.legendaryPokemonCaught !== undefined && data.gameStats.subLegendaryPokemonCaught === undefined)) { + data.gameStats.subLegendaryPokemonSeen = 0; + data.gameStats.subLegendaryPokemonCaught = 0; + data.gameStats.subLegendaryPokemonHatched = 0; + allSpecies.filter(s => s.subLegendary).forEach(s => { + const dexEntry = data.dexData[s.speciesId]; + data.gameStats.subLegendaryPokemonSeen += dexEntry.seenCount; + data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen - dexEntry.seenCount, 0); + data.gameStats.subLegendaryPokemonCaught += dexEntry.caughtCount; + data.gameStats.legendaryPokemonCaught = Math.max(data.gameStats.legendaryPokemonCaught - dexEntry.caughtCount, 0); + data.gameStats.subLegendaryPokemonHatched += dexEntry.hatchedCount; + data.gameStats.legendaryPokemonHatched = Math.max(data.gameStats.legendaryPokemonHatched - dexEntry.hatchedCount, 0); + }); + data.gameStats.subLegendaryPokemonSeen = Math.max(data.gameStats.subLegendaryPokemonSeen, data.gameStats.subLegendaryPokemonCaught); + data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen, data.gameStats.legendaryPokemonCaught); + data.gameStats.mythicalPokemonSeen = Math.max(data.gameStats.mythicalPokemonSeen, data.gameStats.mythicalPokemonCaught); + } + + // --- PATCHES --- + + // Fix Starter Data + if (data.gameVersion) { + for (const starterId of defaultStarterSpecies) { + data.starterData[starterId].abilityAttr |= AbilityAttr.ABILITY_1; + data.dexData[starterId].caughtAttr |= DexAttr.FEMALE; + } + } + } + + data.gameVersion = LATEST_VERSION; + } +} + +export function applySettingsDataPatches(settings: Object) { + const curVersion = settings.hasOwnProperty("gameVersion") ? settings["gameVersion"] : "1.0.0"; + if (curVersion !== LATEST_VERSION) { + switch (curVersion) { + case "1.0.0": + case "1.0.1": + case "1.0.2": + case "1.0.3": + case "1.0.4": + // --- PATCHES --- + + // Fix Reward Cursor Target + if (settings.hasOwnProperty("REROLL_TARGET") && !settings.hasOwnProperty(SettingKeys.Shop_Cursor_Target)) { + settings[SettingKeys.Shop_Cursor_Target] = settings["REROLL_TARGET"]; + delete settings["REROLL_TARGET"]; + localStorage.setItem("settings", JSON.stringify(settings)); + } + } + // Note that the current game version will be written at `saveSettings` + } +} From f73a830f7749b8289edc282e55dccd5305c772c8 Mon Sep 17 00:00:00 2001 From: DustinLin <39450497+DustinLin@users.noreply.github.com> Date: Sat, 7 Sep 2024 21:36:47 -0700 Subject: [PATCH 17/22] [DOCS] adding JSDocs to `arena.ts` (#3590) * adding some docs * Update src/field/pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * seems like battleStats changed to statStages * Apply suggestions from code review editing doc text Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Update tsdocs, convert comment to tsdoc in `pokemon.ts` --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> --- src/field/arena.ts | 58 ++++++++++++++++++++++++++++++++++++++++---- src/field/pokemon.ts | 1 + 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/field/arena.ts b/src/field/arena.ts index e8defbd1a8e..5b167791769 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -60,7 +60,7 @@ export class Arena { this.scene.arenaBg.setTexture(`${biomeKey}_bg`); this.scene.arenaBgTransition.setTexture(`${biomeKey}_bg`); - // Redo this on initialise because during save/load the current wave isn't always + // Redo this on initialize because during save/load the current wave isn't always // set correctly during construction this.updatePoolsForTimeOfDay(); } @@ -289,7 +289,7 @@ export class Arena { /** * Sets weather to the override specified in overrides.ts - * @param weather new weather to set of type WeatherType + * @param weather new {@linkcode WeatherType} to set * @returns true to force trySetWeather to return true */ trySetWeatherOverride(weather: WeatherType): boolean { @@ -301,8 +301,8 @@ export class Arena { /** * Attempts to set a new weather to the battle - * @param weather new weather to set of type WeatherType - * @param hasPokemonSource is the new weather from a pokemon + * @param weather {@linkcode WeatherType} new {@linkcode WeatherType} to set + * @param hasPokemonSource boolean if the new weather is from a pokemon * @returns true if new weather set, false if no weather provided or attempting to set the same weather as currently in use */ trySetWeather(weather: WeatherType, hasPokemonSource: boolean): boolean { @@ -573,6 +573,12 @@ export class Arena { this.ignoreAbilities = ignoreAbilities; } + /** + * Applies each `ArenaTag` in this Arena, based on which side (self, enemy, or both) is passed in as a parameter + * @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply + * @param side {@linkcode ArenaTagSide} which side's arena tags to apply + * @param args array of parameters that the called upon tags may need + */ applyTagsForSide(tagType: ArenaTagType | Constructor, side: ArenaTagSide, ...args: unknown[]): void { let tags = typeof tagType === "string" ? this.tags.filter(t => t.tagType === tagType) @@ -583,11 +589,28 @@ export class Arena { tags.forEach(t => t.apply(this, args)); } + /** + * Applies the specified tag to both sides (ie: both user and trainer's tag that match the Tag specified) + * by calling {@linkcode applyTagsForSide()} + * @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply + * @param args array of parameters that the called upon tags may need + */ applyTags(tagType: ArenaTagType | Constructor, ...args: unknown[]): void { this.applyTagsForSide(tagType, ArenaTagSide.BOTH, ...args); } - addTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves | undefined, sourceId: integer, side: ArenaTagSide = ArenaTagSide.BOTH, quiet: boolean = false, targetIndex?: BattlerIndex): boolean { + /** + * Adds a new tag to the arena + * @param tagType {@linkcode ArenaTagType} the tag being added + * @param turnCount How many turns the tag lasts + * @param sourceMove {@linkcode Moves} the move the tag came from, or `undefined` if not from a move + * @param sourceId The ID of the pokemon in play the tag came from (see {@linkcode BattleScene.getPokemonById}) + * @param side {@linkcode ArenaTagSide} which side(s) the tag applies to + * @param quiet If a message should be queued on screen to announce the tag being added + * @param targetIndex The {@linkcode BattlerIndex} of the target pokemon + * @returns `false` if there already exists a tag of this type in the Arena + */ + addTag(tagType: ArenaTagType, turnCount: number, sourceMove: Moves | undefined, sourceId: number, side: ArenaTagSide = ArenaTagSide.BOTH, quiet: boolean = false, targetIndex?: BattlerIndex): boolean { const existingTag = this.getTagOnSide(tagType, side); if (existingTag) { existingTag.onOverlap(this); @@ -600,6 +623,7 @@ export class Arena { return false; } + // creates a new tag object const newTag = getArenaTag(tagType, turnCount || 0, sourceMove, sourceId, targetIndex, side); if (newTag) { this.tags.push(newTag); @@ -613,6 +637,11 @@ export class Arena { return true; } + /** + * Attempts to get a tag from the Arena via {@linkcode getTagOnSide} that applies to both sides + * @param tagType The {@linkcode ArenaTagType} or {@linkcode ArenaTag} to get + * @returns either the {@linkcode ArenaTag}, or `undefined` if it isn't there + */ getTag(tagType: ArenaTagType | Constructor): ArenaTag | undefined { return this.getTagOnSide(tagType, ArenaTagSide.BOTH); } @@ -621,16 +650,35 @@ export class Arena { return !!this.getTag(tagType); } + /** + * Attempts to get a tag from the Arena from a specific side (the tag passed in has to either apply to both sides, or the specific side only) + * + * eg: `MIST` only applies to the user's side, while `MUD_SPORT` applies to both user and enemy side + * @param tagType The {@linkcode ArenaTagType} or {@linkcode ArenaTag} to get + * @param side The {@linkcode ArenaTagSide} to look at + * @returns either the {@linkcode ArenaTag}, or `undefined` if it isn't there + */ getTagOnSide(tagType: ArenaTagType | Constructor, side: ArenaTagSide): ArenaTag | undefined { return typeof(tagType) === "string" ? this.tags.find(t => t.tagType === tagType && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side)) : this.tags.find(t => t instanceof tagType && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side)); } + /** + * Uses {@linkcode findTagsOnSide} to filter (using the parameter function) for specific tags that apply to both sides + * @param tagPredicate a function mapping {@linkcode ArenaTag}s to `boolean`s + * @returns array of {@linkcode ArenaTag}s from which the Arena's tags return true and apply to both sides + */ findTags(tagPredicate: (t: ArenaTag) => boolean): ArenaTag[] { return this.findTagsOnSide(tagPredicate, ArenaTagSide.BOTH); } + /** + * Returns specific tags from the arena that pass the `tagPredicate` function passed in as a parameter, and apply to the given side + * @param tagPredicate a function mapping {@linkcode ArenaTag}s to `boolean`s + * @param side The {@linkcode ArenaTagSide} to look at + * @returns array of {@linkcode ArenaTag}s from which the Arena's tags return `true` and apply to the given side + */ findTagsOnSide(tagPredicate: (t: ArenaTag) => boolean, side: ArenaTagSide): ArenaTag[] { return this.tags.filter(t => tagPredicate(t) && (side === ArenaTagSide.BOTH || t.side === ArenaTagSide.BOTH || t.side === side)); } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index f522d50f357..35a33907850 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -4501,6 +4501,7 @@ export interface AttackMoveResult { } export class PokemonSummonData { + /** [Atk, Def, SpAtk, SpDef, Spd, Acc, Eva] */ public statStages: number[] = [ 0, 0, 0, 0, 0, 0, 0 ]; public moveQueue: QueuedMove[] = []; public tags: BattlerTag[] = []; From 2fc3179bd90dfd8929ee1f1ff765f0075915d945 Mon Sep 17 00:00:00 2001 From: Leo Kim <47556641+KimJeongSun@users.noreply.github.com> Date: Sun, 8 Sep 2024 13:37:14 +0900 Subject: [PATCH 18/22] [Bug] Fix scrappy (+ some immunity move and ability) in inverse battle (#4067) * fix scrappy + etc. update inverse battle test code * update test code following request from swain --- src/field/pokemon.ts | 12 +- src/test/battle/inverse_battle.test.ts | 155 +++++++++++++++++++------ 2 files changed, 126 insertions(+), 41 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 35a33907850..863b0f41d2c 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1427,22 +1427,26 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } let multiplier = types.map(defType => { + const multiplier = new Utils.NumberHolder(getTypeDamageMultiplier(moveType, defType)); + applyChallenges(this.scene.gameMode, ChallengeType.TYPE_EFFECTIVENESS, multiplier); if (source) { const ignoreImmunity = new Utils.BooleanHolder(false); if (source.isActive(true) && source.hasAbilityWithAttr(IgnoreTypeImmunityAbAttr)) { applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, simulated, moveType, defType); } if (ignoreImmunity.value) { - return 1; + if (multiplier.value === 0) { + return 1; + } } const exposedTags = this.findTags(tag => tag instanceof ExposedTag) as ExposedTag[]; if (exposedTags.some(t => t.ignoreImmunity(defType, moveType))) { - return 1; + if (multiplier.value === 0) { + return 1; + } } } - const multiplier = new Utils.NumberHolder(getTypeDamageMultiplier(moveType, defType)); - applyChallenges(this.scene.gameMode, ChallengeType.TYPE_EFFECTIVENESS, multiplier); return multiplier.value; }).reduce((acc, cur) => acc * cur, 1) as TypeDamageMultiplier; diff --git a/src/test/battle/inverse_battle.test.ts b/src/test/battle/inverse_battle.test.ts index be8b04155eb..2a561a09e5e 100644 --- a/src/test/battle/inverse_battle.test.ts +++ b/src/test/battle/inverse_battle.test.ts @@ -1,8 +1,5 @@ import { BattlerIndex } from "#app/battle"; -import { allMoves } from "#app/data/move"; import { Type } from "#app/data/type"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; import { Abilities } from "#enums/abilities"; import { ArenaTagType } from "#enums/arena-tag-type"; import { Challenges } from "#enums/challenges"; @@ -11,7 +8,8 @@ import { Species } from "#enums/species"; import { StatusEffect } from "#enums/status-effect"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { SPLASH_ONLY } from "#test/utils/testUtils"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; const TIMEOUT = 20 * 1000; @@ -39,43 +37,63 @@ describe("Inverse Battle", () => { .starterSpecies(Species.FEEBAS) .ability(Abilities.BALL_FETCH) .enemySpecies(Species.MAGIKARP) - .enemyAbility(Abilities.BALL_FETCH); + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(SPLASH_ONLY); }); - it("1. immune types are 2x effective - Thunderbolt against Ground Type", async () => { - game.override.enemySpecies(Species.SANDSHREW); + it("Immune types are 2x effective - Thunderbolt against Ground Type", async () => { + game.override + .moveset([Moves.THUNDERBOLT]) + .enemySpecies(Species.SANDSHREW); + await game.challengeMode.startBattle(); - const player = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; + vi.spyOn(enemy, "getMoveEffectiveness"); - expect(enemy.getMoveEffectiveness(player, allMoves[Moves.THUNDERBOLT])).toBe(2); + game.move.select(Moves.THUNDERBOLT); + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.phaseInterceptor.to("MoveEffectPhase"); + + expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); }, TIMEOUT); - it("2. 2x effective types are 0.5x effective - Thunderbolt against Flying Type", async () => { - game.override.enemySpecies(Species.PIDGEY); + it("2x effective types are 0.5x effective - Thunderbolt against Flying Type", async () => { + game.override + .moveset([Moves.THUNDERBOLT]) + .enemySpecies(Species.PIDGEY); await game.challengeMode.startBattle(); - const player = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; + vi.spyOn(enemy, "getMoveEffectiveness"); - expect(enemy.getMoveEffectiveness(player, allMoves[Moves.THUNDERBOLT])).toBe(0.5); + game.move.select(Moves.THUNDERBOLT); + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.phaseInterceptor.to("MoveEffectPhase"); + + expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(0.5); }, TIMEOUT); - it("3. 0.5x effective types are 2x effective - Thunderbolt against Electric Type", async () => { - game.override.enemySpecies(Species.CHIKORITA); + it("0.5x effective types are 2x effective - Thunderbolt against Electric Type", async () => { + game.override + .moveset([Moves.THUNDERBOLT]) + .enemySpecies(Species.CHIKORITA); await game.challengeMode.startBattle(); - const player = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; + vi.spyOn(enemy, "getMoveEffectiveness"); - expect(enemy.getMoveEffectiveness(player, allMoves[Moves.THUNDERBOLT])).toBe(2); + game.move.select(Moves.THUNDERBOLT); + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.phaseInterceptor.to("MoveEffectPhase"); + + expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); }, TIMEOUT); - it("4. Stealth Rock follows the inverse matchups - Stealth Rock against Charizard deals 1/32 of max HP", async () => { + it("Stealth Rock follows the inverse matchups - Stealth Rock against Charizard deals 1/32 of max HP", async () => { game.scene.arena.addTag(ArenaTagType.STEALTH_ROCK, 1, Moves.STEALTH_ROCK, 0); game.override .enemySpecies(Species.CHARIZARD) @@ -95,18 +113,24 @@ describe("Inverse Battle", () => { expect(currentHp).toBeGreaterThan(maxHp * 31 / 32 - 1); }, TIMEOUT); - it("5. Freeze Dry is 2x effective against Water Type like other Ice type Move - Freeze Dry against Squirtle", async () => { - game.override.enemySpecies(Species.SQUIRTLE); + it("Freeze Dry is 2x effective against Water Type like other Ice type Move - Freeze Dry against Squirtle", async () => { + game.override + .moveset([Moves.FREEZE_DRY]) + .enemySpecies(Species.SQUIRTLE); await game.challengeMode.startBattle(); - const player = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; + vi.spyOn(enemy, "getMoveEffectiveness"); - expect(enemy.getMoveEffectiveness(player, allMoves[Moves.FREEZE_DRY])).toBe(2); + game.move.select(Moves.FREEZE_DRY); + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.phaseInterceptor.to("MoveEffectPhase"); + + expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); }, TIMEOUT); - it("6. Water Absorb should heal against water moves - Water Absorb against Water gun", async () => { + it("Water Absorb should heal against water moves - Water Absorb against Water gun", async () => { game.override .moveset([Moves.WATER_GUN]) .enemyAbility(Abilities.WATER_ABSORB); @@ -117,13 +141,12 @@ describe("Inverse Battle", () => { enemy.hp = enemy.getMaxHp() - 1; game.move.select(Moves.WATER_GUN); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); - - await game.phaseInterceptor.to(MoveEndPhase); + await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.hp).toBe(enemy.getMaxHp()); }, TIMEOUT); - it("7. Fire type does not get burned - Will-O-Wisp against Charmander", async () => { + it("Fire type does not get burned - Will-O-Wisp against Charmander", async () => { game.override .moveset([Moves.WILL_O_WISP]) .enemySpecies(Species.CHARMANDER); @@ -135,13 +158,12 @@ describe("Inverse Battle", () => { game.move.select(Moves.WILL_O_WISP); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.move.forceHit(); - - await game.phaseInterceptor.to(MoveEndPhase); + await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.status?.effect).not.toBe(StatusEffect.BURN); }, TIMEOUT); - it("8. Electric type does not get paralyzed - Nuzzle against Pikachu", async () => { + it("Electric type does not get paralyzed - Nuzzle against Pikachu", async () => { game.override .moveset([Moves.NUZZLE]) .enemySpecies(Species.PIKACHU) @@ -153,14 +175,30 @@ describe("Inverse Battle", () => { game.move.select(Moves.NUZZLE); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); - - await game.phaseInterceptor.to(MoveEndPhase); + await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.status?.effect).not.toBe(StatusEffect.PARALYSIS); }, TIMEOUT); + it("Ground type is not immune to Thunder Wave - Thunder Wave against Sandshrew", async () => { + game.override + .moveset([Moves.THUNDER_WAVE]) + .enemySpecies(Species.SANDSHREW); - it("10. Anticipation should trigger on 2x effective moves - Anticipation against Thunderbolt", async () => { + await game.challengeMode.startBattle(); + + const enemy = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.THUNDER_WAVE); + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.move.forceHit(); + await game.phaseInterceptor.to("MoveEndPhase"); + + expect(enemy.status?.effect).toBe(StatusEffect.PARALYSIS); + }, TIMEOUT); + + + it("Anticipation should trigger on 2x effective moves - Anticipation against Thunderbolt", async () => { game.override .moveset([Moves.THUNDERBOLT]) .enemySpecies(Species.SANDSHREW) @@ -171,7 +209,7 @@ describe("Inverse Battle", () => { expect(game.scene.getEnemyPokemon()?.summonData.abilitiesApplied[0]).toBe(Abilities.ANTICIPATION); }, TIMEOUT); - it("11. Conversion 2 should change the type to the resistive type - Conversion 2 against Dragonite", async () => { + it("Conversion 2 should change the type to the resistive type - Conversion 2 against Dragonite", async () => { game.override .moveset([Moves.CONVERSION_2]) .enemyMoveset([Moves.DRAGON_CLAW, Moves.DRAGON_CLAW, Moves.DRAGON_CLAW, Moves.DRAGON_CLAW]); @@ -183,21 +221,64 @@ describe("Inverse Battle", () => { game.move.select(Moves.CONVERSION_2); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); expect(player.getTypes()[0]).toBe(Type.DRAGON); }, TIMEOUT); - it("12. Flying Press should be 0.25x effective against Grass + Dark Type - Flying Press against Meowscarada", async () => { + it("Flying Press should be 0.25x effective against Grass + Dark Type - Flying Press against Meowscarada", async () => { game.override .moveset([Moves.FLYING_PRESS]) .enemySpecies(Species.MEOWSCARADA); await game.challengeMode.startBattle(); - const player = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; + vi.spyOn(enemy, "getMoveEffectiveness"); - expect(enemy.getMoveEffectiveness(player, allMoves[Moves.FLYING_PRESS])).toBe(0.25); + game.move.select(Moves.FLYING_PRESS); + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.phaseInterceptor.to("MoveEffectPhase"); + + expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(0.25); + }, TIMEOUT); + + it("Scrappy ability has no effect - Tackle against Ghost Type still 2x effective with Scrappy", async () => { + game.override + .moveset([Moves.TACKLE]) + .ability(Abilities.SCRAPPY) + .enemySpecies(Species.GASTLY); + + await game.challengeMode.startBattle(); + + const enemy = game.scene.getEnemyPokemon()!; + vi.spyOn(enemy, "getMoveEffectiveness"); + + game.move.select(Moves.TACKLE); + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.phaseInterceptor.to("MoveEffectPhase"); + + expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); + }, TIMEOUT); + + it("FORESIGHT has no effect - Tackle against Ghost Type still 2x effective with Foresight", async () => { + game.override + .moveset([Moves.FORESIGHT, Moves.TACKLE]) + .enemySpecies(Species.GASTLY); + + await game.challengeMode.startBattle(); + + const enemy = game.scene.getEnemyPokemon()!; + vi.spyOn(enemy, "getMoveEffectiveness"); + + game.move.select(Moves.FORESIGHT); + await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.phaseInterceptor.to("TurnEndPhase"); + + game.move.select(Moves.TACKLE); + await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.phaseInterceptor.to("MoveEffectPhase"); + + expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); }, TIMEOUT); }); From 2bd07cb84e02d51345a4e2c85543b023a35bdec7 Mon Sep 17 00:00:00 2001 From: flx-sta <50131232+flx-sta@users.noreply.github.com> Date: Sat, 7 Sep 2024 21:37:37 -0700 Subject: [PATCH 19/22] fix and optimize imports (#4061) - remove any `.js` extension imports - remove unncessary dynamic imports of `modifier.ts` file. The file was being imported statically & dynamically. Made it pure static - increase vite chunk-size warning limit Co-authored-by: Mumble <171087428+frutescens@users.noreply.github.com> --- src/@types/common.ts | 2 +- src/@types/i18next.d.ts | 2 +- src/battle-scene.ts | 2 +- src/configs/inputs/pad_procon.ts | 2 +- src/data/challenge.ts | 14 ++++---- src/data/egg.ts | 2 +- src/data/pokemon-forms.ts | 2 +- src/data/terrain.ts | 2 +- src/data/variant.ts | 2 +- src/events/arena.ts | 6 ++-- src/inputs-controller.ts | 2 +- src/main.ts | 4 +-- src/modifier/modifier-type.ts | 2 +- src/modifier/modifier.ts | 6 ++-- src/phases/add-enemy-buff-modifier-phase.ts | 10 +++--- src/phases/attempt-capture-phase.ts | 28 +++++++-------- src/phases/battle-end-phase.ts | 4 +-- src/phases/battle-phase.ts | 6 ++-- src/phases/berry-phase.ts | 12 +++---- src/phases/check-switch-phase.ts | 10 +++--- src/phases/common-anim-phase.ts | 6 ++-- src/phases/damage-phase.ts | 10 +++--- src/phases/end-card-phase.ts | 8 ++--- src/phases/end-evolution-phase.ts | 6 ++-- .../enemy-party-member-pokemon-phase.ts | 4 +-- src/phases/exp-phase.ts | 8 ++--- src/phases/field-phase.ts | 2 +- src/phases/game-over-modifier-reward-phase.ts | 6 ++-- src/phases/hide-party-exp-bar-phase.ts | 2 +- src/phases/learn-move-phase.ts | 18 +++++----- src/phases/level-cap-phase.ts | 4 +-- src/phases/level-up-phase.ts | 14 ++++---- src/phases/login-phase.ts | 12 +++---- src/phases/message-phase.ts | 4 +-- src/phases/modifier-reward-phase.ts | 4 +-- src/phases/money-reward-phase.ts | 8 ++--- src/phases/move-anim-test-phase.ts | 10 +++--- src/phases/move-effect-phase.ts | 28 +++++++-------- src/phases/move-end-phase.ts | 6 ++-- src/phases/move-header-phase.ts | 6 ++-- src/phases/move-phase.ts | 36 +++++++++---------- src/phases/new-biome-encounter-phase.ts | 6 ++-- src/phases/next-encounter-phase.ts | 2 +- src/phases/obtain-status-effect-phase.ts | 14 ++++---- src/phases/outdated-phase.ts | 6 ++-- src/phases/party-heal-phase.ts | 4 +-- src/phases/party-member-pokemon-phase.ts | 4 +-- src/phases/party-status-cure-phase.ts | 6 ++-- .../player-party-member-pokemon-phase.ts | 4 +-- src/phases/pokemon-heal-phase.ts | 20 +++++------ src/phases/pokemon-phase.ts | 6 ++-- src/phases/post-game-over-phase.ts | 4 +-- src/phases/post-summon-phase.ts | 10 +++--- src/phases/post-turn-status-effect-phase.ts | 18 +++++----- src/phases/quiet-form-change-phase.ts | 14 ++++---- src/phases/reload-session-phase.ts | 8 ++--- src/phases/return-phase.ts | 4 +-- src/phases/ribbon-modifier-reward-phase.ts | 8 ++--- src/phases/scan-ivs-phase.ts | 14 ++++---- src/phases/select-biome-phase.ts | 14 ++++---- src/phases/select-challenge-phase.ts | 6 ++-- src/phases/select-gender-phase.ts | 10 +++--- src/phases/select-modifier-phase.ts | 16 ++++----- src/phases/select-starter-phase.ts | 24 ++++++------- src/phases/select-target-phase.ts | 8 ++--- src/phases/shiny-sparkle-phase.ts | 4 +-- src/phases/show-ability-phase.ts | 4 +-- src/phases/show-party-exp-bar-phase.ts | 8 ++--- src/phases/show-trainer-phase.ts | 4 +-- src/phases/summon-missing-phase.ts | 4 +-- src/phases/summon-phase.ts | 18 +++++----- src/phases/switch-biome-phase.ts | 6 ++-- src/phases/switch-phase.ts | 6 ++-- src/phases/switch-summon-phase.ts | 20 +++++------ src/phases/test-message-phase.ts | 2 +- src/phases/title-phase.ts | 34 +++++++++--------- src/phases/toggle-double-position-phase.ts | 4 +-- src/phases/trainer-message-test-phase.ts | 6 ++-- src/phases/trainer-victory-phase.ts | 12 +++---- src/phases/turn-end-phase.ts | 18 +++++----- src/phases/turn-init-phase.ts | 8 ++--- src/phases/unavailable-phase.ts | 6 ++-- src/phases/unlock-phase.ts | 8 ++--- src/phases/victory-phase.ts | 10 +++--- src/phases/weather-effect-phase.ts | 2 +- src/plugins/i18n.ts | 22 ++++++------ src/system/arena-data.ts | 2 +- src/system/challenge-data.ts | 2 +- src/system/egg-data.ts | 2 +- src/system/game-data.ts | 24 ++++++------- src/system/settings/settings.ts | 2 +- src/system/voucher.ts | 4 +-- src/test/abilities/tera_shell.test.ts | 2 +- src/test/battle/damage_calculation.test.ts | 2 +- src/test/moves/gigaton_hammer.test.ts | 2 +- src/test/moves/lunar_blessing.test.ts | 4 +-- src/test/utils/helpers/overridesHelper.ts | 10 +++--- src/test/utils/testUtils.ts | 2 +- src/ui/ability-bar.ts | 2 +- src/ui/admin-ui-handler.ts | 4 +-- src/ui/arena-flyout.ts | 10 +++--- src/ui/ball-ui-handler.ts | 2 +- src/ui/battle-flyout.ts | 6 ++-- src/ui/command-ui-handler.ts | 4 +-- src/ui/dropdown.ts | 4 +-- src/ui/egg-counter-container.ts | 4 +-- src/ui/egg-hatch-scene-handler.ts | 2 +- src/ui/fight-ui-handler.ts | 6 ++-- src/ui/filter-bar.ts | 2 +- src/ui/party-ui-handler.ts | 8 ++--- src/ui/rename-form-ui-handler.ts | 2 +- src/ui/run-info-ui-handler.ts | 15 ++++---- src/ui/save-slot-select-ui-handler.ts | 8 ++--- .../settings/abstract-settings-ui-handler.ts | 2 +- .../settings/move-touch-controls-handler.ts | 4 +-- src/ui/settings/navigationMenu.ts | 2 +- src/ui/settings/settings-audio-ui-handler.ts | 2 +- .../settings/settings-display-ui-handler.ts | 2 +- .../settings/settings-gamepad-ui-handler.ts | 2 +- .../settings/settings-keyboard-ui-handler.ts | 2 +- src/ui/time-of-day-widget.ts | 2 +- src/ui/title-ui-handler.ts | 2 +- vite.config.ts | 1 + 123 files changed, 456 insertions(+), 460 deletions(-) diff --git a/src/@types/common.ts b/src/@types/common.ts index 6868d766008..fcd946656dc 100644 --- a/src/@types/common.ts +++ b/src/@types/common.ts @@ -1,3 +1,3 @@ -import BattleScene from "#app/battle-scene.js"; +import BattleScene from "#app/battle-scene"; export type ConditionFn = (scene: BattleScene, args?: any[]) => boolean; diff --git a/src/@types/i18next.d.ts b/src/@types/i18next.d.ts index d895659acef..9e8418a8977 100644 --- a/src/@types/i18next.d.ts +++ b/src/@types/i18next.d.ts @@ -1,4 +1,4 @@ -import { type enConfig } from "#app/locales/en/config.js"; +import { type enConfig } from "#app/locales/en/config"; import { TOptions } from "i18next"; //TODO: this needs to be type properly in the future diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 9123a213f4c..ff4258a13f5 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -63,7 +63,7 @@ import { Moves } from "#enums/moves"; import { PlayerGender } from "#enums/player-gender"; import { Species } from "#enums/species"; import { UiTheme } from "#enums/ui-theme"; -import { TimedEventManager } from "#app/timed-event-manager.js"; +import { TimedEventManager } from "#app/timed-event-manager"; import i18next from "i18next"; import { TrainerType } from "#enums/trainer-type"; import { battleSpecDialogue } from "./data/dialogue"; diff --git a/src/configs/inputs/pad_procon.ts b/src/configs/inputs/pad_procon.ts index 8cb707f882a..be751cc3acc 100644 --- a/src/configs/inputs/pad_procon.ts +++ b/src/configs/inputs/pad_procon.ts @@ -1,4 +1,4 @@ -import {SettingGamepad} from "#app/system/settings/settings-gamepad.js"; +import {SettingGamepad} from "#app/system/settings/settings-gamepad"; import {Button} from "#enums/buttons"; /** diff --git a/src/data/challenge.ts b/src/data/challenge.ts index 62751b92f9c..2205519c532 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -1,18 +1,18 @@ import * as Utils from "../utils"; import i18next from "i18next"; -import { defaultStarterSpecies, DexAttrProps, GameData } from "#app/system/game-data.js"; +import { defaultStarterSpecies, DexAttrProps, GameData } from "#app/system/game-data"; import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm, speciesStarters } from "./pokemon-species"; -import Pokemon, { PokemonMove } from "#app/field/pokemon.js"; -import { BattleType, FixedBattleConfig } from "#app/battle.js"; -import Trainer, { TrainerVariant } from "#app/field/trainer.js"; -import { GameMode } from "#app/game-mode.js"; +import Pokemon, { PokemonMove } from "#app/field/pokemon"; +import { BattleType, FixedBattleConfig } from "#app/battle"; +import Trainer, { TrainerVariant } from "#app/field/trainer"; +import { GameMode } from "#app/game-mode"; import { Type } from "./type"; import { Challenges } from "#enums/challenges"; import { Species } from "#enums/species"; import { TrainerType } from "#enums/trainer-type"; import { Nature } from "./nature"; -import { Moves } from "#app/enums/moves.js"; -import { TypeColor, TypeShadow } from "#app/enums/color.js"; +import { Moves } from "#app/enums/moves"; +import { TypeColor, TypeShadow } from "#app/enums/color"; import { pokemonEvolutions } from "./pokemon-evolutions"; import { pokemonFormChanges } from "./pokemon-forms"; diff --git a/src/data/egg.ts b/src/data/egg.ts index 508263c9c8e..ce27030ebef 100644 --- a/src/data/egg.ts +++ b/src/data/egg.ts @@ -8,7 +8,7 @@ import { PlayerPokemon } from "#app/field/pokemon"; import i18next from "i18next"; import { EggTier } from "#enums/egg-type"; import { Species } from "#enums/species"; -import { EggSourceType } from "#app/enums/egg-source-types.js"; +import { EggSourceType } from "#app/enums/egg-source-types"; export const EGG_SEED = 1073741824; diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index bc815b91f3a..0d3e511bcba 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -8,7 +8,7 @@ import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import { TimeOfDay } from "#enums/time-of-day"; -import { getPokemonNameWithAffix } from "#app/messages.js"; +import { getPokemonNameWithAffix } from "#app/messages"; import i18next from "i18next"; import { WeatherType } from "./weather"; diff --git a/src/data/terrain.ts b/src/data/terrain.ts index d4789078af7..6db68b92239 100644 --- a/src/data/terrain.ts +++ b/src/data/terrain.ts @@ -4,7 +4,7 @@ import { Type } from "./type"; import * as Utils from "../utils"; import { ChangeMovePriorityAbAttr, applyAbAttrs } from "./ability"; import { ProtectAttr } from "./move"; -import { BattlerIndex } from "#app/battle.js"; +import { BattlerIndex } from "#app/battle"; import i18next from "i18next"; export enum TerrainType { diff --git a/src/data/variant.ts b/src/data/variant.ts index 48369d112db..b7a01a4be89 100644 --- a/src/data/variant.ts +++ b/src/data/variant.ts @@ -1,4 +1,4 @@ -import { VariantTier } from "#app/enums/variant-tier.js"; +import { VariantTier } from "#app/enums/variant-tier"; export type Variant = 0 | 1 | 2; diff --git a/src/events/arena.ts b/src/events/arena.ts index 9fbbe572601..c05e67d353c 100644 --- a/src/events/arena.ts +++ b/src/events/arena.ts @@ -1,7 +1,7 @@ -import { ArenaTagSide } from "#app/data/arena-tag.js"; +import { ArenaTagSide } from "#app/data/arena-tag"; import { ArenaTagType } from "#enums/arena-tag-type"; -import { TerrainType } from "#app/data/terrain.js"; -import { WeatherType } from "#app/data/weather.js"; +import { TerrainType } from "#app/data/terrain"; +import { WeatherType } from "#app/data/weather"; /** Alias for all {@linkcode ArenaEvent} type strings */ export enum ArenaEventType { diff --git a/src/inputs-controller.ts b/src/inputs-controller.ts index 652e3d58062..bb3cfcbeb3b 100644 --- a/src/inputs-controller.ts +++ b/src/inputs-controller.ts @@ -16,7 +16,7 @@ import { getIconForLatestInput, swap, } from "#app/configs/inputs/configHandler"; import BattleScene from "./battle-scene"; -import {SettingGamepad} from "#app/system/settings/settings-gamepad.js"; +import {SettingGamepad} from "#app/system/settings/settings-gamepad"; import {SettingKeyboard} from "#app/system/settings/settings-keyboard"; import TouchControl from "#app/touch-controls"; import { Button } from "#enums/buttons"; diff --git a/src/main.ts b/src/main.ts index 8a69d3f1b72..b5f813bdf2f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,8 +4,8 @@ import InvertPostFX from "./pipelines/invert"; import { version } from "../package.json"; import UIPlugin from "phaser3-rex-plugins/templates/ui/ui-plugin"; import BBCodeTextPlugin from "phaser3-rex-plugins/plugins/bbcodetext-plugin"; -import InputTextPlugin from "phaser3-rex-plugins/plugins/inputtext-plugin.js"; -import TransitionImagePackPlugin from "phaser3-rex-plugins/templates/transitionimagepack/transitionimagepack-plugin.js"; +import InputTextPlugin from "phaser3-rex-plugins/plugins/inputtext-plugin"; +import TransitionImagePackPlugin from "phaser3-rex-plugins/templates/transitionimagepack/transitionimagepack-plugin"; import { LoadingScene } from "./loading-scene"; diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index d6cfd017829..fdfe60332f5 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -25,7 +25,7 @@ import { BattlerTagType } from "#enums/battler-tag-type"; import { BerryType } from "#enums/berry-type"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import { getPokemonNameWithAffix } from "#app/messages.js"; +import { getPokemonNameWithAffix } from "#app/messages"; import { PermanentStat, TEMP_BATTLE_STATS, TempBattleStat, Stat, getStatKey } from "#app/enums/stat"; const outputModifierData = false; diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index c1d58a7bf39..0b105a0c852 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -26,9 +26,9 @@ import i18next from "i18next"; import { allMoves } from "#app/data/move"; import { Abilities } from "#app/enums/abilities"; -import { LearnMovePhase } from "#app/phases/learn-move-phase.js"; -import { LevelUpPhase } from "#app/phases/level-up-phase.js"; -import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase.js"; +import { LearnMovePhase } from "#app/phases/learn-move-phase"; +import { LevelUpPhase } from "#app/phases/level-up-phase"; +import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; export type ModifierPredicate = (modifier: Modifier) => boolean; diff --git a/src/phases/add-enemy-buff-modifier-phase.ts b/src/phases/add-enemy-buff-modifier-phase.ts index a9936eb765d..451e6e2662c 100644 --- a/src/phases/add-enemy-buff-modifier-phase.ts +++ b/src/phases/add-enemy-buff-modifier-phase.ts @@ -1,8 +1,8 @@ -import BattleScene from "#app/battle-scene.js"; -import { ModifierTier } from "#app/modifier/modifier-tier.js"; -import { regenerateModifierPoolThresholds, ModifierPoolType, getEnemyBuffModifierForWave } from "#app/modifier/modifier-type.js"; -import { EnemyPersistentModifier } from "#app/modifier/modifier.js"; -import { Phase } from "#app/phase.js"; +import BattleScene from "#app/battle-scene"; +import { ModifierTier } from "#app/modifier/modifier-tier"; +import { regenerateModifierPoolThresholds, ModifierPoolType, getEnemyBuffModifierForWave } from "#app/modifier/modifier-type"; +import { EnemyPersistentModifier } from "#app/modifier/modifier"; +import { Phase } from "#app/phase"; export class AddEnemyBuffModifierPhase extends Phase { constructor(scene: BattleScene) { diff --git a/src/phases/attempt-capture-phase.ts b/src/phases/attempt-capture-phase.ts index 72995c0f006..55a82affaf6 100644 --- a/src/phases/attempt-capture-phase.ts +++ b/src/phases/attempt-capture-phase.ts @@ -1,17 +1,17 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import { getPokeballCatchMultiplier, getPokeballAtlasKey, getPokeballTintColor, doPokeballBounceAnim } from "#app/data/pokeball.js"; -import { getStatusEffectCatchRateMultiplier } from "#app/data/status-effect.js"; -import { PokeballType } from "#app/enums/pokeball.js"; -import { StatusEffect } from "#app/enums/status-effect.js"; -import { addPokeballOpenParticles, addPokeballCaptureStars } from "#app/field/anims.js"; -import { EnemyPokemon } from "#app/field/pokemon.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import { PokemonHeldItemModifier } from "#app/modifier/modifier.js"; -import { achvs } from "#app/system/achv.js"; -import { PartyUiMode, PartyOption } from "#app/ui/party-ui-handler.js"; -import { SummaryUiMode } from "#app/ui/summary-ui-handler.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import { getPokeballCatchMultiplier, getPokeballAtlasKey, getPokeballTintColor, doPokeballBounceAnim } from "#app/data/pokeball"; +import { getStatusEffectCatchRateMultiplier } from "#app/data/status-effect"; +import { PokeballType } from "#app/enums/pokeball"; +import { StatusEffect } from "#app/enums/status-effect"; +import { addPokeballOpenParticles, addPokeballCaptureStars } from "#app/field/anims"; +import { EnemyPokemon } from "#app/field/pokemon"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { PokemonHeldItemModifier } from "#app/modifier/modifier"; +import { achvs } from "#app/system/achv"; +import { PartyUiMode, PartyOption } from "#app/ui/party-ui-handler"; +import { SummaryUiMode } from "#app/ui/summary-ui-handler"; +import { Mode } from "#app/ui/ui"; import i18next from "i18next"; import { PokemonPhase } from "./pokemon-phase"; import { VictoryPhase } from "./victory-phase"; diff --git a/src/phases/battle-end-phase.ts b/src/phases/battle-end-phase.ts index 06315668a8b..f08e04b443a 100644 --- a/src/phases/battle-end-phase.ts +++ b/src/phases/battle-end-phase.ts @@ -1,5 +1,5 @@ -import { applyPostBattleAbAttrs, PostBattleAbAttr } from "#app/data/ability.js"; -import { LapsingPersistentModifier, LapsingPokemonHeldItemModifier } from "#app/modifier/modifier.js"; +import { applyPostBattleAbAttrs, PostBattleAbAttr } from "#app/data/ability"; +import { LapsingPersistentModifier, LapsingPokemonHeldItemModifier } from "#app/modifier/modifier"; import { BattlePhase } from "./battle-phase"; import { GameOverPhase } from "./game-over-phase"; diff --git a/src/phases/battle-phase.ts b/src/phases/battle-phase.ts index 3e7e0e28596..b51e19bdf0e 100644 --- a/src/phases/battle-phase.ts +++ b/src/phases/battle-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { TrainerSlot } from "#app/data/trainer-config.js"; -import { Phase } from "#app/phase.js"; +import BattleScene from "#app/battle-scene"; +import { TrainerSlot } from "#app/data/trainer-config"; +import { Phase } from "#app/phase"; export class BattlePhase extends Phase { constructor(scene: BattleScene) { diff --git a/src/phases/berry-phase.ts b/src/phases/berry-phase.ts index 504fb6ec163..66ecaa6c7f8 100644 --- a/src/phases/berry-phase.ts +++ b/src/phases/berry-phase.ts @@ -1,10 +1,10 @@ -import { applyAbAttrs, PreventBerryUseAbAttr, HealFromBerryUseAbAttr } from "#app/data/ability.js"; -import { CommonAnim } from "#app/data/battle-anims.js"; -import { BerryUsedEvent } from "#app/events/battle-scene.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import { BerryModifier } from "#app/modifier/modifier.js"; +import { applyAbAttrs, PreventBerryUseAbAttr, HealFromBerryUseAbAttr } from "#app/data/ability"; +import { CommonAnim } from "#app/data/battle-anims"; +import { BerryUsedEvent } from "#app/events/battle-scene"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { BerryModifier } from "#app/modifier/modifier"; import i18next from "i18next"; -import * as Utils from "#app/utils.js"; +import * as Utils from "#app/utils"; import { FieldPhase } from "./field-phase"; import { CommonAnimPhase } from "./common-anim-phase"; diff --git a/src/phases/check-switch-phase.ts b/src/phases/check-switch-phase.ts index cd8f2b00c46..a069ba224a2 100644 --- a/src/phases/check-switch-phase.ts +++ b/src/phases/check-switch-phase.ts @@ -1,8 +1,8 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattleStyle } from "#app/enums/battle-style.js"; -import { BattlerTagType } from "#app/enums/battler-tag-type.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { BattleStyle } from "#app/enums/battle-style"; +import { BattlerTagType } from "#app/enums/battler-tag-type"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { Mode } from "#app/ui/ui"; import i18next from "i18next"; import { BattlePhase } from "./battle-phase"; import { PostSummonPhase } from "./post-summon-phase"; diff --git a/src/phases/common-anim-phase.ts b/src/phases/common-anim-phase.ts index d3663abe3b6..a85cd7629d9 100644 --- a/src/phases/common-anim-phase.ts +++ b/src/phases/common-anim-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import { CommonAnim, CommonBattleAnim } from "#app/data/battle-anims.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import { CommonAnim, CommonBattleAnim } from "#app/data/battle-anims"; import { PokemonPhase } from "./pokemon-phase"; export class CommonAnimPhase extends PokemonPhase { diff --git a/src/phases/damage-phase.ts b/src/phases/damage-phase.ts index 029c1e717f1..5add0345358 100644 --- a/src/phases/damage-phase.ts +++ b/src/phases/damage-phase.ts @@ -1,8 +1,8 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import { BattleSpec } from "#app/enums/battle-spec.js"; -import { DamageResult, HitResult } from "#app/field/pokemon.js"; -import * as Utils from "#app/utils.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import { BattleSpec } from "#app/enums/battle-spec"; +import { DamageResult, HitResult } from "#app/field/pokemon"; +import * as Utils from "#app/utils"; import { PokemonPhase } from "./pokemon-phase"; export class DamagePhase extends PokemonPhase { diff --git a/src/phases/end-card-phase.ts b/src/phases/end-card-phase.ts index 0b70664b993..274a745017a 100644 --- a/src/phases/end-card-phase.ts +++ b/src/phases/end-card-phase.ts @@ -1,7 +1,7 @@ -import BattleScene from "#app/battle-scene.js"; -import { PlayerGender } from "#app/enums/player-gender.js"; -import { Phase } from "#app/phase.js"; -import { addTextObject, TextStyle } from "#app/ui/text.js"; +import BattleScene from "#app/battle-scene"; +import { PlayerGender } from "#app/enums/player-gender"; +import { Phase } from "#app/phase"; +import { addTextObject, TextStyle } from "#app/ui/text"; import i18next from "i18next"; export class EndCardPhase extends Phase { diff --git a/src/phases/end-evolution-phase.ts b/src/phases/end-evolution-phase.ts index 2a6d492a425..8a6ce52553d 100644 --- a/src/phases/end-evolution-phase.ts +++ b/src/phases/end-evolution-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { Phase } from "#app/phase.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { Phase } from "#app/phase"; +import { Mode } from "#app/ui/ui"; export class EndEvolutionPhase extends Phase { diff --git a/src/phases/enemy-party-member-pokemon-phase.ts b/src/phases/enemy-party-member-pokemon-phase.ts index 10af0913f93..bb34f53b475 100644 --- a/src/phases/enemy-party-member-pokemon-phase.ts +++ b/src/phases/enemy-party-member-pokemon-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import { EnemyPokemon } from "#app/field/pokemon.js"; +import BattleScene from "#app/battle-scene"; +import { EnemyPokemon } from "#app/field/pokemon"; import { PartyMemberPokemonPhase } from "./party-member-pokemon-phase"; export abstract class EnemyPartyMemberPokemonPhase extends PartyMemberPokemonPhase { diff --git a/src/phases/exp-phase.ts b/src/phases/exp-phase.ts index 9c2ba95d550..81982980d2a 100644 --- a/src/phases/exp-phase.ts +++ b/src/phases/exp-phase.ts @@ -1,8 +1,8 @@ -import BattleScene from "#app/battle-scene.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import { ExpBoosterModifier } from "#app/modifier/modifier.js"; +import BattleScene from "#app/battle-scene"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { ExpBoosterModifier } from "#app/modifier/modifier"; import i18next from "i18next"; -import * as Utils from "#app/utils.js"; +import * as Utils from "#app/utils"; import { PlayerPartyMemberPokemonPhase } from "./player-party-member-pokemon-phase"; import { LevelUpPhase } from "./level-up-phase"; diff --git a/src/phases/field-phase.ts b/src/phases/field-phase.ts index b65e903a32b..46c3c4983b4 100644 --- a/src/phases/field-phase.ts +++ b/src/phases/field-phase.ts @@ -1,4 +1,4 @@ -import Pokemon from "#app/field/pokemon.js"; +import Pokemon from "#app/field/pokemon"; import { BattlePhase } from "./battle-phase"; type PokemonFunc = (pokemon: Pokemon) => void; diff --git a/src/phases/game-over-modifier-reward-phase.ts b/src/phases/game-over-modifier-reward-phase.ts index c27659bf9d4..a698e62e2e1 100644 --- a/src/phases/game-over-modifier-reward-phase.ts +++ b/src/phases/game-over-modifier-reward-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { ModifierTypeFunc } from "#app/modifier/modifier-type.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { ModifierTypeFunc } from "#app/modifier/modifier-type"; +import { Mode } from "#app/ui/ui"; import i18next from "i18next"; import { ModifierRewardPhase } from "./modifier-reward-phase"; diff --git a/src/phases/hide-party-exp-bar-phase.ts b/src/phases/hide-party-exp-bar-phase.ts index c2c9d96462e..303650ea1ad 100644 --- a/src/phases/hide-party-exp-bar-phase.ts +++ b/src/phases/hide-party-exp-bar-phase.ts @@ -1,4 +1,4 @@ -import BattleScene from "#app/battle-scene.js"; +import BattleScene from "#app/battle-scene"; import { BattlePhase } from "./battle-phase"; export class HidePartyExpBarPhase extends BattlePhase { diff --git a/src/phases/learn-move-phase.ts b/src/phases/learn-move-phase.ts index 201019e8860..049fc6951b6 100644 --- a/src/phases/learn-move-phase.ts +++ b/src/phases/learn-move-phase.ts @@ -1,12 +1,12 @@ -import BattleScene from "#app/battle-scene.js"; -import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims.js"; -import { allMoves } from "#app/data/move.js"; -import { SpeciesFormChangeMoveLearnedTrigger } from "#app/data/pokemon-forms.js"; -import { Moves } from "#app/enums/moves.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import EvolutionSceneHandler from "#app/ui/evolution-scene-handler.js"; -import { SummaryUiMode } from "#app/ui/summary-ui-handler.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims"; +import { allMoves } from "#app/data/move"; +import { SpeciesFormChangeMoveLearnedTrigger } from "#app/data/pokemon-forms"; +import { Moves } from "#app/enums/moves"; +import { getPokemonNameWithAffix } from "#app/messages"; +import EvolutionSceneHandler from "#app/ui/evolution-scene-handler"; +import { SummaryUiMode } from "#app/ui/summary-ui-handler"; +import { Mode } from "#app/ui/ui"; import i18next from "i18next"; import { PlayerPartyMemberPokemonPhase } from "./player-party-member-pokemon-phase"; diff --git a/src/phases/level-cap-phase.ts b/src/phases/level-cap-phase.ts index db59fbd6473..d1404e45010 100644 --- a/src/phases/level-cap-phase.ts +++ b/src/phases/level-cap-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { Mode } from "#app/ui/ui"; import i18next from "i18next"; import { FieldPhase } from "./field-phase"; diff --git a/src/phases/level-up-phase.ts b/src/phases/level-up-phase.ts index a8a6b8f3d80..a99e038acba 100644 --- a/src/phases/level-up-phase.ts +++ b/src/phases/level-up-phase.ts @@ -1,11 +1,11 @@ -import BattleScene from "#app/battle-scene.js"; -import { ExpNotification } from "#app/enums/exp-notification.js"; -import { EvolutionPhase } from "#app/phases/evolution-phase.js"; -import { PlayerPokemon } from "#app/field/pokemon.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import { LevelAchv } from "#app/system/achv.js"; +import BattleScene from "#app/battle-scene"; +import { ExpNotification } from "#app/enums/exp-notification"; +import { EvolutionPhase } from "#app/phases/evolution-phase"; +import { PlayerPokemon } from "#app/field/pokemon"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { LevelAchv } from "#app/system/achv"; import i18next from "i18next"; -import * as Utils from "#app/utils.js"; +import * as Utils from "#app/utils"; import { PlayerPartyMemberPokemonPhase } from "./player-party-member-pokemon-phase"; import { LearnMovePhase } from "./learn-move-phase"; diff --git a/src/phases/login-phase.ts b/src/phases/login-phase.ts index b58cc9bca1f..89ced201e9e 100644 --- a/src/phases/login-phase.ts +++ b/src/phases/login-phase.ts @@ -1,10 +1,10 @@ -import { updateUserInfo } from "#app/account.js"; -import BattleScene, { bypassLogin } from "#app/battle-scene.js"; -import { Phase } from "#app/phase.js"; -import { handleTutorial, Tutorial } from "#app/tutorial.js"; -import { Mode } from "#app/ui/ui.js"; +import { updateUserInfo } from "#app/account"; +import BattleScene, { bypassLogin } from "#app/battle-scene"; +import { Phase } from "#app/phase"; +import { handleTutorial, Tutorial } from "#app/tutorial"; +import { Mode } from "#app/ui/ui"; import i18next, { t } from "i18next"; -import * as Utils from "#app/utils.js"; +import * as Utils from "#app/utils"; import { SelectGenderPhase } from "./select-gender-phase"; import { UnavailablePhase } from "./unavailable-phase"; diff --git a/src/phases/message-phase.ts b/src/phases/message-phase.ts index 46e907ae2ba..2244980c899 100644 --- a/src/phases/message-phase.ts +++ b/src/phases/message-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import { Phase } from "#app/phase.js"; +import BattleScene from "#app/battle-scene"; +import { Phase } from "#app/phase"; export class MessagePhase extends Phase { private text: string; diff --git a/src/phases/modifier-reward-phase.ts b/src/phases/modifier-reward-phase.ts index 4d083a367a6..20a8366d9c6 100644 --- a/src/phases/modifier-reward-phase.ts +++ b/src/phases/modifier-reward-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import { ModifierType, ModifierTypeFunc, getModifierType } from "#app/modifier/modifier-type.js"; +import BattleScene from "#app/battle-scene"; +import { ModifierType, ModifierTypeFunc, getModifierType } from "#app/modifier/modifier-type"; import i18next from "i18next"; import { BattlePhase } from "./battle-phase"; diff --git a/src/phases/money-reward-phase.ts b/src/phases/money-reward-phase.ts index e0bff608972..2f0a4f7b990 100644 --- a/src/phases/money-reward-phase.ts +++ b/src/phases/money-reward-phase.ts @@ -1,8 +1,8 @@ -import BattleScene from "#app/battle-scene.js"; -import { ArenaTagType } from "#app/enums/arena-tag-type.js"; -import { MoneyMultiplierModifier } from "#app/modifier/modifier.js"; +import BattleScene from "#app/battle-scene"; +import { ArenaTagType } from "#app/enums/arena-tag-type"; +import { MoneyMultiplierModifier } from "#app/modifier/modifier"; import i18next from "i18next"; -import * as Utils from "#app/utils.js"; +import * as Utils from "#app/utils"; import { BattlePhase } from "./battle-phase"; export class MoneyRewardPhase extends BattlePhase { diff --git a/src/phases/move-anim-test-phase.ts b/src/phases/move-anim-test-phase.ts index 7fb3c1d61e7..2d3b54bfd9a 100644 --- a/src/phases/move-anim-test-phase.ts +++ b/src/phases/move-anim-test-phase.ts @@ -1,8 +1,8 @@ -import BattleScene from "#app/battle-scene.js"; -import { initMoveAnim, loadMoveAnimAssets, MoveAnim } from "#app/data/battle-anims.js"; -import { allMoves, SelfStatusMove } from "#app/data/move.js"; -import { Moves } from "#app/enums/moves.js"; -import * as Utils from "#app/utils.js"; +import BattleScene from "#app/battle-scene"; +import { initMoveAnim, loadMoveAnimAssets, MoveAnim } from "#app/data/battle-anims"; +import { allMoves, SelfStatusMove } from "#app/data/move"; +import { Moves } from "#app/enums/moves"; +import * as Utils from "#app/utils"; import { BattlePhase } from "./battle-phase"; export class MoveAnimTestPhase extends BattlePhase { diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index 9b22c520e19..fb2b82ada03 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -1,18 +1,18 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import { applyPreAttackAbAttrs, AddSecondStrikeAbAttr, IgnoreMoveEffectsAbAttr, applyPostDefendAbAttrs, PostDefendAbAttr, applyPostAttackAbAttrs, PostAttackAbAttr, MaxMultiHitAbAttr, AlwaysHitAbAttr } from "#app/data/ability.js"; -import { ArenaTagSide, ConditionalProtectTag } from "#app/data/arena-tag.js"; -import { MoveAnim } from "#app/data/battle-anims.js"; -import { BattlerTagLapseType, ProtectedTag, SemiInvulnerableTag } from "#app/data/battler-tags.js"; -import { MoveTarget, applyMoveAttrs, OverrideMoveEffectAttr, MultiHitAttr, AttackMove, FixedDamageAttr, VariableTargetAttr, MissEffectAttr, MoveFlags, applyFilteredMoveAttrs, MoveAttr, MoveEffectAttr, MoveEffectTrigger, ChargeAttr, MoveCategory, NoEffectAttr, HitsTagAttr } from "#app/data/move.js"; -import { SpeciesFormChangePostMoveTrigger } from "#app/data/pokemon-forms.js"; -import { BattlerTagType } from "#app/enums/battler-tag-type.js"; -import { Moves } from "#app/enums/moves.js"; -import Pokemon, { PokemonMove, MoveResult, HitResult } from "#app/field/pokemon.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import { PokemonMultiHitModifier, FlinchChanceModifier, EnemyAttackStatusEffectChanceModifier, ContactHeldItemTransferChanceModifier, HitHealModifier } from "#app/modifier/modifier.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import { applyPreAttackAbAttrs, AddSecondStrikeAbAttr, IgnoreMoveEffectsAbAttr, applyPostDefendAbAttrs, PostDefendAbAttr, applyPostAttackAbAttrs, PostAttackAbAttr, MaxMultiHitAbAttr, AlwaysHitAbAttr } from "#app/data/ability"; +import { ArenaTagSide, ConditionalProtectTag } from "#app/data/arena-tag"; +import { MoveAnim } from "#app/data/battle-anims"; +import { BattlerTagLapseType, ProtectedTag, SemiInvulnerableTag } from "#app/data/battler-tags"; +import { MoveTarget, applyMoveAttrs, OverrideMoveEffectAttr, MultiHitAttr, AttackMove, FixedDamageAttr, VariableTargetAttr, MissEffectAttr, MoveFlags, applyFilteredMoveAttrs, MoveAttr, MoveEffectAttr, MoveEffectTrigger, ChargeAttr, MoveCategory, NoEffectAttr, HitsTagAttr } from "#app/data/move"; +import { SpeciesFormChangePostMoveTrigger } from "#app/data/pokemon-forms"; +import { BattlerTagType } from "#app/enums/battler-tag-type"; +import { Moves } from "#app/enums/moves"; +import Pokemon, { PokemonMove, MoveResult, HitResult } from "#app/field/pokemon"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { PokemonMultiHitModifier, FlinchChanceModifier, EnemyAttackStatusEffectChanceModifier, ContactHeldItemTransferChanceModifier, HitHealModifier } from "#app/modifier/modifier"; import i18next from "i18next"; -import * as Utils from "#app/utils.js"; +import * as Utils from "#app/utils"; import { PokemonPhase } from "./pokemon-phase"; export class MoveEffectPhase extends PokemonPhase { diff --git a/src/phases/move-end-phase.ts b/src/phases/move-end-phase.ts index 4bce2185aea..e03f2ec14b0 100644 --- a/src/phases/move-end-phase.ts +++ b/src/phases/move-end-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import { BattlerTagLapseType } from "#app/data/battler-tags.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import { BattlerTagLapseType } from "#app/data/battler-tags"; import { PokemonPhase } from "./pokemon-phase"; export class MoveEndPhase extends PokemonPhase { diff --git a/src/phases/move-header-phase.ts b/src/phases/move-header-phase.ts index 5166f287731..c307ff0be6e 100644 --- a/src/phases/move-header-phase.ts +++ b/src/phases/move-header-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { applyMoveAttrs, MoveHeaderAttr } from "#app/data/move.js"; -import Pokemon, { PokemonMove } from "#app/field/pokemon.js"; +import BattleScene from "#app/battle-scene"; +import { applyMoveAttrs, MoveHeaderAttr } from "#app/data/move"; +import Pokemon, { PokemonMove } from "#app/field/pokemon"; import { BattlePhase } from "./battle-phase"; export class MoveHeaderPhase extends BattlePhase { diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index 0ccf19a462f..8209bdd44d1 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -1,21 +1,21 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import { applyAbAttrs, applyPostMoveUsedAbAttrs, applyPreAttackAbAttrs, BlockRedirectAbAttr, IncreasePpAbAttr, PokemonTypeChangeAbAttr, PostMoveUsedAbAttr, RedirectMoveAbAttr } from "#app/data/ability.js"; -import { CommonAnim } from "#app/data/battle-anims.js"; -import { BattlerTagLapseType, CenterOfAttentionTag } from "#app/data/battler-tags.js"; -import { allMoves, applyMoveAttrs, BypassRedirectAttr, BypassSleepAttr, ChargeAttr, CopyMoveAttr, HealStatusEffectAttr, MoveFlags, PreMoveMessageAttr } from "#app/data/move.js"; -import { SpeciesFormChangePreMoveTrigger } from "#app/data/pokemon-forms.js"; -import { getStatusEffectActivationText, getStatusEffectHealText } from "#app/data/status-effect.js"; -import { Type } from "#app/data/type.js"; -import { getTerrainBlockMessage } from "#app/data/weather.js"; -import { Abilities } from "#app/enums/abilities.js"; -import { BattlerTagType } from "#app/enums/battler-tag-type.js"; -import { Moves } from "#app/enums/moves.js"; -import { StatusEffect } from "#app/enums/status-effect.js"; -import { MoveUsedEvent } from "#app/events/battle-scene.js"; -import Pokemon, { MoveResult, PokemonMove, TurnMove } from "#app/field/pokemon.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import * as Utils from "#app/utils.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import { applyAbAttrs, applyPostMoveUsedAbAttrs, applyPreAttackAbAttrs, BlockRedirectAbAttr, IncreasePpAbAttr, PokemonTypeChangeAbAttr, PostMoveUsedAbAttr, RedirectMoveAbAttr } from "#app/data/ability"; +import { CommonAnim } from "#app/data/battle-anims"; +import { BattlerTagLapseType, CenterOfAttentionTag } from "#app/data/battler-tags"; +import { allMoves, applyMoveAttrs, BypassRedirectAttr, BypassSleepAttr, ChargeAttr, CopyMoveAttr, HealStatusEffectAttr, MoveFlags, PreMoveMessageAttr } from "#app/data/move"; +import { SpeciesFormChangePreMoveTrigger } from "#app/data/pokemon-forms"; +import { getStatusEffectActivationText, getStatusEffectHealText } from "#app/data/status-effect"; +import { Type } from "#app/data/type"; +import { getTerrainBlockMessage } from "#app/data/weather"; +import { Abilities } from "#app/enums/abilities"; +import { BattlerTagType } from "#app/enums/battler-tag-type"; +import { Moves } from "#app/enums/moves"; +import { StatusEffect } from "#app/enums/status-effect"; +import { MoveUsedEvent } from "#app/events/battle-scene"; +import Pokemon, { MoveResult, PokemonMove, TurnMove } from "#app/field/pokemon"; +import { getPokemonNameWithAffix } from "#app/messages"; +import * as Utils from "#app/utils"; import i18next from "i18next"; import { BattlePhase } from "./battle-phase"; import { CommonAnimPhase } from "./common-anim-phase"; diff --git a/src/phases/new-biome-encounter-phase.ts b/src/phases/new-biome-encounter-phase.ts index c447e78f7b1..9f1209fb7ee 100644 --- a/src/phases/new-biome-encounter-phase.ts +++ b/src/phases/new-biome-encounter-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { applyAbAttrs, PostBiomeChangeAbAttr } from "#app/data/ability.js"; -import { getRandomWeatherType } from "#app/data/weather.js"; +import BattleScene from "#app/battle-scene"; +import { applyAbAttrs, PostBiomeChangeAbAttr } from "#app/data/ability"; +import { getRandomWeatherType } from "#app/data/weather"; import { NextEncounterPhase } from "./next-encounter-phase"; export class NewBiomeEncounterPhase extends NextEncounterPhase { diff --git a/src/phases/next-encounter-phase.ts b/src/phases/next-encounter-phase.ts index 89987534fc0..d51aa374b6e 100644 --- a/src/phases/next-encounter-phase.ts +++ b/src/phases/next-encounter-phase.ts @@ -1,4 +1,4 @@ -import BattleScene from "#app/battle-scene.js"; +import BattleScene from "#app/battle-scene"; import { EncounterPhase } from "./encounter-phase"; export class NextEncounterPhase extends EncounterPhase { diff --git a/src/phases/obtain-status-effect-phase.ts b/src/phases/obtain-status-effect-phase.ts index ac6e66a2e9f..bb06fafb1c9 100644 --- a/src/phases/obtain-status-effect-phase.ts +++ b/src/phases/obtain-status-effect-phase.ts @@ -1,10 +1,10 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import { CommonBattleAnim, CommonAnim } from "#app/data/battle-anims.js"; -import { getStatusEffectObtainText, getStatusEffectOverlapText } from "#app/data/status-effect.js"; -import { StatusEffect } from "#app/enums/status-effect.js"; -import Pokemon from "#app/field/pokemon.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import { CommonBattleAnim, CommonAnim } from "#app/data/battle-anims"; +import { getStatusEffectObtainText, getStatusEffectOverlapText } from "#app/data/status-effect"; +import { StatusEffect } from "#app/enums/status-effect"; +import Pokemon from "#app/field/pokemon"; +import { getPokemonNameWithAffix } from "#app/messages"; import { PokemonPhase } from "./pokemon-phase"; import { PostTurnStatusEffectPhase } from "./post-turn-status-effect-phase"; diff --git a/src/phases/outdated-phase.ts b/src/phases/outdated-phase.ts index 72d1bb3671d..4baf16d2f56 100644 --- a/src/phases/outdated-phase.ts +++ b/src/phases/outdated-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { Phase } from "#app/phase.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { Phase } from "#app/phase"; +import { Mode } from "#app/ui/ui"; export class OutdatedPhase extends Phase { constructor(scene: BattleScene) { diff --git a/src/phases/party-heal-phase.ts b/src/phases/party-heal-phase.ts index d9179826a19..e6ee11202df 100644 --- a/src/phases/party-heal-phase.ts +++ b/src/phases/party-heal-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import * as Utils from "#app/utils.js"; +import BattleScene from "#app/battle-scene"; +import * as Utils from "#app/utils"; import { BattlePhase } from "./battle-phase"; export class PartyHealPhase extends BattlePhase { diff --git a/src/phases/party-member-pokemon-phase.ts b/src/phases/party-member-pokemon-phase.ts index 1f27826884e..2b6ca01261d 100644 --- a/src/phases/party-member-pokemon-phase.ts +++ b/src/phases/party-member-pokemon-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import Pokemon from "#app/field/pokemon.js"; +import BattleScene from "#app/battle-scene"; +import Pokemon from "#app/field/pokemon"; import { FieldPhase } from "./field-phase"; export abstract class PartyMemberPokemonPhase extends FieldPhase { diff --git a/src/phases/party-status-cure-phase.ts b/src/phases/party-status-cure-phase.ts index a11aa01b63a..e4903c7fc1f 100644 --- a/src/phases/party-status-cure-phase.ts +++ b/src/phases/party-status-cure-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { Abilities } from "#app/enums/abilities.js"; -import Pokemon from "#app/field/pokemon.js"; +import BattleScene from "#app/battle-scene"; +import { Abilities } from "#app/enums/abilities"; +import Pokemon from "#app/field/pokemon"; import { BattlePhase } from "./battle-phase"; import { ShowAbilityPhase } from "./show-ability-phase"; diff --git a/src/phases/player-party-member-pokemon-phase.ts b/src/phases/player-party-member-pokemon-phase.ts index 4b1600b33d2..87855b9334c 100644 --- a/src/phases/player-party-member-pokemon-phase.ts +++ b/src/phases/player-party-member-pokemon-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import { PlayerPokemon } from "#app/field/pokemon.js"; +import BattleScene from "#app/battle-scene"; +import { PlayerPokemon } from "#app/field/pokemon"; import { PartyMemberPokemonPhase } from "./party-member-pokemon-phase"; export abstract class PlayerPartyMemberPokemonPhase extends PartyMemberPokemonPhase { diff --git a/src/phases/pokemon-heal-phase.ts b/src/phases/pokemon-heal-phase.ts index 6db8aeb4fca..49db2641e98 100644 --- a/src/phases/pokemon-heal-phase.ts +++ b/src/phases/pokemon-heal-phase.ts @@ -1,14 +1,14 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import { CommonAnim } from "#app/data/battle-anims.js"; -import { getStatusEffectHealText } from "#app/data/status-effect.js"; -import { StatusEffect } from "#app/enums/status-effect.js"; -import { HitResult, DamageResult } from "#app/field/pokemon.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import { HealingBoosterModifier } from "#app/modifier/modifier.js"; -import { HealAchv } from "#app/system/achv.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import { CommonAnim } from "#app/data/battle-anims"; +import { getStatusEffectHealText } from "#app/data/status-effect"; +import { StatusEffect } from "#app/enums/status-effect"; +import { HitResult, DamageResult } from "#app/field/pokemon"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { HealingBoosterModifier } from "#app/modifier/modifier"; +import { HealAchv } from "#app/system/achv"; import i18next from "i18next"; -import * as Utils from "#app/utils.js"; +import * as Utils from "#app/utils"; import { CommonAnimPhase } from "./common-anim-phase"; export class PokemonHealPhase extends CommonAnimPhase { diff --git a/src/phases/pokemon-phase.ts b/src/phases/pokemon-phase.ts index 871ee57d7a5..b980c1d1719 100644 --- a/src/phases/pokemon-phase.ts +++ b/src/phases/pokemon-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import Pokemon from "#app/field/pokemon.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import Pokemon from "#app/field/pokemon"; import { FieldPhase } from "./field-phase"; export abstract class PokemonPhase extends FieldPhase { diff --git a/src/phases/post-game-over-phase.ts b/src/phases/post-game-over-phase.ts index 02413b41a23..beeb30c7260 100644 --- a/src/phases/post-game-over-phase.ts +++ b/src/phases/post-game-over-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import { Phase } from "#app/phase.js"; +import BattleScene from "#app/battle-scene"; +import { Phase } from "#app/phase"; import { EndCardPhase } from "./end-card-phase"; import { TitlePhase } from "./title-phase"; diff --git a/src/phases/post-summon-phase.ts b/src/phases/post-summon-phase.ts index e671bf30ed1..47a5513f0eb 100644 --- a/src/phases/post-summon-phase.ts +++ b/src/phases/post-summon-phase.ts @@ -1,8 +1,8 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import { applyPostSummonAbAttrs, PostSummonAbAttr } from "#app/data/ability.js"; -import { ArenaTrapTag } from "#app/data/arena-tag.js"; -import { StatusEffect } from "#app/enums/status-effect.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import { applyPostSummonAbAttrs, PostSummonAbAttr } from "#app/data/ability"; +import { ArenaTrapTag } from "#app/data/arena-tag"; +import { StatusEffect } from "#app/enums/status-effect"; import { PokemonPhase } from "./pokemon-phase"; export class PostSummonPhase extends PokemonPhase { diff --git a/src/phases/post-turn-status-effect-phase.ts b/src/phases/post-turn-status-effect-phase.ts index 47db32303a5..413f9eae65e 100644 --- a/src/phases/post-turn-status-effect-phase.ts +++ b/src/phases/post-turn-status-effect-phase.ts @@ -1,12 +1,12 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import { applyAbAttrs, BlockNonDirectDamageAbAttr, BlockStatusDamageAbAttr, ReduceBurnDamageAbAttr } from "#app/data/ability.js"; -import { CommonBattleAnim, CommonAnim } from "#app/data/battle-anims.js"; -import { getStatusEffectActivationText } from "#app/data/status-effect.js"; -import { BattleSpec } from "#app/enums/battle-spec.js"; -import { StatusEffect } from "#app/enums/status-effect.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import * as Utils from "#app/utils.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import { applyAbAttrs, BlockNonDirectDamageAbAttr, BlockStatusDamageAbAttr, ReduceBurnDamageAbAttr } from "#app/data/ability"; +import { CommonBattleAnim, CommonAnim } from "#app/data/battle-anims"; +import { getStatusEffectActivationText } from "#app/data/status-effect"; +import { BattleSpec } from "#app/enums/battle-spec"; +import { StatusEffect } from "#app/enums/status-effect"; +import { getPokemonNameWithAffix } from "#app/messages"; +import * as Utils from "#app/utils"; import { PokemonPhase } from "./pokemon-phase"; export class PostTurnStatusEffectPhase extends PokemonPhase { diff --git a/src/phases/quiet-form-change-phase.ts b/src/phases/quiet-form-change-phase.ts index 3d30d36907e..6a1d31d137d 100644 --- a/src/phases/quiet-form-change-phase.ts +++ b/src/phases/quiet-form-change-phase.ts @@ -1,10 +1,10 @@ -import BattleScene from "#app/battle-scene.js"; -import { SemiInvulnerableTag } from "#app/data/battler-tags.js"; -import { SpeciesFormChange, getSpeciesFormChangeMessage } from "#app/data/pokemon-forms.js"; -import { getTypeRgb } from "#app/data/type.js"; -import { BattleSpec } from "#app/enums/battle-spec.js"; -import Pokemon, { EnemyPokemon } from "#app/field/pokemon.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; +import BattleScene from "#app/battle-scene"; +import { SemiInvulnerableTag } from "#app/data/battler-tags"; +import { SpeciesFormChange, getSpeciesFormChangeMessage } from "#app/data/pokemon-forms"; +import { getTypeRgb } from "#app/data/type"; +import { BattleSpec } from "#app/enums/battle-spec"; +import Pokemon, { EnemyPokemon } from "#app/field/pokemon"; +import { getPokemonNameWithAffix } from "#app/messages"; import { BattlePhase } from "./battle-phase"; import { MovePhase } from "./move-phase"; import { PokemonHealPhase } from "./pokemon-heal-phase"; diff --git a/src/phases/reload-session-phase.ts b/src/phases/reload-session-phase.ts index a61c52323bf..f8a38105869 100644 --- a/src/phases/reload-session-phase.ts +++ b/src/phases/reload-session-phase.ts @@ -1,7 +1,7 @@ -import BattleScene from "#app/battle-scene.js"; -import { Phase } from "#app/phase.js"; -import { Mode } from "#app/ui/ui.js"; -import * as Utils from "#app/utils.js"; +import BattleScene from "#app/battle-scene"; +import { Phase } from "#app/phase"; +import { Mode } from "#app/ui/ui"; +import * as Utils from "#app/utils"; export class ReloadSessionPhase extends Phase { private systemDataStr: string | null; diff --git a/src/phases/return-phase.ts b/src/phases/return-phase.ts index e1753670ad4..dfc458eb817 100644 --- a/src/phases/return-phase.ts +++ b/src/phases/return-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms.js"; +import BattleScene from "#app/battle-scene"; +import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms"; import { SwitchSummonPhase } from "./switch-summon-phase"; export class ReturnPhase extends SwitchSummonPhase { diff --git a/src/phases/ribbon-modifier-reward-phase.ts b/src/phases/ribbon-modifier-reward-phase.ts index 4a80325b7e7..fabb3bfa1b1 100644 --- a/src/phases/ribbon-modifier-reward-phase.ts +++ b/src/phases/ribbon-modifier-reward-phase.ts @@ -1,7 +1,7 @@ -import BattleScene from "#app/battle-scene.js"; -import PokemonSpecies from "#app/data/pokemon-species.js"; -import { ModifierTypeFunc } from "#app/modifier/modifier-type.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import PokemonSpecies from "#app/data/pokemon-species"; +import { ModifierTypeFunc } from "#app/modifier/modifier-type"; +import { Mode } from "#app/ui/ui"; import i18next from "i18next"; import { ModifierRewardPhase } from "./modifier-reward-phase"; diff --git a/src/phases/scan-ivs-phase.ts b/src/phases/scan-ivs-phase.ts index f5e1a814612..ba27e4f1943 100644 --- a/src/phases/scan-ivs-phase.ts +++ b/src/phases/scan-ivs-phase.ts @@ -1,10 +1,10 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import { CommonBattleAnim, CommonAnim } from "#app/data/battle-anims.js"; -import { Stat } from "#app/enums/stat.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import { getTextColor, TextStyle } from "#app/ui/text.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import { CommonBattleAnim, CommonAnim } from "#app/data/battle-anims"; +import { Stat } from "#app/enums/stat"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { getTextColor, TextStyle } from "#app/ui/text"; +import { Mode } from "#app/ui/ui"; import i18next from "i18next"; import { PokemonPhase } from "./pokemon-phase"; diff --git a/src/phases/select-biome-phase.ts b/src/phases/select-biome-phase.ts index 68c2cd29f26..fe9b5b3996b 100644 --- a/src/phases/select-biome-phase.ts +++ b/src/phases/select-biome-phase.ts @@ -1,11 +1,11 @@ -import BattleScene from "#app/battle-scene.js"; -import { biomeLinks, getBiomeName } from "#app/data/biomes.js"; -import { Biome } from "#app/enums/biome.js"; -import { MoneyInterestModifier, MapModifier } from "#app/modifier/modifier.js"; -import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { biomeLinks, getBiomeName } from "#app/data/biomes"; +import { Biome } from "#app/enums/biome"; +import { MoneyInterestModifier, MapModifier } from "#app/modifier/modifier"; +import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; +import { Mode } from "#app/ui/ui"; import { BattlePhase } from "./battle-phase"; -import * as Utils from "#app/utils.js"; +import * as Utils from "#app/utils"; import { PartyHealPhase } from "./party-heal-phase"; import { SwitchBiomePhase } from "./switch-biome-phase"; diff --git a/src/phases/select-challenge-phase.ts b/src/phases/select-challenge-phase.ts index eaf830e0059..9450c60fec5 100644 --- a/src/phases/select-challenge-phase.ts +++ b/src/phases/select-challenge-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { Phase } from "#app/phase.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { Phase } from "#app/phase"; +import { Mode } from "#app/ui/ui"; export class SelectChallengePhase extends Phase { constructor(scene: BattleScene) { diff --git a/src/phases/select-gender-phase.ts b/src/phases/select-gender-phase.ts index 3fc6916e233..7f2c965f1d1 100644 --- a/src/phases/select-gender-phase.ts +++ b/src/phases/select-gender-phase.ts @@ -1,8 +1,8 @@ -import BattleScene from "#app/battle-scene.js"; -import { PlayerGender } from "#app/enums/player-gender.js"; -import { Phase } from "#app/phase.js"; -import { SettingKeys } from "#app/system/settings/settings.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { PlayerGender } from "#app/enums/player-gender"; +import { Phase } from "#app/phase"; +import { SettingKeys } from "#app/system/settings/settings"; +import { Mode } from "#app/ui/ui"; import i18next from "i18next"; export class SelectGenderPhase extends Phase { diff --git a/src/phases/select-modifier-phase.ts b/src/phases/select-modifier-phase.ts index 1c96d278d69..e14638c5dd2 100644 --- a/src/phases/select-modifier-phase.ts +++ b/src/phases/select-modifier-phase.ts @@ -1,12 +1,12 @@ -import BattleScene from "#app/battle-scene.js"; -import { ModifierTier } from "#app/modifier/modifier-tier.js"; -import { regenerateModifierPoolThresholds, ModifierTypeOption, ModifierType, getPlayerShopModifierTypeOptionsForWave, PokemonModifierType, FusePokemonModifierType, PokemonMoveModifierType, TmModifierType, RememberMoveModifierType, PokemonPpRestoreModifierType, PokemonPpUpModifierType, ModifierPoolType, getPlayerModifierTypeOptions } from "#app/modifier/modifier-type.js"; -import { ExtraModifierModifier, Modifier, PokemonHeldItemModifier } from "#app/modifier/modifier.js"; -import ModifierSelectUiHandler, { SHOP_OPTIONS_ROW_LIMIT } from "#app/ui/modifier-select-ui-handler.js"; -import PartyUiHandler, { PartyUiMode, PartyOption } from "#app/ui/party-ui-handler.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { ModifierTier } from "#app/modifier/modifier-tier"; +import { regenerateModifierPoolThresholds, ModifierTypeOption, ModifierType, getPlayerShopModifierTypeOptionsForWave, PokemonModifierType, FusePokemonModifierType, PokemonMoveModifierType, TmModifierType, RememberMoveModifierType, PokemonPpRestoreModifierType, PokemonPpUpModifierType, ModifierPoolType, getPlayerModifierTypeOptions } from "#app/modifier/modifier-type"; +import { ExtraModifierModifier, Modifier, PokemonHeldItemModifier } from "#app/modifier/modifier"; +import ModifierSelectUiHandler, { SHOP_OPTIONS_ROW_LIMIT } from "#app/ui/modifier-select-ui-handler"; +import PartyUiHandler, { PartyUiMode, PartyOption } from "#app/ui/party-ui-handler"; +import { Mode } from "#app/ui/ui"; import i18next from "i18next"; -import * as Utils from "#app/utils.js"; +import * as Utils from "#app/utils"; import { BattlePhase } from "./battle-phase"; import Overrides from "#app/overrides"; diff --git a/src/phases/select-starter-phase.ts b/src/phases/select-starter-phase.ts index ad972a49225..cd3c112549c 100644 --- a/src/phases/select-starter-phase.ts +++ b/src/phases/select-starter-phase.ts @@ -1,15 +1,15 @@ -import BattleScene from "#app/battle-scene.js"; -import { applyChallenges, ChallengeType } from "#app/data/challenge.js"; -import { Gender } from "#app/data/gender.js"; -import { SpeciesFormChangeMoveLearnedTrigger } from "#app/data/pokemon-forms.js"; -import { getPokemonSpecies } from "#app/data/pokemon-species.js"; -import { Species } from "#app/enums/species.js"; -import { PlayerPokemon } from "#app/field/pokemon.js"; -import { overrideModifiers, overrideHeldItems } from "#app/modifier/modifier.js"; -import { Phase } from "#app/phase.js"; -import { SaveSlotUiMode } from "#app/ui/save-slot-select-ui-handler.js"; -import { Starter } from "#app/ui/starter-select-ui-handler.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { applyChallenges, ChallengeType } from "#app/data/challenge"; +import { Gender } from "#app/data/gender"; +import { SpeciesFormChangeMoveLearnedTrigger } from "#app/data/pokemon-forms"; +import { getPokemonSpecies } from "#app/data/pokemon-species"; +import { Species } from "#app/enums/species"; +import { PlayerPokemon } from "#app/field/pokemon"; +import { overrideModifiers, overrideHeldItems } from "#app/modifier/modifier"; +import { Phase } from "#app/phase"; +import { SaveSlotUiMode } from "#app/ui/save-slot-select-ui-handler"; +import { Starter } from "#app/ui/starter-select-ui-handler"; +import { Mode } from "#app/ui/ui"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import { TitlePhase } from "./title-phase"; import Overrides from "#app/overrides"; diff --git a/src/phases/select-target-phase.ts b/src/phases/select-target-phase.ts index fe72335e312..716d2737a6c 100644 --- a/src/phases/select-target-phase.ts +++ b/src/phases/select-target-phase.ts @@ -1,7 +1,7 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import { Command } from "#app/ui/command-ui-handler.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import { Command } from "#app/ui/command-ui-handler"; +import { Mode } from "#app/ui/ui"; import { CommandPhase } from "./command-phase"; import { PokemonPhase } from "./pokemon-phase"; diff --git a/src/phases/shiny-sparkle-phase.ts b/src/phases/shiny-sparkle-phase.ts index 4cd2b68f881..49c60a82dd5 100644 --- a/src/phases/shiny-sparkle-phase.ts +++ b/src/phases/shiny-sparkle-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; import { PokemonPhase } from "./pokemon-phase"; export class ShinySparklePhase extends PokemonPhase { diff --git a/src/phases/show-ability-phase.ts b/src/phases/show-ability-phase.ts index ee0b98f7886..cf34e327b4f 100644 --- a/src/phases/show-ability-phase.ts +++ b/src/phases/show-ability-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; import { PokemonPhase } from "./pokemon-phase"; export class ShowAbilityPhase extends PokemonPhase { diff --git a/src/phases/show-party-exp-bar-phase.ts b/src/phases/show-party-exp-bar-phase.ts index 9920472e801..9e019b202a5 100644 --- a/src/phases/show-party-exp-bar-phase.ts +++ b/src/phases/show-party-exp-bar-phase.ts @@ -1,7 +1,7 @@ -import BattleScene from "#app/battle-scene.js"; -import { ExpNotification } from "#app/enums/exp-notification.js"; -import { ExpBoosterModifier } from "#app/modifier/modifier.js"; -import * as Utils from "#app/utils.js"; +import BattleScene from "#app/battle-scene"; +import { ExpNotification } from "#app/enums/exp-notification"; +import { ExpBoosterModifier } from "#app/modifier/modifier"; +import * as Utils from "#app/utils"; import { HidePartyExpBarPhase } from "./hide-party-exp-bar-phase"; import { LevelUpPhase } from "./level-up-phase"; import { PlayerPartyMemberPokemonPhase } from "./player-party-member-pokemon-phase"; diff --git a/src/phases/show-trainer-phase.ts b/src/phases/show-trainer-phase.ts index 8a869f582d8..26ccddd53fc 100644 --- a/src/phases/show-trainer-phase.ts +++ b/src/phases/show-trainer-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import { PlayerGender } from "#app/enums/player-gender.js"; +import BattleScene from "#app/battle-scene"; +import { PlayerGender } from "#app/enums/player-gender"; import { BattlePhase } from "./battle-phase"; export class ShowTrainerPhase extends BattlePhase { diff --git a/src/phases/summon-missing-phase.ts b/src/phases/summon-missing-phase.ts index bb9607285ad..83ac8779dd8 100644 --- a/src/phases/summon-missing-phase.ts +++ b/src/phases/summon-missing-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; +import BattleScene from "#app/battle-scene"; +import { getPokemonNameWithAffix } from "#app/messages"; import i18next from "i18next"; import { SummonPhase } from "./summon-phase"; diff --git a/src/phases/summon-phase.ts b/src/phases/summon-phase.ts index f65a2063d4c..2645060c547 100644 --- a/src/phases/summon-phase.ts +++ b/src/phases/summon-phase.ts @@ -1,12 +1,12 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattleType } from "#app/battle.js"; -import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball.js"; -import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms.js"; -import { TrainerSlot } from "#app/data/trainer-config.js"; -import { PlayerGender } from "#app/enums/player-gender.js"; -import { addPokeballOpenParticles } from "#app/field/anims.js"; -import Pokemon, { FieldPosition } from "#app/field/pokemon.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; +import BattleScene from "#app/battle-scene"; +import { BattleType } from "#app/battle"; +import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball"; +import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms"; +import { TrainerSlot } from "#app/data/trainer-config"; +import { PlayerGender } from "#app/enums/player-gender"; +import { addPokeballOpenParticles } from "#app/field/anims"; +import Pokemon, { FieldPosition } from "#app/field/pokemon"; +import { getPokemonNameWithAffix } from "#app/messages"; import i18next from "i18next"; import { PartyMemberPokemonPhase } from "./party-member-pokemon-phase"; import { PostSummonPhase } from "./post-summon-phase"; diff --git a/src/phases/switch-biome-phase.ts b/src/phases/switch-biome-phase.ts index f20cd59b240..9cf5635a39f 100644 --- a/src/phases/switch-biome-phase.ts +++ b/src/phases/switch-biome-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { Biome } from "#app/enums/biome.js"; -import { getBiomeKey } from "#app/field/arena.js"; +import BattleScene from "#app/battle-scene"; +import { Biome } from "#app/enums/biome"; +import { getBiomeKey } from "#app/field/arena"; import { BattlePhase } from "./battle-phase"; export class SwitchBiomePhase extends BattlePhase { diff --git a/src/phases/switch-phase.ts b/src/phases/switch-phase.ts index 93b0943febf..b1a2e991ed8 100644 --- a/src/phases/switch-phase.ts +++ b/src/phases/switch-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import PartyUiHandler, { PartyUiMode, PartyOption } from "#app/ui/party-ui-handler.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import PartyUiHandler, { PartyUiMode, PartyOption } from "#app/ui/party-ui-handler"; +import { Mode } from "#app/ui/ui"; import { BattlePhase } from "./battle-phase"; import { SwitchSummonPhase } from "./switch-summon-phase"; diff --git a/src/phases/switch-summon-phase.ts b/src/phases/switch-summon-phase.ts index 8201f2879ed..2a5fd0cc3ac 100644 --- a/src/phases/switch-summon-phase.ts +++ b/src/phases/switch-summon-phase.ts @@ -1,13 +1,13 @@ -import BattleScene from "#app/battle-scene.js"; -import { applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr } from "#app/data/ability.js"; -import { allMoves, ForceSwitchOutAttr } from "#app/data/move.js"; -import { getPokeballTintColor } from "#app/data/pokeball.js"; -import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms.js"; -import { TrainerSlot } from "#app/data/trainer-config.js"; -import Pokemon from "#app/field/pokemon.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import { SwitchEffectTransferModifier } from "#app/modifier/modifier.js"; -import { Command } from "#app/ui/command-ui-handler.js"; +import BattleScene from "#app/battle-scene"; +import { applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr } from "#app/data/ability"; +import { allMoves, ForceSwitchOutAttr } from "#app/data/move"; +import { getPokeballTintColor } from "#app/data/pokeball"; +import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms"; +import { TrainerSlot } from "#app/data/trainer-config"; +import Pokemon from "#app/field/pokemon"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { SwitchEffectTransferModifier } from "#app/modifier/modifier"; +import { Command } from "#app/ui/command-ui-handler"; import i18next from "i18next"; import { PostSummonPhase } from "./post-summon-phase"; import { SummonPhase } from "./summon-phase"; diff --git a/src/phases/test-message-phase.ts b/src/phases/test-message-phase.ts index 14fed24ef4b..464a5ed1f94 100644 --- a/src/phases/test-message-phase.ts +++ b/src/phases/test-message-phase.ts @@ -1,4 +1,4 @@ -import BattleScene from "#app/battle-scene.js"; +import BattleScene from "#app/battle-scene"; import { MessagePhase } from "./message-phase"; export class TestMessagePhase extends MessagePhase { diff --git a/src/phases/title-phase.ts b/src/phases/title-phase.ts index 4c89b725c2d..52503501837 100644 --- a/src/phases/title-phase.ts +++ b/src/phases/title-phase.ts @@ -1,21 +1,21 @@ -import { loggedInUser } from "#app/account.js"; -import BattleScene from "#app/battle-scene.js"; -import { BattleType } from "#app/battle.js"; -import { getDailyRunStarters, fetchDailyRunSeed } from "#app/data/daily-run.js"; -import { Gender } from "#app/data/gender.js"; -import { getBiomeKey } from "#app/field/arena.js"; -import { GameModes, GameMode, getGameMode } from "#app/game-mode.js"; -import { regenerateModifierPoolThresholds, ModifierPoolType, modifierTypes, getDailyRunStarterModifiers } from "#app/modifier/modifier-type.js"; -import { Phase } from "#app/phase.js"; -import { SessionSaveData } from "#app/system/game-data.js"; -import { Unlockables } from "#app/system/unlockables.js"; -import { vouchers } from "#app/system/voucher.js"; -import { OptionSelectItem, OptionSelectConfig } from "#app/ui/abstact-option-select-ui-handler.js"; -import { SaveSlotUiMode } from "#app/ui/save-slot-select-ui-handler.js"; -import { Mode } from "#app/ui/ui.js"; +import { loggedInUser } from "#app/account"; +import BattleScene from "#app/battle-scene"; +import { BattleType } from "#app/battle"; +import { getDailyRunStarters, fetchDailyRunSeed } from "#app/data/daily-run"; +import { Gender } from "#app/data/gender"; +import { getBiomeKey } from "#app/field/arena"; +import { GameModes, GameMode, getGameMode } from "#app/game-mode"; +import { regenerateModifierPoolThresholds, ModifierPoolType, modifierTypes, getDailyRunStarterModifiers } from "#app/modifier/modifier-type"; +import { Phase } from "#app/phase"; +import { SessionSaveData } from "#app/system/game-data"; +import { Unlockables } from "#app/system/unlockables"; +import { vouchers } from "#app/system/voucher"; +import { OptionSelectItem, OptionSelectConfig } from "#app/ui/abstact-option-select-ui-handler"; +import { SaveSlotUiMode } from "#app/ui/save-slot-select-ui-handler"; +import { Mode } from "#app/ui/ui"; import i18next from "i18next"; -import * as Utils from "#app/utils.js"; -import { Modifier } from "#app/modifier/modifier.js"; +import * as Utils from "#app/utils"; +import { Modifier } from "#app/modifier/modifier"; import { CheckSwitchPhase } from "./check-switch-phase"; import { EncounterPhase } from "./encounter-phase"; import { SelectChallengePhase } from "./select-challenge-phase"; diff --git a/src/phases/toggle-double-position-phase.ts b/src/phases/toggle-double-position-phase.ts index fe3d0482483..563af8575d7 100644 --- a/src/phases/toggle-double-position-phase.ts +++ b/src/phases/toggle-double-position-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import { FieldPosition } from "#app/field/pokemon.js"; +import BattleScene from "#app/battle-scene"; +import { FieldPosition } from "#app/field/pokemon"; import { BattlePhase } from "./battle-phase"; export class ToggleDoublePositionPhase extends BattlePhase { diff --git a/src/phases/trainer-message-test-phase.ts b/src/phases/trainer-message-test-phase.ts index 4ea451660c3..8075dd761e2 100644 --- a/src/phases/trainer-message-test-phase.ts +++ b/src/phases/trainer-message-test-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { trainerConfigs } from "#app/data/trainer-config.js"; -import { TrainerType } from "#app/enums/trainer-type.js"; +import BattleScene from "#app/battle-scene"; +import { trainerConfigs } from "#app/data/trainer-config"; +import { TrainerType } from "#app/enums/trainer-type"; import { BattlePhase } from "./battle-phase"; import { TestMessagePhase } from "./test-message-phase"; diff --git a/src/phases/trainer-victory-phase.ts b/src/phases/trainer-victory-phase.ts index a38874c9acd..e925f0c47d4 100644 --- a/src/phases/trainer-victory-phase.ts +++ b/src/phases/trainer-victory-phase.ts @@ -1,10 +1,10 @@ -import BattleScene from "#app/battle-scene.js"; -import { getCharVariantFromDialogue } from "#app/data/dialogue.js"; -import { TrainerType } from "#app/enums/trainer-type.js"; -import { modifierTypes } from "#app/modifier/modifier-type.js"; -import { vouchers } from "#app/system/voucher.js"; +import BattleScene from "#app/battle-scene"; +import { getCharVariantFromDialogue } from "#app/data/dialogue"; +import { TrainerType } from "#app/enums/trainer-type"; +import { modifierTypes } from "#app/modifier/modifier-type"; +import { vouchers } from "#app/system/voucher"; import i18next from "i18next"; -import * as Utils from "#app/utils.js"; +import * as Utils from "#app/utils"; import { BattlePhase } from "./battle-phase"; import { ModifierRewardPhase } from "./modifier-reward-phase"; import { MoneyRewardPhase } from "./money-reward-phase"; diff --git a/src/phases/turn-end-phase.ts b/src/phases/turn-end-phase.ts index c8bd3398bb5..724a5206d74 100644 --- a/src/phases/turn-end-phase.ts +++ b/src/phases/turn-end-phase.ts @@ -1,12 +1,12 @@ -import BattleScene from "#app/battle-scene.js"; -import { applyPostTurnAbAttrs, PostTurnAbAttr } from "#app/data/ability.js"; -import { BattlerTagLapseType } from "#app/data/battler-tags.js"; -import { TerrainType } from "#app/data/terrain.js"; -import { WeatherType } from "#app/enums/weather-type.js"; -import { TurnEndEvent } from "#app/events/battle-scene.js"; -import Pokemon from "#app/field/pokemon.js"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import { TurnHealModifier, EnemyTurnHealModifier, EnemyStatusEffectHealChanceModifier, TurnStatusEffectModifier, TurnHeldItemTransferModifier } from "#app/modifier/modifier.js"; +import BattleScene from "#app/battle-scene"; +import { applyPostTurnAbAttrs, PostTurnAbAttr } from "#app/data/ability"; +import { BattlerTagLapseType } from "#app/data/battler-tags"; +import { TerrainType } from "#app/data/terrain"; +import { WeatherType } from "#app/enums/weather-type"; +import { TurnEndEvent } from "#app/events/battle-scene"; +import Pokemon from "#app/field/pokemon"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { TurnHealModifier, EnemyTurnHealModifier, EnemyStatusEffectHealChanceModifier, TurnStatusEffectModifier, TurnHeldItemTransferModifier } from "#app/modifier/modifier"; import i18next from "i18next"; import { FieldPhase } from "./field-phase"; import { PokemonHealPhase } from "./pokemon-heal-phase"; diff --git a/src/phases/turn-init-phase.ts b/src/phases/turn-init-phase.ts index a999d57ca0f..568cfdc5714 100644 --- a/src/phases/turn-init-phase.ts +++ b/src/phases/turn-init-phase.ts @@ -1,7 +1,7 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex } from "#app/battle.js"; -import { TurnInitEvent } from "#app/events/battle-scene.js"; -import { PlayerPokemon } from "#app/field/pokemon.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex } from "#app/battle"; +import { TurnInitEvent } from "#app/events/battle-scene"; +import { PlayerPokemon } from "#app/field/pokemon"; import i18next from "i18next"; import { FieldPhase } from "./field-phase"; import { ToggleDoublePositionPhase } from "./toggle-double-position-phase"; diff --git a/src/phases/unavailable-phase.ts b/src/phases/unavailable-phase.ts index 4757af5e15d..59bfca7875e 100644 --- a/src/phases/unavailable-phase.ts +++ b/src/phases/unavailable-phase.ts @@ -1,6 +1,6 @@ -import BattleScene from "#app/battle-scene.js"; -import { Phase } from "#app/phase.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { Phase } from "#app/phase"; +import { Mode } from "#app/ui/ui"; import { LoginPhase } from "./login-phase"; export class UnavailablePhase extends Phase { diff --git a/src/phases/unlock-phase.ts b/src/phases/unlock-phase.ts index 1662afaa758..65060309a6c 100644 --- a/src/phases/unlock-phase.ts +++ b/src/phases/unlock-phase.ts @@ -1,7 +1,7 @@ -import BattleScene from "#app/battle-scene.js"; -import { Phase } from "#app/phase.js"; -import { Unlockables, getUnlockableName } from "#app/system/unlockables.js"; -import { Mode } from "#app/ui/ui.js"; +import BattleScene from "#app/battle-scene"; +import { Phase } from "#app/phase"; +import { Unlockables, getUnlockableName } from "#app/system/unlockables"; +import { Mode } from "#app/ui/ui"; import i18next from "i18next"; export class UnlockPhase extends Phase { diff --git a/src/phases/victory-phase.ts b/src/phases/victory-phase.ts index b7587de4dbb..9679a79a37d 100644 --- a/src/phases/victory-phase.ts +++ b/src/phases/victory-phase.ts @@ -1,8 +1,8 @@ -import BattleScene from "#app/battle-scene.js"; -import { BattlerIndex, BattleType } from "#app/battle.js"; -import { modifierTypes } from "#app/modifier/modifier-type.js"; -import { ExpShareModifier, ExpBalanceModifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier } from "#app/modifier/modifier.js"; -import * as Utils from "#app/utils.js"; +import BattleScene from "#app/battle-scene"; +import { BattlerIndex, BattleType } from "#app/battle"; +import { modifierTypes } from "#app/modifier/modifier-type"; +import { ExpShareModifier, ExpBalanceModifier, MultipleParticipantExpBonusModifier, PokemonExpBoosterModifier } from "#app/modifier/modifier"; +import * as Utils from "#app/utils"; import Overrides from "#app/overrides"; import { BattleEndPhase } from "./battle-end-phase"; import { NewBattlePhase } from "./new-battle-phase"; diff --git a/src/phases/weather-effect-phase.ts b/src/phases/weather-effect-phase.ts index ccfc9abb64f..e85ef0326f6 100644 --- a/src/phases/weather-effect-phase.ts +++ b/src/phases/weather-effect-phase.ts @@ -2,7 +2,7 @@ import BattleScene from "#app/battle-scene"; import { applyPreWeatherEffectAbAttrs, SuppressWeatherEffectAbAttr, PreWeatherDamageAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPostWeatherLapseAbAttrs, PostWeatherLapseAbAttr } from "#app/data/ability.js"; import { CommonAnim } from "#app/data/battle-anims"; import { Weather, getWeatherDamageMessage, getWeatherLapseMessage } from "#app/data/weather"; -import { BattlerTagType } from "#app/enums/battler-tag-type.js"; +import { BattlerTagType } from "#app/enums/battler-tag-type"; import { WeatherType } from "#app/enums/weather-type"; import Pokemon, { HitResult } from "#app/field/pokemon"; import * as Utils from "#app/utils"; diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 3d24458a06c..705fd5143a4 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -2,17 +2,17 @@ import i18next from "i18next"; import LanguageDetector from "i18next-browser-languagedetector"; import processor, { KoreanPostpositionProcessor } from "i18next-korean-postposition-processor"; -import { caEsConfig} from "#app/locales/ca_ES/config.js"; -import { deConfig } from "#app/locales/de/config.js"; -import { enConfig } from "#app/locales/en/config.js"; -import { esConfig } from "#app/locales/es/config.js"; -import { frConfig } from "#app/locales/fr/config.js"; -import { itConfig } from "#app/locales/it/config.js"; -import { koConfig } from "#app/locales/ko/config.js"; -import { jaConfig } from "#app/locales/ja/config.js"; -import { ptBrConfig } from "#app/locales/pt_BR/config.js"; -import { zhCnConfig } from "#app/locales/zh_CN/config.js"; -import { zhTwConfig } from "#app/locales/zh_TW/config.js"; +import { caEsConfig} from "#app/locales/ca_ES/config"; +import { deConfig } from "#app/locales/de/config"; +import { enConfig } from "#app/locales/en/config"; +import { esConfig } from "#app/locales/es/config"; +import { frConfig } from "#app/locales/fr/config"; +import { itConfig } from "#app/locales/it/config"; +import { koConfig } from "#app/locales/ko/config"; +import { jaConfig } from "#app/locales/ja/config"; +import { ptBrConfig } from "#app/locales/pt_BR/config"; +import { zhCnConfig } from "#app/locales/zh_CN/config"; +import { zhTwConfig } from "#app/locales/zh_TW/config"; interface LoadingFontFaceProperty { face: FontFace, diff --git a/src/system/arena-data.ts b/src/system/arena-data.ts index 886129edcf6..5b907805372 100644 --- a/src/system/arena-data.ts +++ b/src/system/arena-data.ts @@ -2,7 +2,7 @@ import { Arena } from "../field/arena"; import { ArenaTag } from "../data/arena-tag"; import { Biome } from "#enums/biome"; import { Weather } from "../data/weather"; -import { Terrain } from "#app/data/terrain.js"; +import { Terrain } from "#app/data/terrain"; export default class ArenaData { public biome: Biome; diff --git a/src/system/challenge-data.ts b/src/system/challenge-data.ts index 69df11dd395..394d63867be 100644 --- a/src/system/challenge-data.ts +++ b/src/system/challenge-data.ts @@ -1,4 +1,4 @@ -import { Challenge, copyChallenge } from "#app/data/challenge.js"; +import { Challenge, copyChallenge } from "#app/data/challenge"; export default class ChallengeData { public id: integer; diff --git a/src/system/egg-data.ts b/src/system/egg-data.ts index b4bd4368bd9..785ae364efe 100644 --- a/src/system/egg-data.ts +++ b/src/system/egg-data.ts @@ -2,7 +2,7 @@ import { EggTier } from "#enums/egg-type"; import { Species } from "#enums/species"; import { VariantTier } from "#enums/variant-tiers"; import { EGG_SEED, Egg } from "../data/egg"; -import { EggSourceType } from "#app/enums/egg-source-types.js"; +import { EggSourceType } from "#app/enums/egg-source-types"; export default class EggData { public id: integer; diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 800b8baecff..677bbe4add6 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -30,20 +30,20 @@ import { TrainerVariant } from "../field/trainer"; import { Variant } from "#app/data/variant"; import {setSettingGamepad, SettingGamepad, settingGamepadDefaults} from "./settings/settings-gamepad"; import {setSettingKeyboard, SettingKeyboard} from "#app/system/settings/settings-keyboard"; -import { TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena.js"; -import { EnemyAttackStatusEffectChanceModifier } from "../modifier/modifier"; -import { StatusEffect } from "#app/data/status-effect.js"; +import { TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena"; +import * as Modifier from "../modifier/modifier"; +import { StatusEffect } from "#app/data/status-effect"; import ChallengeData from "./challenge-data"; import { Device } from "#enums/devices"; import { GameDataType } from "#enums/game-data-type"; import { Moves } from "#enums/moves"; import { PlayerGender } from "#enums/player-gender"; import { Species } from "#enums/species"; -import { applyChallenges, ChallengeType } from "#app/data/challenge.js"; -import { WeatherType } from "#app/enums/weather-type.js"; -import { TerrainType } from "#app/data/terrain.js"; -import { OutdatedPhase } from "#app/phases/outdated-phase.js"; -import { ReloadSessionPhase } from "#app/phases/reload-session-phase.js"; +import { applyChallenges, ChallengeType } from "#app/data/challenge"; +import { WeatherType } from "#app/enums/weather-type"; +import { TerrainType } from "#app/data/terrain"; +import { OutdatedPhase } from "#app/phases/outdated-phase"; +import { ReloadSessionPhase } from "#app/phases/reload-session-phase"; import { RUN_HISTORY_LIMIT } from "#app/ui/run-history-ui-handler"; import { applySessionDataPatches, applySettingsDataPatches, applySystemDataPatches } from "./version-converter"; @@ -1065,10 +1065,8 @@ export class GameData { // TODO //scene.arena.tags = sessionData.arena.tags; - const modifiersModule = await import("../modifier/modifier"); - for (const modifierData of sessionData.modifiers) { - const modifier = modifierData.toModifier(scene, modifiersModule[modifierData.className]); + const modifier = modifierData.toModifier(scene, Modifier[modifierData.className]); if (modifier) { scene.addModifier(modifier, true); } @@ -1077,7 +1075,7 @@ export class GameData { scene.updateModifiers(true); for (const enemyModifierData of sessionData.enemyModifiers) { - const modifier = enemyModifierData.toModifier(scene, modifiersModule[enemyModifierData.className]); + const modifier = enemyModifierData.toModifier(scene, Modifier[enemyModifierData.className]); if (modifier) { scene.addEnemyModifier(modifier, true); } @@ -1233,7 +1231,7 @@ export class GameData { if (md?.className === "ExpBalanceModifier") { // Temporarily limit EXP Balance until it gets reworked md.stackCount = Math.min(md.stackCount, 4); } - if (md instanceof EnemyAttackStatusEffectChanceModifier && md.effect === StatusEffect.FREEZE || md.effect === StatusEffect.SLEEP) { + if (md instanceof Modifier.EnemyAttackStatusEffectChanceModifier && md.effect === StatusEffect.FREEZE || md.effect === StatusEffect.SLEEP) { continue; } ret.push(new PersistentModifierData(md, player)); diff --git a/src/system/settings/settings.ts b/src/system/settings/settings.ts index 6b46b6fe96c..bc88c21e1e1 100644 --- a/src/system/settings/settings.ts +++ b/src/system/settings/settings.ts @@ -8,7 +8,7 @@ import SettingsUiHandler from "#app/ui/settings/settings-ui-handler"; import { EaseType } from "#enums/ease-type"; import { MoneyFormat } from "#enums/money-format"; import { PlayerGender } from "#enums/player-gender"; -import { getIsInitialized, initI18n } from "#app/plugins/i18n.js"; +import { getIsInitialized, initI18n } from "#app/plugins/i18n"; import { ShopCursorTarget } from "#app/enums/shop-cursor-target"; function getTranslation(key: string): string { diff --git a/src/system/voucher.ts b/src/system/voucher.ts index 2f94308d9c8..06edfe5c6a6 100644 --- a/src/system/voucher.ts +++ b/src/system/voucher.ts @@ -3,8 +3,8 @@ import i18next from "i18next"; import { AchvTier, achvs, getAchievementDescription } from "./achv"; import { PlayerGender } from "#enums/player-gender"; import { TrainerType } from "#enums/trainer-type"; -import { ConditionFn } from "#app/@types/common.js"; -import { trainerConfigs } from "#app/data/trainer-config.js"; +import { ConditionFn } from "#app/@types/common"; +import { trainerConfigs } from "#app/data/trainer-config"; export enum VoucherType { REGULAR, diff --git a/src/test/abilities/tera_shell.test.ts b/src/test/abilities/tera_shell.test.ts index f9cb2935619..6a6b7bb252b 100644 --- a/src/test/abilities/tera_shell.test.ts +++ b/src/test/abilities/tera_shell.test.ts @@ -1,7 +1,7 @@ import { Abilities } from "#app/enums/abilities"; import { Moves } from "#app/enums/moves"; import { Species } from "#app/enums/species"; -import { HitResult } from "#app/field/pokemon.js"; +import { HitResult } from "#app/field/pokemon"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; diff --git a/src/test/battle/damage_calculation.test.ts b/src/test/battle/damage_calculation.test.ts index 665000450be..9c7c9dc9d3e 100644 --- a/src/test/battle/damage_calculation.test.ts +++ b/src/test/battle/damage_calculation.test.ts @@ -1,4 +1,4 @@ -import { DamagePhase } from "#app/phases/damage-phase.js"; +import { DamagePhase } from "#app/phases/damage-phase"; import { toDmgValue } from "#app/utils"; import { Abilities } from "#enums/abilities"; import { ArenaTagType } from "#enums/arena-tag-type"; diff --git a/src/test/moves/gigaton_hammer.test.ts b/src/test/moves/gigaton_hammer.test.ts index 9379e9d98b2..0162375cdb2 100644 --- a/src/test/moves/gigaton_hammer.test.ts +++ b/src/test/moves/gigaton_hammer.test.ts @@ -1,4 +1,4 @@ -import { BattlerIndex } from "#app/battle.js"; +import { BattlerIndex } from "#app/battle"; import GameManager from "#app/test/utils/gameManager"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; diff --git a/src/test/moves/lunar_blessing.test.ts b/src/test/moves/lunar_blessing.test.ts index 73647716f06..92428c39029 100644 --- a/src/test/moves/lunar_blessing.test.ts +++ b/src/test/moves/lunar_blessing.test.ts @@ -1,5 +1,5 @@ -import { StatusEffect } from "#app/enums/status-effect.js"; -import { CommandPhase } from "#app/phases/command-phase.js"; +import { StatusEffect } from "#app/enums/status-effect"; +import { CommandPhase } from "#app/phases/command-phase"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; diff --git a/src/test/utils/helpers/overridesHelper.ts b/src/test/utils/helpers/overridesHelper.ts index cc5f9018325..a42ef84b496 100644 --- a/src/test/utils/helpers/overridesHelper.ts +++ b/src/test/utils/helpers/overridesHelper.ts @@ -1,12 +1,12 @@ -import { StatusEffect } from "#app/data/status-effect.js"; +import { StatusEffect } from "#app/data/status-effect"; import { Weather, WeatherType } from "#app/data/weather"; -import { Abilities } from "#app/enums/abilities.js"; +import { Abilities } from "#app/enums/abilities"; import { Biome } from "#app/enums/biome"; -import { Moves } from "#app/enums/moves.js"; -import { Species } from "#app/enums/species.js"; +import { Moves } from "#app/enums/moves"; +import { Species } from "#app/enums/species"; import * as GameMode from "#app/game-mode"; import { GameModes, getGameMode } from "#app/game-mode"; -import { ModifierOverride } from "#app/modifier/modifier-type.js"; +import { ModifierOverride } from "#app/modifier/modifier-type"; import Overrides from "#app/overrides"; import { vi } from "vitest"; import { GameManagerHelper } from "./gameManagerHelper"; diff --git a/src/test/utils/testUtils.ts b/src/test/utils/testUtils.ts index 378c3d23fde..2265cf8d79c 100644 --- a/src/test/utils/testUtils.ts +++ b/src/test/utils/testUtils.ts @@ -1,4 +1,4 @@ -import { Moves } from "#app/enums/moves.js"; +import { Moves } from "#app/enums/moves"; import i18next, { type ParseKeys } from "i18next"; import { vi } from "vitest"; diff --git a/src/ui/ability-bar.ts b/src/ui/ability-bar.ts index b8259af9f3d..a924d545852 100644 --- a/src/ui/ability-bar.ts +++ b/src/ui/ability-bar.ts @@ -1,4 +1,4 @@ -import { getPokemonNameWithAffix } from "#app/messages.js"; +import { getPokemonNameWithAffix } from "#app/messages"; import BattleScene from "../battle-scene"; import Pokemon from "../field/pokemon"; import { TextStyle, addTextObject } from "./text"; diff --git a/src/ui/admin-ui-handler.ts b/src/ui/admin-ui-handler.ts index 5c91a36ab64..c48138853fc 100644 --- a/src/ui/admin-ui-handler.ts +++ b/src/ui/admin-ui-handler.ts @@ -1,9 +1,9 @@ -import BattleScene from "#app/battle-scene.js"; +import BattleScene from "#app/battle-scene"; import { ModalConfig } from "./modal-ui-handler"; import { Mode } from "./ui"; import * as Utils from "../utils"; import { FormModalUiHandler } from "./form-modal-ui-handler"; -import { Button } from "#app/enums/buttons.js"; +import { Button } from "#app/enums/buttons"; export default class AdminUiHandler extends FormModalUiHandler { diff --git a/src/ui/arena-flyout.ts b/src/ui/arena-flyout.ts index 882c15d3d8c..42a2396e665 100644 --- a/src/ui/arena-flyout.ts +++ b/src/ui/arena-flyout.ts @@ -1,10 +1,10 @@ import { addTextObject, TextStyle } from "./text"; -import BattleScene from "#app/battle-scene.js"; -import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag.js"; -import { WeatherType } from "#app/data/weather.js"; -import { TerrainType } from "#app/data/terrain.js"; +import BattleScene from "#app/battle-scene"; +import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; +import { WeatherType } from "#app/data/weather"; +import { TerrainType } from "#app/data/terrain"; import { addWindow, WindowVariant } from "./ui-theme"; -import { ArenaEvent, ArenaEventType, TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena.js"; +import { ArenaEvent, ArenaEventType, TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena"; import { BattleSceneEventType, TurnEndEvent } from "../events/battle-scene"; import { ArenaTagType } from "#enums/arena-tag-type"; import TimeOfDayWidget from "./time-of-day-widget"; diff --git a/src/ui/ball-ui-handler.ts b/src/ui/ball-ui-handler.ts index 04691886d9c..332fe5f65b9 100644 --- a/src/ui/ball-ui-handler.ts +++ b/src/ui/ball-ui-handler.ts @@ -6,7 +6,7 @@ import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import { addWindow } from "./ui-theme"; import {Button} from "#enums/buttons"; -import { CommandPhase } from "#app/phases/command-phase.js"; +import { CommandPhase } from "#app/phases/command-phase"; export default class BallUiHandler extends UiHandler { private pokeballSelectContainer: Phaser.GameObjects.Container; diff --git a/src/ui/battle-flyout.ts b/src/ui/battle-flyout.ts index 6204fa2f928..fe561b76c9f 100644 --- a/src/ui/battle-flyout.ts +++ b/src/ui/battle-flyout.ts @@ -1,13 +1,13 @@ import { default as Pokemon } from "../field/pokemon"; import { addTextObject, TextStyle } from "./text"; import * as Utils from "../utils"; -import BattleScene from "#app/battle-scene.js"; -import Move from "#app/data/move.js"; +import BattleScene from "#app/battle-scene"; +import Move from "#app/data/move"; import { BattleSceneEventType, BerryUsedEvent, MoveUsedEvent } from "../events/battle-scene"; import { BerryType } from "#enums/berry-type"; import { Moves } from "#enums/moves"; import { UiTheme } from "#enums/ui-theme"; -import { getPokemonNameWithAffix } from "#app/messages.js"; +import { getPokemonNameWithAffix } from "#app/messages"; /** Container for info about a {@linkcode Move} */ interface MoveInfo { diff --git a/src/ui/command-ui-handler.ts b/src/ui/command-ui-handler.ts index 27ff923e9a3..764e71a8c3f 100644 --- a/src/ui/command-ui-handler.ts +++ b/src/ui/command-ui-handler.ts @@ -5,8 +5,8 @@ import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import i18next from "i18next"; import {Button} from "#enums/buttons"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import { CommandPhase } from "#app/phases/command-phase.js"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { CommandPhase } from "#app/phases/command-phase"; export enum Command { FIGHT = 0, diff --git a/src/ui/dropdown.ts b/src/ui/dropdown.ts index 08d55b03cdb..4e1235c211d 100644 --- a/src/ui/dropdown.ts +++ b/src/ui/dropdown.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene.js"; -import { SceneBase } from "#app/scene-base.js"; +import BattleScene from "#app/battle-scene"; +import { SceneBase } from "#app/scene-base"; import { addTextObject, TextStyle } from "./text"; import { addWindow, WindowVariant } from "./ui-theme"; import i18next from "i18next"; diff --git a/src/ui/egg-counter-container.ts b/src/ui/egg-counter-container.ts index a688b8b7efc..21cebf5d97e 100644 --- a/src/ui/egg-counter-container.ts +++ b/src/ui/egg-counter-container.ts @@ -1,7 +1,7 @@ -import BattleScene from "#app/battle-scene.js"; +import BattleScene from "#app/battle-scene"; import { addWindow } from "./ui-theme"; import { addTextObject, TextStyle } from "./text"; -import { EggCountChangedEvent, EggEventType } from "#app/events/egg.js"; +import { EggCountChangedEvent, EggEventType } from "#app/events/egg"; import EggHatchSceneHandler from "./egg-hatch-scene-handler"; /** diff --git a/src/ui/egg-hatch-scene-handler.ts b/src/ui/egg-hatch-scene-handler.ts index 733873b974e..7b01ef7a3a6 100644 --- a/src/ui/egg-hatch-scene-handler.ts +++ b/src/ui/egg-hatch-scene-handler.ts @@ -2,7 +2,7 @@ import BattleScene from "../battle-scene"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import {Button} from "#enums/buttons"; -import { EggHatchPhase } from "#app/phases/egg-hatch-phase.js"; +import { EggHatchPhase } from "#app/phases/egg-hatch-phase"; export default class EggHatchSceneHandler extends UiHandler { public eggHatchContainer: Phaser.GameObjects.Container; diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index 4bbe88dabd9..60db9d19eef 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -5,11 +5,11 @@ import { Command } from "./command-ui-handler"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import * as Utils from "../utils"; -import { MoveCategory } from "#app/data/move.js"; +import { MoveCategory } from "#app/data/move"; import i18next from "i18next"; import {Button} from "#enums/buttons"; -import Pokemon, { PokemonMove } from "#app/field/pokemon.js"; -import { CommandPhase } from "#app/phases/command-phase.js"; +import Pokemon, { PokemonMove } from "#app/field/pokemon"; +import { CommandPhase } from "#app/phases/command-phase"; export default class FightUiHandler extends UiHandler { public static readonly MOVES_CONTAINER_NAME = "moves"; diff --git a/src/ui/filter-bar.ts b/src/ui/filter-bar.ts index 31d7c562da2..aa0f575d398 100644 --- a/src/ui/filter-bar.ts +++ b/src/ui/filter-bar.ts @@ -1,4 +1,4 @@ -import BattleScene from "#app/battle-scene.js"; +import BattleScene from "#app/battle-scene"; import { DropDown, DropDownType } from "./dropdown"; import { StarterContainer } from "./starter-container"; import { addTextObject, getTextColor, TextStyle } from "./text"; diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index 98a19402a2b..9e025dbe086 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -15,15 +15,15 @@ import { addWindow } from "./ui-theme"; import { SpeciesFormChangeItemTrigger, FormChangeItem } from "../data/pokemon-forms"; import { getVariantTint } from "#app/data/variant"; import {Button} from "#enums/buttons"; -import { applyChallenges, ChallengeType } from "#app/data/challenge.js"; +import { applyChallenges, ChallengeType } from "#app/data/challenge"; import MoveInfoOverlay from "./move-info-overlay"; import i18next from "i18next"; import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import { getPokemonNameWithAffix } from "#app/messages.js"; -import { CommandPhase } from "#app/phases/command-phase.js"; -import { SelectModifierPhase } from "#app/phases/select-modifier-phase.js"; +import { getPokemonNameWithAffix } from "#app/messages"; +import { CommandPhase } from "#app/phases/command-phase"; +import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; const defaultMessage = i18next.t("partyUiHandler:choosePokemon"); diff --git a/src/ui/rename-form-ui-handler.ts b/src/ui/rename-form-ui-handler.ts index 33885509344..078177cafb1 100644 --- a/src/ui/rename-form-ui-handler.ts +++ b/src/ui/rename-form-ui-handler.ts @@ -1,7 +1,7 @@ import { FormModalUiHandler } from "./form-modal-ui-handler"; import { ModalConfig } from "./modal-ui-handler"; import i18next from "i18next"; -import { PlayerPokemon } from "#app/field/pokemon.js"; +import { PlayerPokemon } from "#app/field/pokemon"; export default class RenameFormUiHandler extends FormModalUiHandler { getModalTitle(config?: ModalConfig): string { diff --git a/src/ui/run-info-ui-handler.ts b/src/ui/run-info-ui-handler.ts index 7a183a11d29..d6bafb8599e 100644 --- a/src/ui/run-info-ui-handler.ts +++ b/src/ui/run-info-ui-handler.ts @@ -18,8 +18,7 @@ import { Type, getTypeRgb } from "../data/type"; import { TypeColor, TypeShadow } from "#app/enums/color"; import { getNatureStatMultiplier, getNatureName } from "../data/nature"; import { getVariantTint } from "#app/data/variant"; -import { PokemonHeldItemModifier, TerastallizeModifier } from "../modifier/modifier"; -import {modifierSortFunc} from "../modifier/modifier"; +import * as Modifier from "../modifier/modifier"; import { Species } from "#enums/species"; import { PlayerGender } from "#enums/player-gender"; @@ -68,7 +67,7 @@ export default class RunInfoUiHandler extends UiHandler { override async setup() { this.runContainer = this.scene.add.container(1, -(this.scene.game.canvas.height / 6) + 1); // The import of the modifiersModule is loaded here to sidestep async/await issues. - this.modifiersModule = await import("../modifier/modifier"); + this.modifiersModule = Modifier; this.runContainer.setVisible(false); } @@ -303,7 +302,7 @@ export default class RunInfoUiHandler extends UiHandler { const teraPokemon = {}; this.runInfo.enemyModifiers.forEach((m) => { const modifier = m.toModifier(this.scene, this.modifiersModule[m.className]); - if (modifier instanceof TerastallizeModifier) { + if (modifier instanceof Modifier.TerastallizeModifier) { const teraDetails = modifier?.getArgs(); const pkmnId = teraDetails[0]; teraPokemon[pkmnId] = teraDetails[1]; @@ -434,7 +433,7 @@ export default class RunInfoUiHandler extends UiHandler { modifierIconsContainer.setScale(0.45); for (const m of this.runInfo.modifiers) { const modifier = m.toModifier(this.scene, this.modifiersModule[m.className]); - if (modifier instanceof PokemonHeldItemModifier) { + if (modifier instanceof Modifier.PokemonHeldItemModifier) { continue; } const icon = modifier?.getIcon(this.scene, false); @@ -635,17 +634,17 @@ export default class RunInfoUiHandler extends UiHandler { // Endless/Endless Spliced have a different scale because Pokemon tend to accumulate more items in these runs. const heldItemsScale = (this.runInfo.gameMode === GameModes.SPLICED_ENDLESS || this.runInfo.gameMode === GameModes.ENDLESS) ? 0.25 : 0.5; const heldItemsContainer = this.scene.add.container(-82, 2); - const heldItemsList : PokemonHeldItemModifier[] = []; + const heldItemsList : Modifier.PokemonHeldItemModifier[] = []; if (this.runInfo.modifiers.length) { for (const m of this.runInfo.modifiers) { const modifier = m.toModifier(this.scene, this.modifiersModule[m.className]); - if (modifier instanceof PokemonHeldItemModifier && modifier.pokemonId === pokemon.id) { + if (modifier instanceof Modifier.PokemonHeldItemModifier && modifier.pokemonId === pokemon.id) { modifier.stackCount = m["stackCount"]; heldItemsList.push(modifier); } } if (heldItemsList.length > 0) { - (heldItemsList as PokemonHeldItemModifier[]).sort(modifierSortFunc); + (heldItemsList as Modifier.PokemonHeldItemModifier[]).sort(Modifier.modifierSortFunc); let row = 0; for (const [index, item] of heldItemsList.entries()) { if ( index > 36 ) { diff --git a/src/ui/save-slot-select-ui-handler.ts b/src/ui/save-slot-select-ui-handler.ts index e6ab0d3b3c3..89b20322a68 100644 --- a/src/ui/save-slot-select-ui-handler.ts +++ b/src/ui/save-slot-select-ui-handler.ts @@ -2,7 +2,7 @@ import i18next from "i18next"; import BattleScene from "../battle-scene"; import { Button } from "#enums/buttons"; import { GameMode } from "../game-mode"; -import { PokemonHeldItemModifier } from "../modifier/modifier"; +import * as Modifier from "../modifier/modifier"; import { SessionSaveData } from "../system/game-data"; import PokemonData from "../system/pokemon-data"; import * as Utils from "../utils"; @@ -306,14 +306,12 @@ class SessionSlot extends Phaser.GameObjects.Container { this.add(pokemonIconsContainer); - const modifiersModule = await import("../modifier/modifier"); - const modifierIconsContainer = this.scene.add.container(148, 30); modifierIconsContainer.setScale(0.5); let visibleModifierIndex = 0; for (const m of data.modifiers) { - const modifier = m.toModifier(this.scene, modifiersModule[m.className]); - if (modifier instanceof PokemonHeldItemModifier) { + const modifier = m.toModifier(this.scene, Modifier[m.className]); + if (modifier instanceof Modifier.PokemonHeldItemModifier) { continue; } const icon = modifier?.getIcon(this.scene, false); diff --git a/src/ui/settings/abstract-settings-ui-handler.ts b/src/ui/settings/abstract-settings-ui-handler.ts index f21f2ebcc9d..570377eab43 100644 --- a/src/ui/settings/abstract-settings-ui-handler.ts +++ b/src/ui/settings/abstract-settings-ui-handler.ts @@ -5,7 +5,7 @@ import { Mode } from "../ui"; import UiHandler from "../ui-handler"; import { addWindow } from "../ui-theme"; import {Button} from "#enums/buttons"; -import {InputsIcons} from "#app/ui/settings/abstract-control-settings-ui-handler.js"; +import {InputsIcons} from "#app/ui/settings/abstract-control-settings-ui-handler"; import NavigationMenu, {NavigationManager} from "#app/ui/settings/navigationMenu"; import { Setting, SettingKeys, SettingType } from "#app/system/settings/settings"; import i18next from "i18next"; diff --git a/src/ui/settings/move-touch-controls-handler.ts b/src/ui/settings/move-touch-controls-handler.ts index cf56bf47d3b..cff68fa523d 100644 --- a/src/ui/settings/move-touch-controls-handler.ts +++ b/src/ui/settings/move-touch-controls-handler.ts @@ -1,5 +1,5 @@ -import TouchControl from "#app/touch-controls.js"; -import UI from "#app/ui/ui.js"; +import TouchControl from "#app/touch-controls"; +import UI from "#app/ui/ui"; import { Scene } from "phaser"; export const TOUCH_CONTROL_POSITIONS_LANDSCAPE = "touchControlPositionsLandscape"; diff --git a/src/ui/settings/navigationMenu.ts b/src/ui/settings/navigationMenu.ts index 370b6f67c76..7d7761b7b69 100644 --- a/src/ui/settings/navigationMenu.ts +++ b/src/ui/settings/navigationMenu.ts @@ -1,6 +1,6 @@ import BattleScene from "#app/battle-scene"; import {Mode} from "#app/ui/ui"; -import {InputsIcons} from "#app/ui/settings/abstract-control-settings-ui-handler.js"; +import {InputsIcons} from "#app/ui/settings/abstract-control-settings-ui-handler"; import {addTextObject, setTextStyle, TextStyle} from "#app/ui/text"; import {addWindow} from "#app/ui/ui-theme"; import {Button} from "#enums/buttons"; diff --git a/src/ui/settings/settings-audio-ui-handler.ts b/src/ui/settings/settings-audio-ui-handler.ts index 4a895fc3170..86c6a9bce40 100644 --- a/src/ui/settings/settings-audio-ui-handler.ts +++ b/src/ui/settings/settings-audio-ui-handler.ts @@ -1,6 +1,6 @@ import BattleScene from "../../battle-scene"; import { Mode } from "../ui"; -"#app/inputs-controller.js"; +"#app/inputs-controller"; import AbstractSettingsUiHandler from "./abstract-settings-ui-handler"; import { SettingType } from "#app/system/settings/settings"; diff --git a/src/ui/settings/settings-display-ui-handler.ts b/src/ui/settings/settings-display-ui-handler.ts index 25dda6e9bfb..3d602c50a78 100644 --- a/src/ui/settings/settings-display-ui-handler.ts +++ b/src/ui/settings/settings-display-ui-handler.ts @@ -1,6 +1,6 @@ import BattleScene from "../../battle-scene"; import { Mode } from "../ui"; -"#app/inputs-controller.js"; +"#app/inputs-controller"; import AbstractSettingsUiHandler from "./abstract-settings-ui-handler"; import { SettingKeys, SettingType } from "#app/system/settings/settings"; diff --git a/src/ui/settings/settings-gamepad-ui-handler.ts b/src/ui/settings/settings-gamepad-ui-handler.ts index 902d7eff34e..63a9d2ab23b 100644 --- a/src/ui/settings/settings-gamepad-ui-handler.ts +++ b/src/ui/settings/settings-gamepad-ui-handler.ts @@ -12,7 +12,7 @@ import pad_xbox360 from "#app/configs/inputs/pad_xbox360"; import pad_dualshock from "#app/configs/inputs/pad_dualshock"; import pad_unlicensedSNES from "#app/configs/inputs/pad_unlicensedSNES"; import {InterfaceConfig} from "#app/inputs-controller"; -import AbstractControlSettingsUiHandler from "#app/ui/settings/abstract-control-settings-ui-handler.js"; +import AbstractControlSettingsUiHandler from "#app/ui/settings/abstract-control-settings-ui-handler"; import {Device} from "#enums/devices"; import {truncateString} from "#app/utils"; import i18next from "i18next"; diff --git a/src/ui/settings/settings-keyboard-ui-handler.ts b/src/ui/settings/settings-keyboard-ui-handler.ts index dc6de8c90dc..7e020034bc6 100644 --- a/src/ui/settings/settings-keyboard-ui-handler.ts +++ b/src/ui/settings/settings-keyboard-ui-handler.ts @@ -9,7 +9,7 @@ import { settingKeyboardOptions } from "#app/system/settings/settings-keyboard"; import {reverseValueToKeySetting, truncateString} from "#app/utils"; -import AbstractControlSettingsUiHandler from "#app/ui/settings/abstract-control-settings-ui-handler.js"; +import AbstractControlSettingsUiHandler from "#app/ui/settings/abstract-control-settings-ui-handler"; import {InterfaceConfig} from "#app/inputs-controller"; import {addTextObject, TextStyle} from "#app/ui/text"; import {deleteBind} from "#app/configs/inputs/configHandler"; diff --git a/src/ui/time-of-day-widget.ts b/src/ui/time-of-day-widget.ts index 5d2f184e679..ea80a6e524a 100644 --- a/src/ui/time-of-day-widget.ts +++ b/src/ui/time-of-day-widget.ts @@ -1,5 +1,5 @@ import * as Utils from "../utils"; -import BattleScene from "#app/battle-scene.js"; +import BattleScene from "#app/battle-scene"; import { BattleSceneEventType } from "../events/battle-scene"; import { EaseType } from "#enums/ease-type"; import { TimeOfDay } from "#enums/time-of-day"; diff --git a/src/ui/title-ui-handler.ts b/src/ui/title-ui-handler.ts index 3c25ed34d61..67a4f7260e6 100644 --- a/src/ui/title-ui-handler.ts +++ b/src/ui/title-ui-handler.ts @@ -5,7 +5,7 @@ import * as Utils from "../utils"; import { TextStyle, addTextObject, getTextStyleOptions } from "./text"; import { getBattleCountSplashMessage, getSplashMessages } from "../data/splash-messages"; import i18next from "i18next"; -import { TimedEventDisplay } from "#app/timed-event-manager.js"; +import { TimedEventDisplay } from "#app/timed-event-manager"; export default class TitleUiHandler extends OptionSelectUiHandler { private titleContainer: Phaser.GameObjects.Container; diff --git a/vite.config.ts b/vite.config.ts index 8fa7d799f27..1fd85e2572f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -10,6 +10,7 @@ export const defaultConfig: UserConfig = { clearScreen: false, appType: "mpa", build: { + chunkSizeWarningLimit: 10000, minify: 'esbuild', sourcemap: false, rollupOptions: { From df250c8b90c7ca0ebc23906689409243f4484b90 Mon Sep 17 00:00:00 2001 From: Lugiad Date: Sun, 8 Sep 2024 13:57:17 +0200 Subject: [PATCH 20/22] [Localization] New translations batch locales (Move-disabling effects, abilities triggers, error messages and some misc ajustements) (#4068) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update battle.json * Update battler-tags.json * Update battle.json * Update battle.json * Update battler-tags.json * Update battle.json * Update battler-tags.json * Update battler-tags.json * Update battle.json * Update battle.json * Update battler-tags.json * Update battler-tags.json * Update battle.json * Update battle.json * Update battler-tags.json * Update battler-tags.json * Update battle.json * Update battle.json * Update battler-tags.json * Update battle.json * Update battle.json * Update battle.json * Update battler-tags.json * Update battle.json * Update battle.json * Update src/locales/de/battle.json Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> * Update src/locales/de/battler-tags.json Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> * Update battler-tags.json * Update src/locales/ko/battle.json Co-authored-by: sodam <66295123+sodaMelon@users.noreply.github.com> * Update src/locales/ko/battler-tags.json Co-authored-by: sodam <66295123+sodaMelon@users.noreply.github.com> * Update src/locales/it/battle.json Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com> * Update src/locales/it/battler-tags.json Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com> * Update menu.json * Update ability-trigger.json * Update ability-trigger.json * Update ability-trigger.json * Update ability-trigger.json * Update ability-trigger.json * Update ability-trigger.json * Update ability-trigger.json * Update ability-trigger.json * Update menu.json * Update menu.json * Update menu.json * Update menu.json * Update menu.json * Update menu.json * Update menu.json * Update menu.json * Update src/locales/de/ability-trigger.json Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> * Update src/locales/de/ability-trigger.json Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> * Update src/locales/de/menu.json Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> * Update src/locales/ko/ability-trigger.json Co-authored-by: Leo Kim <47556641+KimJeongSun@users.noreply.github.com> * Update src/locales/ko/menu.json Co-authored-by: Leo Kim <47556641+KimJeongSun@users.noreply.github.com> * Update src/locales/ko/ability-trigger.json Co-authored-by: Leo Kim <47556641+KimJeongSun@users.noreply.github.com> * Update src/locales/ko/menu.json Co-authored-by: Leo Kim <47556641+KimJeongSun@users.noreply.github.com> * Update menu.json * Update ability-trigger.json * Update ability-trigger.json * Update ability-trigger.json * Update ability-trigger.json * Update ability-trigger.json * Update ability-trigger.json * Update menu.json * Update ability-trigger.json * Update battle.json * Update battler-tags.json * Update src/locales/zh_CN/battle.json Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com> * Update src/locales/zh_TW/battle.json Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com> * Update modifier-type.json * Update modifier-type.json * Update modifier-type.json * Update modifier-type.json * Update modifier-type.json * Update modifier-type.json * Update modifier-type.json * Update modifier-type.json * Update modifier-type.json * Update modifier-type.json * Update modifier-type.json * Update menu.json * Update battler-tags.json * Update battle.json * Update ability-trigger.json * Update battler-tags.json * Update battler-tags.json * Update battler-tags.json * Update battler-tags.json * Update modifier-type.json * Update menu.json * Update battle.json * Update tutorial.json * Update tutorial.json * Update egg.json * Update battle.json * Update battle.json * Update tutorial.json * Update egg.json * Update modifier-type.json * Update modifier-type.json * Update modifier-type.json * Update modifier-type.json * Update modifier-type.json * Update challenges.json * Update src/locales/ko/modifier-type.json Co-authored-by: Enoch * Update src/locales/ko/modifier-type.json Co-authored-by: Enoch * Update src/locales/ja/battle.json Co-authored-by: Chapybara-jp * Update src/locales/ja/menu.json Co-authored-by: Chapybara-jp * Update src/locales/ja/modifier-type.json Co-authored-by: Chapybara-jp * Update src/locales/ja/modifier-type.json Co-authored-by: Chapybara-jp * Update src/locales/ja/modifier-type.json Co-authored-by: Chapybara-jp * Update dialogue.json * Update dialogue-misc.json * Update dialogue-final-boss.json * Update dialogue-double-battle.json * Update ability-trigger.json * Update achv.json * Update arena-tag.json * Update battle.json * Update battler-tags.json * Update command-ui-handler.json * Update menu.json * Update modifier-type.json * Update modifier.json * Update move-trigger.json * Update pokemon-info-container.json * Update pokemon-info.json * Update splash-messages.json * Update status-effect.json * Update tutorial.json * Update voucher.json * Update weather.json * Update ability-trigger.json * Update src/locales/de/modifier-type.json Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> * Update src/locales/de/modifier-type.json Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> * Update modifier-type.json * Update bgm-name.json * Update bgm-name.json * Update src/locales/it/menu.json Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com> * types_ja.png update * Apply suggestions from code review Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com> --------- Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com> Co-authored-by: sodam <66295123+sodaMelon@users.noreply.github.com> Co-authored-by: Niccolò <123510358+NicusPulcis@users.noreply.github.com> Co-authored-by: Leo Kim <47556641+KimJeongSun@users.noreply.github.com> Co-authored-by: Yonmaru40 <47717431+40chyan@users.noreply.github.com> Co-authored-by: Enoch Co-authored-by: Chapybara-jp --- public/images/types_ja.png | Bin 9300 -> 7057 bytes src/locales/de/ability-trigger.json | 4 +- src/locales/de/battle.json | 3 +- src/locales/de/battler-tags.json | 6 +- src/locales/de/menu.json | 6 +- src/locales/de/modifier-type.json | 8 +- src/locales/en/ability-trigger.json | 4 +- src/locales/en/challenges.json | 4 +- src/locales/es/ability-trigger.json | 2 + src/locales/es/battle.json | 3 +- src/locales/es/battler-tags.json | 4 +- src/locales/es/menu.json | 4 +- src/locales/es/modifier-type.json | 8 +- src/locales/fr/ability-trigger.json | 18 +-- src/locales/fr/achv.json | 4 +- src/locales/fr/arena-tag.json | 2 +- src/locales/fr/battle.json | 117 +++++++++--------- src/locales/fr/battler-tags.json | 32 ++--- src/locales/fr/command-ui-handler.json | 4 +- src/locales/fr/dialogue-double-battle.json | 42 +++---- src/locales/fr/dialogue-final-boss.json | 6 +- src/locales/fr/dialogue-misc.json | 6 +- src/locales/fr/dialogue.json | 132 ++++++++++----------- src/locales/fr/egg.json | 4 +- src/locales/fr/menu.json | 26 ++-- src/locales/fr/modifier-type.json | 24 ++-- src/locales/fr/modifier.json | 2 +- src/locales/fr/move-trigger.json | 16 +-- src/locales/fr/pokemon-info-container.json | 8 +- src/locales/fr/pokemon-info.json | 4 +- src/locales/fr/splash-messages.json | 66 +++++------ src/locales/fr/status-effect.json | 4 +- src/locales/fr/tutorial.json | 18 +-- src/locales/fr/voucher.json | 10 +- src/locales/fr/weather.json | 54 ++++----- src/locales/it/ability-trigger.json | 4 +- src/locales/it/battle.json | 3 +- src/locales/it/battler-tags.json | 6 +- src/locales/it/menu.json | 6 +- src/locales/it/modifier-type.json | 8 +- src/locales/ja/ability-trigger.json | 4 +- src/locales/ja/battle.json | 3 +- src/locales/ja/battler-tags.json | 4 +- src/locales/ja/menu.json | 4 +- src/locales/ja/modifier-type.json | 8 +- src/locales/ko/ability-trigger.json | 4 +- src/locales/ko/battle.json | 3 +- src/locales/ko/battler-tags.json | 6 +- src/locales/ko/menu.json | 4 +- src/locales/ko/modifier-type.json | 8 +- src/locales/pt_BR/battle.json | 2 +- src/locales/pt_BR/battler-tags.json | 2 +- src/locales/pt_BR/modifier-type.json | 8 +- src/locales/zh_CN/ability-trigger.json | 4 +- src/locales/zh_CN/battle.json | 3 +- src/locales/zh_CN/battler-tags.json | 6 +- src/locales/zh_CN/menu.json | 6 +- src/locales/zh_CN/modifier-type.json | 8 +- src/locales/zh_TW/ability-trigger.json | 4 +- src/locales/zh_TW/battle.json | 3 +- src/locales/zh_TW/battler-tags.json | 6 +- src/locales/zh_TW/menu.json | 6 +- src/locales/zh_TW/modifier-type.json | 8 +- 63 files changed, 444 insertions(+), 352 deletions(-) diff --git a/public/images/types_ja.png b/public/images/types_ja.png index e60d8e071aa42c3ae09c7ae30937704d465606a0..a6f3b00607f6eaa8c3a4f88cf54bc4f14fbd6710 100644 GIT binary patch delta 4764 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 YXO}q%hF2Z^R{rltSIYofpke9vKl Date: Sun, 8 Sep 2024 20:48:09 -0700 Subject: [PATCH 21/22] [Bug] Fix incorrect defensive properties on Terastallized Pokemon (#4070) * Fix incorrect defensive properties on Terastallized Pokemon * Add tests to `effectiveness.test.ts` * Suppress errors from Tera achievement validation --- src/field/pokemon.ts | 5 +++- src/test/moves/effectiveness.test.ts | 39 +++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 863b0f41d2c..6d29e30254a 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1049,6 +1049,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const teraType = this.getTeraType(); if (teraType !== Type.UNKNOWN) { types.push(teraType); + if (forDefend) { + return types; + } } } @@ -1368,7 +1371,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { : 1); applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier); - if (this.getTypes().find(t => move.isTypeImmune(source, this, t))) { + if (this.getTypes(true, true).find(t => move.isTypeImmune(source, this, t))) { typeMultiplier.value = 0; } diff --git a/src/test/moves/effectiveness.test.ts b/src/test/moves/effectiveness.test.ts index af44586b69d..d1903c79844 100644 --- a/src/test/moves/effectiveness.test.ts +++ b/src/test/moves/effectiveness.test.ts @@ -1,23 +1,32 @@ import { allMoves } from "#app/data/move"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { TrainerSlot } from "#app/data/trainer-config"; +import { Type } from "#app/data/type"; import { Abilities } from "#app/enums/abilities"; import { Moves } from "#app/enums/moves"; import { Species } from "#app/enums/species"; import * as Messages from "#app/messages"; +import { TerastallizeModifier } from "#app/modifier/modifier"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, describe, expect, it, vi } from "vitest"; function testMoveEffectiveness(game: GameManager, move: Moves, targetSpecies: Species, - expected: number, targetAbility: Abilities = Abilities.BALL_FETCH): void { + expected: number, targetAbility: Abilities = Abilities.BALL_FETCH, teraType?: Type): void { // Suppress getPokemonNameWithAffix because it calls on a null battle spec vi.spyOn(Messages, "getPokemonNameWithAffix").mockReturnValue(""); game.override.enemyAbility(targetAbility); + + if (teraType !== undefined) { + game.override.enemyHeldItems([{ name:"TERA_SHARD", type: teraType }]); + } + const user = game.scene.addPlayerPokemon(getPokemonSpecies(Species.SNORLAX), 5); const target = game.scene.addEnemyPokemon(getPokemonSpecies(targetSpecies), 5, TrainerSlot.NONE); expect(target.getMoveEffectiveness(user, allMoves[move])).toBe(expected); + user.destroy(); + target.destroy(); } describe("Moves - Type Effectiveness", () => { @@ -29,6 +38,8 @@ describe("Moves - Type Effectiveness", () => { type: Phaser.HEADLESS, }); game = new GameManager(phaserGame); + TerastallizeModifier.prototype.apply = (args) => true; + game.override.ability(Abilities.BALL_FETCH); }); @@ -67,4 +78,30 @@ describe("Moves - Type Effectiveness", () => { it("Electric-type attacks are negated by Volt Absorb", () => testMoveEffectiveness(game, Moves.THUNDERBOLT, Species.GYARADOS, 0, Abilities.VOLT_ABSORB) ); + + it("Electric-type attacks are super-effective against Tera-Water Pokemon", + () => testMoveEffectiveness(game, Moves.THUNDERBOLT, Species.EXCADRILL, 2, Abilities.BALL_FETCH, Type.WATER) + ); + + it("Powder moves have no effect on Grass-type Pokemon", + () => testMoveEffectiveness(game, Moves.SLEEP_POWDER, Species.AMOONGUSS, 0) + ); + + it("Powder moves have no effect on Tera-Grass Pokemon", + () => testMoveEffectiveness(game, Moves.SLEEP_POWDER, Species.SNORLAX, 0, Abilities.BALL_FETCH, Type.GRASS) + ); + + it("Prankster-boosted status moves have no effect on Dark-type Pokemon", + () => { + game.override.ability(Abilities.PRANKSTER); + testMoveEffectiveness(game, Moves.BABY_DOLL_EYES, Species.MIGHTYENA, 0); + } + ); + + it("Prankster-boosted status moves have no effect on Tera-Dark Pokemon", + () => { + game.override.ability(Abilities.PRANKSTER); + testMoveEffectiveness(game, Moves.BABY_DOLL_EYES, Species.SNORLAX, 0, Abilities.BALL_FETCH, Type.DARK); + } + ); }); From 06f98f6737ba959f2894c1dc48fbdac7e3ecf5ed Mon Sep 17 00:00:00 2001 From: "Adrian T." <68144167+torranx@users.noreply.github.com> Date: Mon, 9 Sep 2024 11:50:47 +0800 Subject: [PATCH 22/22] [Bug] Fix console error from undefined stockpilingTag (#4118) --- src/data/move.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 19014c0eb30..e6e7f574671 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3472,7 +3472,7 @@ export class SpitUpPowerAttr extends VariablePowerAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const stockpilingTag = user.getTag(StockpilingTag); - if (stockpilingTag !== null && stockpilingTag.stockpiledCount > 0) { + if (stockpilingTag && stockpilingTag.stockpiledCount > 0) { const power = args[0] as Utils.IntegerHolder; power.value = this.multiplier * stockpilingTag.stockpiledCount; return true; @@ -3490,7 +3490,7 @@ export class SwallowHealAttr extends HealAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const stockpilingTag = user.getTag(StockpilingTag); - if (stockpilingTag !== null && stockpilingTag?.stockpiledCount > 0) { + if (stockpilingTag && stockpilingTag.stockpiledCount > 0) { const stockpiled = stockpilingTag.stockpiledCount; let healRatio: number;