Skip to content

Commit

Permalink
Merge branch 'aj-main' of https://github.com/ajhyperbit/pokerogue int…
Browse files Browse the repository at this point in the history
…o aj-main
  • Loading branch information
ajhyperbit committed Aug 19, 2024
2 parents aaf1360 + 2b4eeb6 commit e0f572a
Show file tree
Hide file tree
Showing 26 changed files with 678 additions and 424 deletions.
Binary file modified public/images/pokemon/867.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/images/pokemon/back/867.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/images/pokemon/back/shiny/867.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
818 changes: 440 additions & 378 deletions public/images/pokemon/exp/867.json

Large diffs are not rendered by default.

Binary file modified public/images/pokemon/exp/867.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/images/pokemon/exp/back/867.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/images/pokemon/exp/back/shiny/867.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/images/pokemon/shiny/867.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/images/pokemon/variant/back/female/178_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/images/pokemon/variant/back/female/178_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 16 additions & 16 deletions public/images/pokemon/variant/exp/800-ultra.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
{
"1": {
"b0a080": "e552ec",
"f8f8e8": "ffe2ed",
"9b8259": "b021c5",
"e5e4c2": "ffb9f9",
"000000": "000000",
"bc9b4e": "900090",
"f8f8d0": "ff8ae9",
"e8e088": "ff49e7",
"d0b868": "d10cc7",
"7d673b": "510059",
"282828": "282828",
"f84040": "f84040",
"f88888": "1ae2e6",
"c81010": "00c2d2"
},
"2": {
"b0a080": "d96b23",
"f8f8e8": "ffe1b8",
"9b8259": "b43c06",
Expand All @@ -30,5 +14,21 @@
"f84040": "f84040",
"f88888": "f88888",
"c81010": "c81010"
},
"2": {
"b0a080": "e552ec",
"f8f8e8": "ffe2ed",
"9b8259": "b021c5",
"e5e4c2": "ffb9f9",
"000000": "000000",
"bc9b4e": "900090",
"f8f8d0": "ff8ae9",
"e8e088": "ff49e7",
"d0b868": "d10cc7",
"7d673b": "510059",
"282828": "282828",
"f84040": "f84040",
"f88888": "1ae2e6",
"c81010": "00c2d2"
}
}
1 change: 0 additions & 1 deletion src/battle-scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2430,7 +2430,6 @@ export default class BattleScene extends SceneBase {
getEnemyModifierTypesForWave(difficultyWaveIndex, count, [ enemyPokemon ], this.currentBattle.battleType === BattleType.TRAINER ? ModifierPoolType.TRAINER : ModifierPoolType.WILD, upgradeChance)
.map(mt => mt.newModifier(enemyPokemon).add(this.enemyModifiers, false, this));
});

this.updateModifiers(false).then(() => resolve());
});
}
Expand Down
6 changes: 3 additions & 3 deletions src/data/ability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2395,16 +2395,16 @@ export class PreStatChangeAbAttr extends AbAttr {
}

