Compare commits

..

No commits in common. "a97803b99b53ae2bec104571fa3e63e70a21824c" and "c40717fd33f57575a6c49cb9f1931776e41f2240" have entirely different histories.

23 changed files with 815 additions and 1006 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 800 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 793 B

After

Width:  |  Height:  |  Size: 743 B

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -1,21 +1,5 @@
{
"1": {
"b0a080": "d96b23",
"f8f8e8": "ffe1b8",
"9b8259": "b43c06",
"e5e4c2": "ffbf79",
"000000": "000000",
"bc9b4e": "8e0021",
"f8f8d0": "ff7e75",
"e8e088": "ee2033",
"d0b868": "bc0125",
"7d673b": "770031",
"282828": "282828",
"f84040": "f84040",
"f88888": "f88888",
"c81010": "c81010"
},
"2": {
"b0a080": "e552ec",
"f8f8e8": "ffe2ed",
"9b8259": "b021c5",
@ -30,5 +14,21 @@
"f84040": "f84040",
"f88888": "1ae2e6",
"c81010": "00c2d2"
},
"2": {
"b0a080": "d96b23",
"f8f8e8": "ffe1b8",
"9b8259": "b43c06",
"e5e4c2": "ffbf79",
"000000": "000000",
"bc9b4e": "8e0021",
"f8f8d0": "ff7e75",
"e8e088": "ee2033",
"d0b868": "bc0125",
"7d673b": "770031",
"282828": "282828",
"f84040": "f84040",
"f88888": "f88888",
"c81010": "c81010"
}
}

View File

@ -2419,14 +2419,9 @@ export default class BattleScene extends SceneBase {
count = Math.max(count, Math.floor(chances / 2));
}
getEnemyModifierTypesForWave(difficultyWaveIndex, count, [ enemyPokemon ], this.currentBattle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD, upgradeChance)
.map(mt => {
const enemyModifier = mt.newModifier(enemyPokemon);
if (enemyModifier instanceof TurnHeldItemTransferModifier) {
enemyModifier.setTransferrableFalse();
}
enemyModifier.add(this.enemyModifiers, false, this);
});
.map(mt => mt.newModifier(enemyPokemon).add(this.enemyModifiers, false, this));
});
this.updateModifiers(false).then(() => resolve());
});
}

View File

