pokerogue/test/items/light-ball.test.ts
Wlowscha 466c4aede2
Replace remaining Modifiers with Rewards (#6091)
* Changing remaining Modifiers to Consumables, and renaming ModifierType to Reward

* Renamed modifier files and moved them into items folder

* Using rewards in most places

* Removed consumables in favor of using rewards directly

* Renamed RewardTier to RarityTier

* Reward ids, function to match rewards

* Getting reward tiers from player pool still

* Messing around with parameters of Reward.apply()

* Always requiring player pokemon in rewards

* Fixing some functions in select-reward-phase and battle-scene

* Fixed various post-merge issues

* Fixed most localization strings (accidentally broken by replacing modifierType with reward)

* Fixed tests for select reward phase

* Using Pokemon.hasSpecies()

* Zero weight for trainer items rewards which are already max stack

* Cleaning up SelectRewardPhase, held item rewards behave the same as any PokemonReward

* Cleaned up some functions

* Introduced RewardCategoryId, distributed RewardIds

* Utility `is` functions for rewards

* Minor fixes

* Moved `HeldItemEffect` to its own file

* rmade some todo comments

* Adding a big comment

* Added tsdocs and removed `RewardClass`

* undid breaking changes

* added TODO

* Moved matchingRewards function to reward-utils.ts

* Added RewardGenerator classes for mints and tera shards

* Introducing default rarity tiers for trainer items and rewards

* RewardFunc now can return RewardGenerator

* Moved pool reward functions to their own file, plus other utility files

* Fixed WeightedModifier to work with the new RewardFunc

* Fixed wrong type import

* Shifting trainer item and reward ids to avoid overlaps

* Added some types

* Updated comment in reward.ts

* Added strong typing ot item maps

* added type safety to held item name map

---------

Co-authored-by: Bertie690 <taylormw163@gmail.com>
Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com>
2025-07-27 17:09:21 -07:00

211 lines
8.1 KiB
TypeScript

import { HeldItemEffect } from "#enums/held-item-effect";
import { HeldItemId } from "#enums/held-item-id";
import { SpeciesId } from "#enums/species-id";
import { Stat } from "#enums/stat";
import { applyHeldItems } from "#items/all-held-items";
import i18next from "#plugins/i18n";
import { GameManager } from "#test/test-utils/game-manager";
import { NumberHolder } from "#utils/common";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
describe("Items - Light Ball", () => {
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.battleStyle("single");
});
it("LIGHT_BALL activates in battle correctly", async () => {
game.override.startingHeldItems([{ entry: HeldItemId.LIGHT_BALL }]);
const consoleSpy = vi.spyOn(console, "log");
await game.classicMode.startBattle([SpeciesId.PIKACHU]);
const partyMember = game.scene.getPlayerParty()[0];
// Checking console log to make sure Light Ball is applied when getEffectiveStat (with the appropriate stat) is called
partyMember.getEffectiveStat(Stat.DEF);
expect(consoleSpy).not.toHaveBeenLastCalledWith(
"Applied",
i18next.t("modifierType:SpeciesBoosterItem.LIGHT_BALL.name"),
"",
);
// Printing dummy console messages along the way so subsequent checks don't pass because of the first
console.log("");
partyMember.getEffectiveStat(Stat.SPDEF);
expect(consoleSpy).not.toHaveBeenLastCalledWith(
"Applied",
i18next.t("modifierType:SpeciesBoosterItem.LIGHT_BALL.name"),
"",
);
console.log("");
partyMember.getEffectiveStat(Stat.ATK);
expect(consoleSpy).toHaveBeenLastCalledWith(
"Applied",
i18next.t("modifierType:SpeciesBoosterItem.LIGHT_BALL.name"),
"",
);
console.log("");
partyMember.getEffectiveStat(Stat.SPATK);
expect(consoleSpy).toHaveBeenLastCalledWith(
"Applied",
i18next.t("modifierType:SpeciesBoosterItem.LIGHT_BALL.name"),
"",
);
console.log("");
partyMember.getEffectiveStat(Stat.SPD);
expect(consoleSpy).not.toHaveBeenLastCalledWith(
"Applied",
i18next.t("modifierType:SpeciesBoosterItem.LIGHT_BALL.name"),
"",
);
});
it("LIGHT_BALL held by PIKACHU", async () => {
await game.classicMode.startBattle([SpeciesId.PIKACHU]);
const partyMember = game.scene.getPlayerParty()[0];
const atkStat = partyMember.getStat(Stat.ATK);
const spAtkStat = partyMember.getStat(Stat.SPATK);
// Making sure modifier is not applied without holding item
const atkValue = new NumberHolder(atkStat);
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.DEF, statValue: atkValue });
const spAtkValue = new NumberHolder(spAtkStat);
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.SPDEF, statValue: spAtkValue });
expect(atkValue.value / atkStat).toBe(1);
expect(spAtkValue.value / spAtkStat).toBe(1);
// Giving Light Ball to party member and testing if it applies
partyMember.heldItemManager.add(HeldItemId.LIGHT_BALL);
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.ATK, statValue: atkValue });
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.SPATK, statValue: spAtkValue });
expect(atkValue.value / atkStat).toBe(2);
expect(spAtkValue.value / spAtkStat).toBe(2);
});
it("LIGHT_BALL held by fused PIKACHU (base)", async () => {
await game.classicMode.startBattle([SpeciesId.PIKACHU, SpeciesId.MAROWAK]);
const partyMember = game.scene.getPlayerParty()[0];
const ally = game.scene.getPlayerParty()[1];
// Fuse party members (taken from PlayerPokemon.fuse(...) function)
partyMember.fusionSpecies = ally.species;
partyMember.fusionFormIndex = ally.formIndex;
partyMember.fusionAbilityIndex = ally.abilityIndex;
partyMember.fusionShiny = ally.shiny;
partyMember.fusionVariant = ally.variant;
partyMember.fusionGender = ally.gender;
partyMember.fusionLuck = ally.luck;
const atkStat = partyMember.getStat(Stat.ATK);
const spAtkStat = partyMember.getStat(Stat.SPATK);
// Making sure modifier is not applied without holding item
const atkValue = new NumberHolder(atkStat);
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.DEF, statValue: atkValue });
const spAtkValue = new NumberHolder(spAtkStat);
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.SPDEF, statValue: spAtkValue });
expect(atkValue.value / atkStat).toBe(1);
expect(spAtkValue.value / spAtkStat).toBe(1);
// Giving Light Ball to party member and testing if it applies
partyMember.heldItemManager.add(HeldItemId.LIGHT_BALL);
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.ATK, statValue: atkValue });
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.SPATK, statValue: spAtkValue });
expect(atkValue.value / atkStat).toBe(2);
expect(spAtkValue.value / spAtkStat).toBe(2);
});
it("LIGHT_BALL held by fused PIKACHU (part)", async () => {
await game.classicMode.startBattle([SpeciesId.MAROWAK, SpeciesId.PIKACHU]);
const partyMember = game.scene.getPlayerParty()[0];
const ally = game.scene.getPlayerParty()[1];
// Fuse party members (taken from PlayerPokemon.fuse(...) function)
partyMember.fusionSpecies = ally.species;
partyMember.fusionFormIndex = ally.formIndex;
partyMember.fusionAbilityIndex = ally.abilityIndex;
partyMember.fusionShiny = ally.shiny;
partyMember.fusionVariant = ally.variant;
partyMember.fusionGender = ally.gender;
partyMember.fusionLuck = ally.luck;
const atkStat = partyMember.getStat(Stat.ATK);
const spAtkStat = partyMember.getStat(Stat.SPATK);
// Making sure modifier is not applied without holding item
const atkValue = new NumberHolder(atkStat);
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.DEF, statValue: atkValue });
const spAtkValue = new NumberHolder(spAtkStat);
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.SPDEF, statValue: spAtkValue });
expect(atkValue.value / atkStat).toBe(1);
expect(spAtkValue.value / spAtkStat).toBe(1);
// Giving Light Ball to party member and testing if it applies
partyMember.heldItemManager.add(HeldItemId.LIGHT_BALL);
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.ATK, statValue: atkValue });
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.SPATK, statValue: spAtkValue });
expect(atkValue.value / atkStat).toBe(2);
expect(spAtkValue.value / spAtkStat).toBe(2);
});
it("LIGHT_BALL not held by PIKACHU", async () => {
await game.classicMode.startBattle([SpeciesId.MAROWAK]);
const partyMember = game.scene.getPlayerParty()[0];
const atkStat = partyMember.getStat(Stat.ATK);
const spAtkStat = partyMember.getStat(Stat.SPATK);
// Making sure modifier is not applied without holding item
const atkValue = new NumberHolder(atkStat);
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.DEF, statValue: atkValue });
const spAtkValue = new NumberHolder(spAtkStat);
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.SPDEF, statValue: spAtkValue });
expect(atkValue.value / atkStat).toBe(1);
expect(spAtkValue.value / spAtkStat).toBe(1);
// Giving Light Ball to party member and testing if it applies
partyMember.heldItemManager.add(HeldItemId.LIGHT_BALL);
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.ATK, statValue: atkValue });
applyHeldItems(HeldItemEffect.STAT_BOOST, { pokemon: partyMember, stat: Stat.SPATK, statValue: spAtkValue });
expect(atkValue.value / atkStat).toBe(1);
expect(spAtkValue.value / spAtkStat).toBe(1);
});
});