export class ProtectStatAbAttr extends PreStatChangeAbAttr {
private protectedStat: BattleStat | null;
private protectedStat?: BattleStat;

constructor(protectedStat?: BattleStat) {
super();

this.protectedStat = protectedStat ?? null;
this.protectedStat = protectedStat;
}

applyPreStatChange(pokemon: Pokemon, passive: boolean, stat: BattleStat, cancelled: Utils.BooleanHolder, args: any[]): boolean {
if (!this.protectedStat || stat === this.protectedStat) {
if (Utils.isNullOrUndefined(this.protectedStat) || stat === this.protectedStat) {
cancelled.value = true;
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/data/move.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4441,7 +4441,7 @@ export class CurseAttr extends MoveEffectAttr {
const curseRecoilDamage = Math.max(1, Math.floor(user.getMaxHp() / 2));
user.damageAndUpdate(curseRecoilDamage, HitResult.OTHER, false, true, true);
user.scene.queueMessage(
i18next.t("battle:cursedOnAdd", {
i18next.t("battlerTags:cursedOnAdd", {
pokemonNameWithAffix: getPokemonNameWithAffix(user),
pokemonName: getPokemonNameWithAffix(target)
})
Expand Down
6 changes: 3 additions & 3 deletions src/field/pokemon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 undefined if it's a status move
* @returns The type damage multiplier or 1 if it's a status move
*/
getMoveEffectiveness(source: Pokemon, move: PokemonMove): TypeDamageMultiplier | undefined {
getMoveEffectiveness(source: Pokemon, move: PokemonMove): TypeDamageMultiplier {
if (move.getMove().category === MoveCategory.STATUS) {
return undefined;
return 1;
}

return this.getAttackMoveEffectiveness(source, move, !this.battleData?.abilityRevealed);
Expand Down
2 changes: 1 addition & 1 deletion src/modifier/modifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2414,7 +2414,7 @@ export class ContactHeldItemTransferChanceModifier extends HeldItemTransferModif
}

getTransferMessage(pokemon: Pokemon, targetPokemon: Pokemon, item: ModifierTypes.ModifierType): string {
return i18next.t("modifier:contactHeldItemTransferApply", { pokemonNameWithAffix: getPokemonNameWithAffix(targetPokemon), itemName: item.name, pokemonName: pokemon.name, typeName: this.type.name });
return i18next.t("modifier:contactHeldItemTransferApply", { pokemonNameWithAffix: getPokemonNameWithAffix(targetPokemon), itemName: item.name, pokemonName: getPokemonNameWithAffix(pokemon), typeName: this.type.name });
}

getMaxHeldItemCount(pokemon: Pokemon): integer {
Expand Down
25 changes: 20 additions & 5 deletions src/phases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,10 @@ export class EncounterPhase extends BattlePhase {
} else if (!(battle.waveIndex % 1000)) {
enemyPokemon.formIndex = 1;
enemyPokemon.updateScale();
const bossMBH = this.scene.findModifier(m => m instanceof TurnHeldItemTransferModifier && m.pokemonId === enemyPokemon.id, false) as TurnHeldItemTransferModifier;
this.scene.removeModifier(bossMBH!);
bossMBH?.setTransferrableFalse();
this.scene.addEnemyModifier(bossMBH!);
}
}

Expand Down Expand Up @@ -4033,13 +4037,24 @@ export class FaintPhase extends PokemonPhase {
}

if (this.player) {
const nonFaintedLegalPartyMembers = this.scene.getParty().filter(p => p.isAllowedInBattle());
const nonFaintedPartyMemberCount = nonFaintedLegalPartyMembers.length;
if (!nonFaintedPartyMemberCount) {
/** 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 */
this.scene.unshiftPhase(new GameOverPhase(this.scene));
} else if (nonFaintedPartyMemberCount === 1 && this.scene.currentBattle.double) {
} 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.
*/
this.scene.unshiftPhase(new ToggleDoublePositionPhase(this.scene, true));
} else if (nonFaintedPartyMemberCount >= this.scene.currentBattle.getBattlerCount()) {
} 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.
*/
this.scene.pushPhase(new SwitchPhase(this.scene, this.fieldIndex, true, false));
}
} else {
Expand Down
58 changes: 58 additions & 0 deletions src/test/abilities/hyper_cutter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { BattleStat } from "#app/data/battle-stat";
import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import GameManager from "#test/utils/gameManager";
import { getMovePosition } from "#test/utils/gameManagerUtils";
import { SPLASH_ONLY } from "#test/utils/testUtils";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";

describe("Abilities - Hyper Cutter", () => {
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
.battleType("single")
.moveset([Moves.SAND_ATTACK, Moves.NOBLE_ROAR, Moves.DEFOG, Moves.OCTOLOCK])
.ability(Abilities.BALL_FETCH)
.enemySpecies(Species.SHUCKLE)
.enemyAbility(Abilities.HYPER_CUTTER)
.enemyMoveset(SPLASH_ONLY);
});

// Reference Link: https://bulbapedia.bulbagarden.net/wiki/Hyper_Cutter_(Ability)

it("only prevents ATK drops", async () => {
await game.startBattle();

const enemy = game.scene.getEnemyPokemon()!;

game.doAttack(getMovePosition(game.scene, 0, Moves.OCTOLOCK));
await game.toNextTurn();
game.doAttack(getMovePosition(game.scene, 0, Moves.DEFOG));
await game.toNextTurn();
game.doAttack(getMovePosition(game.scene, 0, Moves.NOBLE_ROAR));
await game.toNextTurn();
game.doAttack(getMovePosition(game.scene, 0, Moves.SAND_ATTACK));
await game.toNextTurn();
game.override.moveset([Moves.STRING_SHOT]);
game.doAttack(getMovePosition(game.scene, 0, Moves.STRING_SHOT));
await game.toNextTurn();

expect(enemy.summonData.battleStats[BattleStat.ATK]).toEqual(0);
[BattleStat.ACC, BattleStat.DEF, BattleStat.EVA, BattleStat.SPATK, BattleStat.SPDEF, BattleStat.SPD].forEach((stat: number) => expect(enemy.summonData.battleStats[stat]).toBeLessThan(0));
});
});
1 change: 0 additions & 1 deletion src/test/ui/transfer-item.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ 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();
});

Expand Down
89 changes: 89 additions & 0 deletions src/test/ui/type-hints.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
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);
});
});
3 changes: 3 additions & 0 deletions src/test/utils/gameManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ 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.
Expand All @@ -44,6 +45,7 @@ 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.
Expand All @@ -63,6 +65,7 @@ export default class GameManager {
this.move = new MoveHelper(this);
this.classicMode = new ClassicModeHelper(this);
this.dailyMode = new DailyModeHelper(this);
this.settings = new SettingsHelper(this);
}

/**
Expand Down
15 changes: 15 additions & 0 deletions src/test/utils/helpers/settingsHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
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;
}
}
7 changes: 5 additions & 2 deletions src/test/utils/mocks/mocksContainer/mockContainer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import MockTextureManager from "#test/utils/mocks/mockTextureManager";
import { vi } from "vitest";
import { MockGameObject } from "../mockGameObject";

export default class MockContainer implements MockGameObject {
Expand All @@ -13,6 +14,7 @@ export default class MockContainer implements MockGameObject {
public frame;
protected textureManager;
public list: MockGameObject[] = [];
private name?: string;

constructor(textureManager: MockTextureManager, x, y) {
this.x = x;
Expand Down Expand Up @@ -159,9 +161,10 @@ export default class MockContainer implements MockGameObject {
// Moves this Game Object to be below the given Game Object in the display list.
}

setName(name) {
setName = vi.fn((name: string) => {
this.name = name;
// return this.phaserSprite.setName(name);
}
});

bringToTop(obj) {
// Brings this Game Object to the top of its parents display list.
Expand Down
Loading

0 comments on commit e0f572a

Please sign in to comment.