@ -921,7 +921,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* by how many learnable moves there are for the {@linkcode Pokemon}.
*/
getLearnableLevelMoves(): Moves[] {
let levelMoves = this.getLevelMoves(1, true, false, true).map(lm => lm[1]);
let levelMoves = this.getLevelMoves(1, true).map(lm => lm[1]);
if (this.metBiome === -1 && !this.scene.gameMode.isFreshStartChallenge() && !this.scene.gameMode.isDaily) {
levelMoves = this.getUnlockedEggMoves().concat(levelMoves);
}
@ -1210,11 +1210,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
*
* @param source - The Pokémon using the move.
* @param move - The move being used.
* @returns The type damage multiplier or 1 if it's a status move
* @returns The type damage multiplier or undefined if it's a status move
*/
getMoveEffectiveness(source: Pokemon, move: PokemonMove): TypeDamageMultiplier {
getMoveEffectiveness(source: Pokemon, move: PokemonMove): TypeDamageMultiplier | undefined {
if (move.getMove().category === MoveCategory.STATUS) {
return 1;
return undefined;
}
return this.getAttackMoveEffectiveness(source, move, !this.battleData?.abilityRevealed);

View File

@ -4033,24 +4033,13 @@ export class FaintPhase extends PokemonPhase {
}
if (this.player) {
/** The total number of Pokemon in the player's party that can legally fight */
const legalPlayerPokemon = this.scene.getParty().filter(p => p.isAllowedInBattle());
/** The total number of legal player Pokemon that aren't currently on the field */
const legalPlayerPartyPokemon = legalPlayerPokemon.filter(p => !p.isActive(true));
if (!legalPlayerPokemon.length) {
/** If the player doesn't have any legal Pokemon, end the game */
const nonFaintedLegalPartyMembers = this.scene.getParty().filter(p => p.isAllowedInBattle());
const nonFaintedPartyMemberCount = nonFaintedLegalPartyMembers.length;
if (!nonFaintedPartyMemberCount) {
this.scene.unshiftPhase(new GameOverPhase(this.scene));
} else if (this.scene.currentBattle.double && legalPlayerPokemon.length === 1 && legalPlayerPartyPokemon.length === 0) {
/**
* If the player has exactly one Pokemon in total at this point in a double battle, and that Pokemon
* is already on the field, unshift a phase that moves that Pokemon to center position.
*/
} else if (nonFaintedPartyMemberCount === 1 && this.scene.currentBattle.double) {
this.scene.unshiftPhase(new ToggleDoublePositionPhase(this.scene, true));
} else if (legalPlayerPartyPokemon.length > 0) {
/**
* If previous conditions weren't met, and the player has at least 1 legal Pokemon off the field,
* push a phase that prompts the player to summon a Pokemon from their party.
*/
} else if (nonFaintedPartyMemberCount >= this.scene.currentBattle.getBattlerCount()) {
this.scene.pushPhase(new SwitchPhase(this.scene, this.fieldIndex, true, false));
}
} else {

View File

@ -12,7 +12,6 @@ import { SPLASH_ONLY } from "#test/utils/testUtils";
describe("Moves - Rollout", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
const TIMEOUT = 20 * 1000;
beforeAll(() => {
phaserGame = new Phaser.Game({
@ -78,5 +77,5 @@ describe("Moves - Rollout", () => {
// reset
expect(turn6Dmg).toBeGreaterThanOrEqual(turn1Dmg - variance);
expect(turn6Dmg).toBeLessThanOrEqual(turn1Dmg + variance);
}, TIMEOUT);
});
});

View File

@ -87,6 +87,7 @@ describe("UI - Transfer Items", () => {
handler.processInput(Button.ACTION); // select Pokemon
expect(handler.optionsContainer.list.some((option) => (option as BBCodeText).text?.includes("Transfer"))).toBe(true);
game.phaseInterceptor.unlock();
});

View File

@ -1,89 +0,0 @@
import { Button } from "#app/enums/buttons.js";
import { Moves } from "#app/enums/moves";
import { Species } from "#app/enums/species";
import { CommandPhase } from "#app/phases";
import FightUiHandler from "#app/ui/fight-ui-handler.js";
import { Mode } from "#app/ui/ui.js";
import GameManager from "#test/utils/gameManager";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
import MockText from "../utils/mocks/mocksContainer/mockText";
import { SPLASH_ONLY } from "../utils/testUtils";
describe("UI - Type Hints", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
});
beforeEach(async () => {
game = new GameManager(phaserGame);
game.settings.typeHints(true); //activate type hints
game.override.battleType("single").startingLevel(100).startingWave(1).enemyMoveset(SPLASH_ONLY);
});
it("check immunity color", async () => {
game.override
.battleType("single")
.startingLevel(100)
.startingWave(1)
.enemySpecies(Species.FLORGES)
.enemyMoveset(SPLASH_ONLY)
.moveset([Moves.DRAGON_CLAW]);
game.settings.typeHints(true); //activate type hints
await game.startBattle([Species.RAYQUAZA]);
game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
const { ui } = game.scene;
const handler = ui.getHandler<FightUiHandler>();
handler.processInput(Button.ACTION); // select "Fight"
game.phaseInterceptor.unlock();
});
game.onNextPrompt("CommandPhase", Mode.FIGHT, () => {
const { ui } = game.scene;
const movesContainer = ui.getByName<Phaser.GameObjects.Container>(FightUiHandler.MOVES_CONTAINER_NAME);
const dragonClawText = movesContainer
.getAll<Phaser.GameObjects.Text>()
.find((text) => text.text === "Dragon Claw")! as unknown as MockText;
expect.soft(dragonClawText.color).toBe("#929292");
ui.getHandler().processInput(Button.ACTION);
});
await game.phaseInterceptor.to(CommandPhase);
});
it("check status move color", async () => {
game.override.enemySpecies(Species.FLORGES).moveset([Moves.GROWL]);
await game.startBattle([Species.RAYQUAZA]);
game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
const { ui } = game.scene;
const handler = ui.getHandler<FightUiHandler>();
handler.processInput(Button.ACTION); // select "Fight"
game.phaseInterceptor.unlock();
});
game.onNextPrompt("CommandPhase", Mode.FIGHT, () => {
const { ui } = game.scene;
const movesContainer = ui.getByName<Phaser.GameObjects.Container>(FightUiHandler.MOVES_CONTAINER_NAME);
const growlText = movesContainer
.getAll<Phaser.GameObjects.Text>()
.find((text) => text.text === "Growl")! as unknown as MockText;
expect.soft(growlText.color).toBe(undefined);
ui.getHandler().processInput(Button.ACTION);
});
await game.phaseInterceptor.to(CommandPhase);
});
});

View File

