[Item] Implement Eviolite Behavior (#2161)

* Add Eviolite with Unit Tests

* Localize for de, es, fr, it, ko, zh_CN, zh_TW

* Adjust German Localization

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>

* Adjust Italian Localization

* Change Multiplier Type

* Adjust Unit Test Import

* Change Constructor

* Make Unit Tests Localized

* Comment Out of Reward Pool

---------

Co-authored-by: Jannik Tappert <38758606+CodeTappert@users.noreply.github.com>
This commit is contained in:
Amani H 2024-06-24 22:00:59 -04:00 committed by GitHub
parent ec91d2453a
commit 136652caa9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 2147 additions and 1748 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -10,7 +10,7 @@ import * as Utils from "../utils";
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from "../data/type";
import { getLevelTotalExp } from "../data/exp";
import { Stat } from "../data/pokemon-stat";
import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, TerastallizeModifier } from "../modifier/modifier";
import { AttackTypeBoosterModifier, DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, PokemonBaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonMultiHitModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempBattleStatBoosterModifier, EvolutionStatBoosterModifier, TerastallizeModifier } from "../modifier/modifier";
import { PokeballType } from "../data/pokeball";
import { Gender } from "../data/gender";
import { initMoveAnim, loadMoveAnimAssets } from "../data/battle-anims";
@ -657,6 +657,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.scene.applyModifiers(TempBattleStatBoosterModifier, this.isPlayer(), battleStat as integer as TempBattleStat, statLevel);
}
const statValue = new Utils.NumberHolder(this.getStat(stat));
this.scene.applyModifiers(EvolutionStatBoosterModifier, this.isPlayer(), this, stat, statValue);
const fieldApplied = new Utils.BooleanHolder(false);
for (const pokemon of this.scene.getField(true)) {
applyFieldBattleStatMultiplierAbAttrs(FieldMultiplyBattleStatAbAttr, pokemon, stat, statValue, this, fieldApplied);

View File

@ -182,6 +182,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"SOOTHE_BELL": { name: "Sanftglocke" },
"EVIOLITE": { name: "Evolith", description: "Ein mysteriöser Klumpen, der die Vert. u. Spez.-Vert. von Pokémon erhöht, die sich noch entwickeln können." },
"SOUL_DEW": { name: "Seelentau", description: "Erhöht den Einfluss des Wesens eines Pokemon auf seine Werte um 10% (additiv)." },
"NUGGET": { name: "Nugget" },

View File

@ -182,6 +182,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"SOOTHE_BELL": { name: "Soothe Bell" },
"EVIOLITE": { name: "Eviolite", description: "This mysterious evolutionary lump boosts the Defense and Sp. Def stats when held by a Pokémon that can still evolve." },
"SOUL_DEW": { name: "Soul Dew", description: "Increases the influence of a Pokémon's nature on its stats by 10% (additive)." },
"NUGGET": { name: "Nugget" },

View File

@ -182,6 +182,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"SOOTHE_BELL": { name: "Camp. Alivio" },
"EVIOLITE": { name: "Mineral Evolutivo", description: "Roca misteriosa. El Pokémon portador aumentará su Defensa y su Defensa Especial si aún puede evolucionar." },
"SOUL_DEW": { name: "Rocío bondad", description: "Aumenta la influencia de la naturaleza de un Pokémon en sus estadísticas en un 10% (aditivo)." },
"NUGGET": { name: "Pepita" },

View File

@ -182,6 +182,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"SOOTHE_BELL": { name: "Grelot Zen" },
"EVIOLITE": { name: "Évoluroc", description: "Un étrange concentré dévolution qui augmente la Défense et la Défense Spéciale dun Pokémon pouvant évoluer." },
"SOUL_DEW": { name: "Rosée Âme", description: "Augmente de 10% linfluence de la nature dun Pokémon sur ses statistiques (cumulatif)." },
"NUGGET": { name: "Pépite" },

View File

@ -182,6 +182,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"SOOTHE_BELL": { name: "Calmanella" },
"EVIOLITE": { name: "Evolcondensa", description: "Misteriosa materia evolutiva. Aumenta la Difesa e la Difesa Speciale di un Pokémon che può ancora evolversi." },
"SOUL_DEW": { name: "Cuorugiada", description: "Aumenta del 10% l'influenza della natura di un Pokémon sulle sue statistiche (Aggiuntivo)." },
"NUGGET": { name: "Pepita" },

View File

@ -182,6 +182,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"SOOTHE_BELL": { name: "평온의방울" },
"EVIOLITE": { name: "진화의휘석", description: "진화의 이상한 덩어리. 지니게 하면 진화 전 포켓몬의 방어와 특수방어가 올라간다." },
"SOUL_DEW": { name: "마음의물방울", description: "지닌 포켓몬의 성격의 효과가 10% 증가한다 (합연산)." },
"NUGGET": { name: "금구슬" },

View File

@ -182,6 +182,8 @@ export const modifierType: ModifierTypeTranslationEntries = {
"SOOTHE_BELL": { name: "安抚之铃" },
"EVIOLITE": { name: "进化奇石", description: "进化的神奇石块。携带后,还能进化的宝可梦的 防御和特防就会提高。" },
"SOUL_DEW": { name: "心之水滴", description: "增加宝可梦性格影响10% (加算)。" },
"NUGGET": { name: "金珠" },

View File

@ -187,6 +187,10 @@ export const modifierType: ModifierTypeTranslationEntries = {
LUCKY_EGG: { name: "幸運蛋" },
GOLDEN_EGG: { name: "金蛋" },
SOOTHE_BELL: { name: "安撫之鈴" },
EVIOLITE: {
name: "進化奇石",
description: "進化的神奇石塊。攜帶後,還能進化的寶可夢的 防禦和特防就會提高。"
},
SOUL_DEW: {
name: "心之水滴",
description: "增加寶可夢性格影響10% (加算)。",

View File

@ -1193,6 +1193,8 @@ export const modifierTypes = {
SOOTHE_BELL: () => new PokemonFriendshipBoosterModifierType("modifierType:ModifierType.SOOTHE_BELL", "soothe_bell"),
EVIOLITE: () => new PokemonHeldItemModifierType("modifierType:ModifierType.EVIOLITE", "eviolite", (type, args) => new Modifiers.EvolutionStatBoosterModifier(type, (args[0] as Pokemon).id, [Stat.DEF, Stat.SPDEF], 1.5)),
SOUL_DEW: () => new PokemonHeldItemModifierType("modifierType:ModifierType.SOUL_DEW", "soul_dew", (type, args) => new Modifiers.PokemonNatureWeightModifier(type, (args[0] as Pokemon).id)),
NUGGET: () => new MoneyRewardModifierType("modifierType:ModifierType.NUGGET", "nugget", 1, "modifierType:ModifierType.MoneyRewardModifierType.extra.small"),
@ -1366,6 +1368,7 @@ const modifierPool: ModifierPool = {
new WeightedModifierType(modifierTypes.MINT, 4),
new WeightedModifierType(modifierTypes.RARE_EVOLUTION_ITEM, (party: Pokemon[]) => Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 15) * 4, 32), 32),
new WeightedModifierType(modifierTypes.AMULET_COIN, 3),
//new WeightedModifierType(modifierTypes.EVIOLITE, (party: Pokemon[]) => party.some(p => ((p.getSpeciesForm(true).speciesId in pokemonEvolutions) || (p.isFusion() && (p.getFusionSpeciesForm(true).speciesId in pokemonEvolutions))) && !p.getHeldItems().some(i => i instanceof Modifiers.EvolutionStatBoosterModifier)) ? 10 : 0),
new WeightedModifierType(modifierTypes.TOXIC_ORB, (party: Pokemon[]) => {
const checkedAbilities = [Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.TOXIC_BOOST, Abilities.POISON_HEAL, Abilities.MAGIC_GUARD];
const checkedMoves = [Moves.FACADE, Moves.TRICK, Moves.FLING, Moves.SWITCHEROO, Moves.PSYCHO_SHIFT];

View File

@ -706,6 +706,83 @@ export class PokemonBaseStatModifier extends PokemonHeldItemModifier {
}
}
/**
* Modifier used for held items, specifically Eviolite, that apply
* {@linkcode Stat} boost(s) using a multiplier if the holder can evolve.
* @extends PokemonHeldItemModifier
* @see {@linkcode apply}
*/
export class EvolutionStatBoosterModifier extends PokemonHeldItemModifier {
/** The stats that the held item boosts */
private stats: Stat[];
/** The multiplier used to increase the relevant stat(s) */
private multiplier: number;
constructor(type: ModifierType, pokemonId: integer, stats: Stat[], multiplier: number, stackCount?: integer) {
super(type, pokemonId, stackCount);
this.stats = stats;
this.multiplier = multiplier;
}
clone() {
return new EvolutionStatBoosterModifier(this.type, this.pokemonId, this.stats, this.multiplier, this.stackCount);
}
getArgs(): any[] {
return [ ...super.getArgs(), this.stats, this.multiplier ];
}
matchType(modifier: Modifier): boolean {
return modifier instanceof EvolutionStatBoosterModifier;
}
/**
* Checks if the incoming stat is listed in {@linkcode stats}
* @param args [0] {@linkcode Pokemon} N/A
* [1] {@linkcode Stat} being checked at the time
* [2] {@linkcode Utils.NumberHolder} N/A
* @returns true if the stat could be boosted, false otherwise
*/
shouldApply(args: any[]): boolean {
return this.stats.includes(args[1] as Stat);
}
/**
* Boosts the incoming stat value by a {@linkcode multiplier} if the holder
* can evolve. Note that, if the holder is a fusion, they will receive
* only half of the boost if either of the fused members are fully
* evolved. However, if they are both unevolved, the full boost
* will apply.
* @param args [0] {@linkcode Pokemon} that holds the held item
* [1] {@linkcode Stat} N/A
* [2] {@linkcode Utils.NumberHolder} that holds the resulting value of the stat
* @returns true if the stat boost applies successfully, false otherwise
* @see shouldApply
*/
apply(args: any[]): boolean {
const holder = args[0] as Pokemon;
const statValue = args[2] as Utils.NumberHolder;
const isUnevolved = holder.getSpeciesForm(true).speciesId in pokemonEvolutions;
if (holder.isFusion() && (holder.getFusionSpeciesForm(true).speciesId in pokemonEvolutions) !== isUnevolved) {
// Half boost applied if holder is fused and either part of fusion is fully evolved
statValue.value *= 1 + (this.multiplier - 1) / 2;
return true;
} else if (isUnevolved) {
// Full boost applied if holder is unfused and unevolved or, if fused, both parts of fusion are unevolved
statValue.value *= this.multiplier;
return true;
}
return false;
}
getMaxHeldItemCount(_pokemon: Pokemon): integer {
return 1;
}
}
/**
* Applies Specific Type item boosts (e.g., Magnet)
*/

View File

@ -0,0 +1,278 @@
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import Phase from "phaser";
import GameManager from "#app/test/utils/gameManager";
import * as overrides from "#app/overrides";
import { Stat } from "#app/data/pokemon-stat";
import { EvolutionStatBoosterModifier } from "#app/modifier/modifier";
import { modifierTypes } from "#app/modifier/modifier-type";
import * as Utils from "#app/utils";
import i18next from "#app/plugins/i18n";
import { Species } from "#enums/species";
describe("Items - Eviolite", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
beforeAll(() => {
phaserGame = new Phase.Game({
type: Phaser.HEADLESS,
});
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
});
beforeEach(() => {
game = new GameManager(phaserGame);
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
});
it("EVIOLITE activates in battle correctly", async() => {
vi.spyOn(overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue([{ name: "EVIOLITE" }]);
const consoleSpy = vi.spyOn(console, "log");
await game.startBattle([
Species.PICHU
]);
const partyMember = game.scene.getParty()[0];
// Checking consoe log to make sure Eviolite is applied when getBattleStat (with the appropriate stat) is called
partyMember.getBattleStat(Stat.DEF);
expect(consoleSpy).toHaveBeenLastCalledWith("Applied", i18next.t("modifierType:ModifierType.EVIOLITE.name"), "");
// Printing dummy console messages along the way so subsequent checks don't pass because of the first
console.log("");
partyMember.getBattleStat(Stat.SPDEF);
expect(consoleSpy).toHaveBeenLastCalledWith("Applied", i18next.t("modifierType:ModifierType.EVIOLITE.name"), "");
console.log("");
partyMember.getBattleStat(Stat.ATK);
expect(consoleSpy).not.toHaveBeenLastCalledWith("Applied", i18next.t("modifierType:ModifierType.EVIOLITE.name"), "");
console.log("");
partyMember.getBattleStat(Stat.SPATK);
expect(consoleSpy).not.toHaveBeenLastCalledWith("Applied", i18next.t("modifierType:ModifierType.EVIOLITE.name"), "");
console.log("");
partyMember.getBattleStat(Stat.SPD);
expect(consoleSpy).not.toHaveBeenLastCalledWith("Applied", i18next.t("modifierType:ModifierType.EVIOLITE.name"), "");
});
it("EVIOLITE held by unevolved, unfused pokemon", async() => {
await game.startBattle([
Species.PICHU
]);
const partyMember = game.scene.getParty()[0];
const defStat = partyMember.getStat(Stat.DEF);
const spDefStat = partyMember.getStat(Stat.SPDEF);
// Making sure modifier is not applied without holding item
const defValue = new Utils.NumberHolder(defStat);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
const spDefValue = new Utils.NumberHolder(spDefStat);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue);
expect(defValue.value / defStat).toBe(1);
expect(spDefValue.value / spDefStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
partyMember.scene.addModifier(modifierTypes.EVIOLITE().newModifier(partyMember), true);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue);
expect(defValue.value / defStat).toBe(1.5);
expect(spDefValue.value / spDefStat).toBe(1.5);
}, 20000);
it("EVIOLITE held by fully evolved, unfused pokemon", async() => {
await game.startBattle([
Species.RAICHU,
]);
const partyMember = game.scene.getParty()[0];
const defStat = partyMember.getStat(Stat.DEF);
const spDefStat = partyMember.getStat(Stat.SPDEF);
// Making sure modifier is not applied without holding item
const defValue = new Utils.NumberHolder(defStat);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
const spDefValue = new Utils.NumberHolder(spDefStat);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue);
expect(defValue.value / defStat).toBe(1);
expect(spDefValue.value / spDefStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
partyMember.scene.addModifier(modifierTypes.EVIOLITE().newModifier(partyMember), true);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue);
expect(defValue.value / defStat).toBe(1);
expect(spDefValue.value / spDefStat).toBe(1);
}, 20000);
it("EVIOLITE held by completely unevolved, fused pokemon", async() => {
await game.startBattle([
Species.PICHU,
Species.CLEFFA
]);
const partyMember = game.scene.getParty()[0];
const ally = game.scene.getParty()[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 defStat = partyMember.getStat(Stat.DEF);
const spDefStat = partyMember.getStat(Stat.SPDEF);
// Making sure modifier is not applied without holding item
const defValue = new Utils.NumberHolder(defStat);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
const spDefValue = new Utils.NumberHolder(spDefStat);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue);
expect(defValue.value / defStat).toBe(1);
expect(spDefValue.value / spDefStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
partyMember.scene.addModifier(modifierTypes.EVIOLITE().newModifier(partyMember), true);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue);
expect(defValue.value / defStat).toBe(1.5);
expect(spDefValue.value / spDefStat).toBe(1.5);
}, 20000);
it("EVIOLITE held by partially unevolved (base), fused pokemon", async() => {
await game.startBattle([
Species.PICHU,
Species.CLEFABLE
]);
const partyMember = game.scene.getParty()[0];
const ally = game.scene.getParty()[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 defStat = partyMember.getStat(Stat.DEF);
const spDefStat = partyMember.getStat(Stat.SPDEF);
// Making sure modifier is not applied without holding item
const defValue = new Utils.NumberHolder(defStat);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
const spDefValue = new Utils.NumberHolder(spDefStat);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue);
expect(defValue.value / defStat).toBe(1);
expect(spDefValue.value / spDefStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
partyMember.scene.addModifier(modifierTypes.EVIOLITE().newModifier(partyMember), true);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue);
expect(defValue.value / defStat).toBe(1.25);
expect(spDefValue.value / spDefStat).toBe(1.25);
}, 20000);
it("EVIOLITE held by partially unevolved (fusion), fused pokemon", async() => {
await game.startBattle([
Species.RAICHU,
Species.CLEFFA
]);
const partyMember = game.scene.getParty()[0];
const ally = game.scene.getParty()[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 defStat = partyMember.getStat(Stat.DEF);
const spDefStat = partyMember.getStat(Stat.SPDEF);
// Making sure modifier is not applied without holding item
const defValue = new Utils.NumberHolder(defStat);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
const spDefValue = new Utils.NumberHolder(spDefStat);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue);
expect(defValue.value / defStat).toBe(1);
expect(spDefValue.value / spDefStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
partyMember.scene.addModifier(modifierTypes.EVIOLITE().newModifier(partyMember), true);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue);
expect(defValue.value / defStat).toBe(1.25);
expect(spDefValue.value / spDefStat).toBe(1.25);
}, 20000);
it("EVIOLITE held by completely evolved, fused pokemon", async() => {
await game.startBattle([
Species.RAICHU,
Species.CLEFABLE
]);
const partyMember = game.scene.getParty()[0];
const ally = game.scene.getParty()[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 defStat = partyMember.getStat(Stat.DEF);
const spDefStat = partyMember.getStat(Stat.SPDEF);
// Making sure modifier is not applied without holding item
const defValue = new Utils.NumberHolder(defStat);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
const spDefValue = new Utils.NumberHolder(spDefStat);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue);
expect(defValue.value / defStat).toBe(1);
expect(spDefValue.value / spDefStat).toBe(1);
// Giving Eviolite to party member and testing if it applies
partyMember.scene.addModifier(modifierTypes.EVIOLITE().newModifier(partyMember), true);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.DEF, defValue);
partyMember.scene.applyModifiers(EvolutionStatBoosterModifier, true, partyMember, Stat.SPDEF, spDefValue);
expect(defValue.value / defStat).toBe(1);
expect(spDefValue.value / spDefStat).toBe(1);
}, 20000);
});