@ -30,7 +30,6 @@ import { MoveHelper } from "./helpers/moveHelper";
import { vi } from "vitest";
import { ClassicModeHelper } from "./helpers/classicModeHelper";
import { DailyModeHelper } from "./helpers/dailyModeHelper";
import { SettingsHelper } from "./helpers/settingsHelper";
/**
* Class to manage the game state and transitions between phases.
@ -45,7 +44,6 @@ export default class GameManager {
public readonly move: MoveHelper;
public readonly classicMode: ClassicModeHelper;
public readonly dailyMode: DailyModeHelper;
public readonly settings: SettingsHelper;
/**
* Creates an instance of GameManager.
@ -65,7 +63,6 @@ export default class GameManager {
this.move = new MoveHelper(this);
this.classicMode = new ClassicModeHelper(this);
this.dailyMode = new DailyModeHelper(this);
this.settings = new SettingsHelper(this);
}
/**

View File

@ -1,15 +0,0 @@
import { GameManagerHelper } from "./gameManagerHelper";
/**
* Helper to handle settings for tests
*/
export class SettingsHelper extends GameManagerHelper {
/**
* Disable/Enable type hints settings
* @param enable true to enabled, false to disabled
*/
typeHints(enable: boolean) {
this.game.scene.typeHints = enable;
}
}

View File

@ -1,5 +1,4 @@
import MockTextureManager from "#test/utils/mocks/mockTextureManager";
import { vi } from "vitest";
import { MockGameObject } from "../mockGameObject";
export default class MockContainer implements MockGameObject {
@ -14,7 +13,6 @@ export default class MockContainer implements MockGameObject {
public frame;
protected textureManager;
public list: MockGameObject[] = [];
private name?: string;
constructor(textureManager: MockTextureManager, x, y) {
this.x = x;
@ -161,10 +159,9 @@ export default class MockContainer implements MockGameObject {
// Moves this Game Object to be below the given Game Object in the display list.
}
setName = vi.fn((name: string) => {
this.name = name;
setName(name) {
// return this.phaserSprite.setName(name);
});
}
bringToTop(obj) {
// Brings this Game Object to the top of its parents display list.

View File

@ -1,5 +1,4 @@
import UI from "#app/ui/ui";
import { vi } from "vitest";
import { MockGameObject } from "../mockGameObject";
export default class MockText implements MockGameObject {
@ -11,8 +10,6 @@ export default class MockText implements MockGameObject {
public list: MockGameObject[] = [];
public style;
public text = "";
private name?: string;
public color?: string;
constructor(textureManager, x, y, content, styleOptions) {
this.scene = textureManager.scene;
@ -193,9 +190,10 @@ export default class MockText implements MockGameObject {
};
}
setColor = vi.fn((color: string) => {
this.color = color;
});
setColor(color) {
// Sets the tint of this Game Object.
// return this.phaserText.setColor(color);
}
setShadowColor(color) {
// Sets the shadow color.
@ -221,9 +219,9 @@ export default class MockText implements MockGameObject {
// return this.phaserText.setAlpha(alpha);
}
setName = vi.fn((name: string) => {
this.name = name;
});
setName(name) {
// return this.phaserText.setName(name);
}
setAlign(align) {
// return this.phaserText.setAlign(align);

View File

@ -226,7 +226,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
highestIv = ivs[s];
}
});
if (shownStat !== null && shownStat !== undefined) {
if (shownStat) {
shownStats.push(shownStat);
statsPool.splice(statsPool.indexOf(shownStat), 1);
}

View File

@ -12,8 +12,6 @@ import {Button} from "#enums/buttons";
import Pokemon, { PokemonMove } from "#app/field/pokemon.js";
export default class FightUiHandler extends UiHandler {
public static readonly MOVES_CONTAINER_NAME = "moves";
private movesContainer: Phaser.GameObjects.Container;
private moveInfoContainer: Phaser.GameObjects.Container;
private typeIcon: Phaser.GameObjects.Sprite;
@ -37,7 +35,7 @@ export default class FightUiHandler extends UiHandler {
const ui = this.getUi();
this.movesContainer = this.scene.add.container(18, -38.7);
this.movesContainer.setName(FightUiHandler.MOVES_CONTAINER_NAME);
this.movesContainer.setName("moves");
ui.add(this.movesContainer);
this.moveInfoContainer = this.scene.add.container(1, 0);
@ -273,10 +271,11 @@ export default class FightUiHandler extends UiHandler {
return undefined;
}
const moveColors = opponents
.map((opponent) => opponent.getMoveEffectiveness(pokemon, pokemonMove))
.sort((a, b) => b - a)
.map((effectiveness) => getTypeDamageMultiplierColor(effectiveness ?? 0, "offense"));
const moveColors = opponents.map((opponent) => {
return opponent.getMoveEffectiveness(pokemon, pokemonMove);
}).filter((eff) => !!eff).sort((a, b) => b - a).map((effectiveness) => {
return getTypeDamageMultiplierColor(effectiveness, "offense");
});
return moveColors[0];
}