Merge branch 'beta' into instruct

This commit is contained in:
Bertie690 2024-11-15 07:16:26 -05:00 committed by GitHub
commit eb074a457e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 218 additions and 75 deletions

View File

@ -1233,13 +1233,40 @@ export default class BattleScene extends SceneBase {
newDouble = !!double;
}
if (Overrides.BATTLE_TYPE_OVERRIDE === "double") {
// Disable double battles on Endless/Endless Spliced Wave 50x boss battles (Introduced 1.2.0)
if (this.gameMode.isEndlessBoss(newWaveIndex)) {
newDouble = false;
}
if (!isNullOrUndefined(Overrides.BATTLE_TYPE_OVERRIDE)) {
let doubleOverrideForWave: "single" | "double" | null = null;
switch (Overrides.BATTLE_TYPE_OVERRIDE) {
case "double":
doubleOverrideForWave = "double";
break;
case "single":
doubleOverrideForWave = "single";
break;
case "even-doubles":
doubleOverrideForWave = (newWaveIndex % 2) ? "single" : "double";
break;
case "odd-doubles":
doubleOverrideForWave = (newWaveIndex % 2) ? "double" : "single";
break;
}
if (doubleOverrideForWave === "double") {
newDouble = true;
}
/* Override battles into single only if not fighting with trainers */
if (newBattleType !== BattleType.TRAINER && Overrides.BATTLE_TYPE_OVERRIDE === "single") {
/**
* Override battles into single only if not fighting with trainers.
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/1948 | GitHub Issue #1948}
*/
if (newBattleType !== BattleType.TRAINER && doubleOverrideForWave === "single") {
newDouble = false;
}
}
const lastBattle = this.currentBattle;

View File

@ -516,7 +516,7 @@ export class NonSuperEffectiveImmunityAbAttr extends TypeImmunityAbAttr {
applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
const modifierValue = args.length > 0
? (args[0] as Utils.NumberHolder).value
: pokemon.getAttackTypeEffectiveness(attacker.getMoveType(move), attacker);
: pokemon.getAttackTypeEffectiveness(attacker.getMoveType(move), attacker, undefined, undefined, move);
if (move instanceof AttackMove && modifierValue < 2) {
cancelled.value = true; // Suppresses "No Effect" message
@ -3180,7 +3180,7 @@ function getAnticipationCondition(): AbAttrCondition {
continue;
}
// the move's base type (not accounting for variable type changes) is super effective
if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type, opponent, true) >= 2) {
if (move.getMove() instanceof AttackMove && pokemon.getAttackTypeEffectiveness(move.getMove().type, opponent, true, undefined, move.getMove()) >= 2) {
return true;
}
// move is a OHKO

View File

@ -1809,8 +1809,8 @@ export class TypeImmuneTag extends BattlerTag {
* @see {@link https://bulbapedia.bulbagarden.net/wiki/Telekinesis_(move) | Moves.TELEKINESIS}
*/
export class FloatingTag extends TypeImmuneTag {
constructor(tagType: BattlerTagType, sourceMove: Moves) {
super(tagType, sourceMove, Type.GROUND, 5);
constructor(tagType: BattlerTagType, sourceMove: Moves, turnCount: number) {
super(tagType, sourceMove, Type.GROUND, turnCount);
}
onAdd(pokemon: Pokemon): void {
@ -3053,7 +3053,7 @@ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, source
case BattlerTagType.CHARGED:
return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true);
case BattlerTagType.FLOATING:
return new FloatingTag(tagType, sourceMove);
return new FloatingTag(tagType, sourceMove, turnCount);
case BattlerTagType.MINIMIZED:
return new MinimizeTag();
case BattlerTagType.DESTINY_BOND:

View File

@ -653,7 +653,7 @@ export class FreshStartChallenge extends Challenge {
pokemon.shiny = false; // Not shiny
pokemon.variant = 0; // Not shiny
pokemon.formIndex = 0; // Froakie should be base form
pokemon.ivs = [ 10, 10, 10, 10, 10, 10 ]; // Default IVs of 10 for all stats
pokemon.ivs = [ 15, 15, 15, 15, 15, 15 ]; // Default IVs of 15 for all stats (Updated to 15 from 10 in 1.2.0)
return true;
}

View File

@ -897,7 +897,7 @@ export class AttackMove extends Move {
let attackScore = 0;
const effectiveness = target.getAttackTypeEffectiveness(this.type, user);
const effectiveness = target.getAttackTypeEffectiveness(this.type, user, undefined, undefined, this);
attackScore = Math.pow(effectiveness - 1, 2) * effectiveness < 1 ? -2 : 2;
if (attackScore) {
if (this.category === MoveCategory.PHYSICAL) {
@ -4971,48 +4971,6 @@ export class NeutralDamageAgainstFlyingTypeMultiplierAttr extends VariableMoveTy
}
}
/**
* This class forces Freeze-Dry to be super effective against Water Type.
* It considers if target is Mono or Dual Type and calculates the new Multiplier accordingly.
* @see {@linkcode apply}
*/
export class FreezeDryAttr extends VariableMoveTypeMultiplierAttr {
/**
* If the target is Mono Type (Water only) then a 2x Multiplier is always forced.
* If target is Dual Type (containing Water) then only a 2x Multiplier is forced for the Water Type.
*
* Additionally Freeze-Dry's effectiveness against water is always forced during {@linkcode InverseBattleChallenge}.
* The multiplier is recalculated for the non-Water Type in case of Dual Type targets containing Water Type.
*
* @param user The {@linkcode Pokemon} applying the move
* @param target The {@linkcode Pokemon} targeted by the move
* @param move The move used by the user
* @param args `[0]` a {@linkcode Utils.NumberHolder | NumberHolder} containing a type effectiveness multiplier
* @returns `true` if super effectiveness on water type is forced; `false` otherwise
*/
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const multiplier = args[0] as Utils.NumberHolder;
if (target.isOfType(Type.WATER) && multiplier.value !== 0) {
const multipleTypes = (target.getTypes().length > 1);
if (multipleTypes) {
const nonWaterType = target.getTypes().filter(type => type !== Type.WATER)[0];
const effectivenessAgainstTarget = new Utils.NumberHolder(getTypeDamageMultiplier(user.getMoveType(move), nonWaterType));
applyChallenges(user.scene.gameMode, ChallengeType.TYPE_EFFECTIVENESS, effectivenessAgainstTarget);
multiplier.value = effectivenessAgainstTarget.value * 2;
return true;
}
multiplier.value = 2;
return true;
}
return false;
}
}
export class IceNoEffectTypeAttr extends VariableMoveTypeMultiplierAttr {
/**
* Checks to see if the Target is Ice-Type or not. If so, the move will have no effect.
@ -5040,6 +4998,41 @@ export class FlyingTypeMultiplierAttr extends VariableMoveTypeMultiplierAttr {
}
}
/**
* Attribute for moves which have a custom type chart interaction.
*/
export class VariableMoveTypeChartAttr extends MoveAttr {
/**
* @param user {@linkcode Pokemon} using the move
* @param target {@linkcode Pokemon} target of the move
* @param move {@linkcode Move} with this attribute
* @param args [0] {@linkcode NumberHolder} holding the type effectiveness
* @param args [1] A single defensive type of the target
*
* @returns true if application of the attribute succeeds
*/
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
return false;
}
}
/**
* This class forces Freeze-Dry to be super effective against Water Type.
*/
export class FreezeDryAttr extends VariableMoveTypeChartAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const multiplier = args[0] as Utils.NumberHolder;
const defType = args[1] as Type;
if (defType === Type.WATER) {
multiplier.value = 2;
return true;
} else {
return false;
}
}
}
export class OneHitKOAccuracyAttr extends VariableAccuracyAttr {
apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean {
const accuracy = args[0] as Utils.NumberHolder;
@ -9016,7 +9009,7 @@ export function initMoves() {
new SelfStatusMove(Moves.AQUA_RING, Type.WATER, -1, 20, -1, 0, 4)
.attr(AddBattlerTagAttr, BattlerTagType.AQUA_RING, true, true),
new SelfStatusMove(Moves.MAGNET_RISE, Type.ELECTRIC, -1, 10, -1, 0, 4)
.attr(AddBattlerTagAttr, BattlerTagType.FLOATING, true, true)
.attr(AddBattlerTagAttr, BattlerTagType.FLOATING, true, true, 5)
.condition((user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY) && [ BattlerTagType.FLOATING, BattlerTagType.IGNORE_FLYING, BattlerTagType.INGRAIN ].every((tag) => !user.getTag(tag))),
new AttackMove(Moves.FLARE_BLITZ, Type.FIRE, MoveCategory.PHYSICAL, 120, 100, 15, 10, 0, 4)
.attr(RecoilAttr, false, 0.33)
@ -9567,8 +9560,7 @@ export function initMoves() {
.target(MoveTarget.ALL_NEAR_OTHERS),
new AttackMove(Moves.FREEZE_DRY, Type.ICE, MoveCategory.SPECIAL, 70, 100, 20, 10, 0, 6)
.attr(StatusEffectAttr, StatusEffect.FREEZE)
.attr(FreezeDryAttr)
.edgeCase(), // This currently just multiplies the move's power instead of changing its effectiveness. It also doesn't account for abilities that modify type effectiveness such as tera shell.
.attr(FreezeDryAttr),
new AttackMove(Moves.DISARMING_VOICE, Type.FAIRY, MoveCategory.SPECIAL, 40, -1, 15, -1, 0, 6)
.soundBased()
.target(MoveTarget.ALL_NEAR_ENEMIES),

View File

@ -3,7 +3,7 @@ import BattleScene, { AnySound } from "#app/battle-scene";
import { Variant, VariantSet, variantColorCache } from "#app/data/variant";
import { variantData } from "#app/data/variant";
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "#app/ui/battle-info";
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget, CombinedPledgeStabBoostAttr } from "#app/data/move";
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget, CombinedPledgeStabBoostAttr, VariableMoveTypeChartAttr } from "#app/data/move";
import { default as PokemonSpecies, PokemonSpeciesForm, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
import { CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER, getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters";
import { starterPassiveAbilities } from "#app/data/balance/passives";
@ -1632,7 +1632,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const moveType = source.getMoveType(move);
const typeMultiplier = new Utils.NumberHolder((move.category !== MoveCategory.STATUS || move.hasAttr(RespectAttackTypeImmunityAttr))
? this.getAttackTypeEffectiveness(moveType, source, false, simulated)
? this.getAttackTypeEffectiveness(moveType, source, false, simulated, move)
: 1);
applyMoveAttrs(VariableMoveTypeMultiplierAttr, source, this, move, typeMultiplier);
@ -1684,9 +1684,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* @param source {@linkcode Pokemon} the Pokemon using the move
* @param ignoreStrongWinds whether or not this ignores strong winds (anticipation, forewarn, stealth rocks)
* @param simulated tag to only apply the strong winds effect message when the move is used
* @param move (optional) the move whose type effectiveness is to be checked. Used for applying {@linkcode VariableMoveTypeChartAttr}
* @returns a multiplier for the type effectiveness
*/
getAttackTypeEffectiveness(moveType: Type, source?: Pokemon, ignoreStrongWinds: boolean = false, simulated: boolean = true): TypeDamageMultiplier {
getAttackTypeEffectiveness(moveType: Type, source?: Pokemon, ignoreStrongWinds: boolean = false, simulated: boolean = true, move?: Move): TypeDamageMultiplier {
if (moveType === Type.STELLAR) {
return this.isTerastallized() ? 2 : 1;
}
@ -1705,6 +1706,9 @@ 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 (move) {
applyMoveAttrs(VariableMoveTypeChartAttr, null, this, move, multiplier, defType);
}
if (source) {
const ignoreImmunity = new Utils.BooleanHolder(false);
if (source.isActive(true) && source.hasAbilityWithAttr(IgnoreTypeImmunityAbAttr)) {

View File

@ -236,7 +236,7 @@ export class GameMode implements GameModeConfig {
* @returns true if waveIndex is a multiple of 50 in Endless
*/
isEndlessBoss(waveIndex: integer): boolean {
return !!(waveIndex % 50) &&
return waveIndex % 50 === 0 &&
(this.modeId === GameModes.ENDLESS || this.modeId === GameModes.SPLICED_ENDLESS);
}

View File

@ -3631,7 +3631,7 @@ export class EnemyEndureChanceModifier extends EnemyPersistentModifier {
super(type, stackCount || 10);
//Hardcode temporarily
this.chance = .02;
this.chance = 2;
}
match(modifier: Modifier) {
@ -3639,11 +3639,11 @@ export class EnemyEndureChanceModifier extends EnemyPersistentModifier {
}
clone() {
return new EnemyEndureChanceModifier(this.type, this.chance * 100, this.stackCount);
return new EnemyEndureChanceModifier(this.type, this.chance, this.stackCount);
}
getArgs(): any[] {
return [ this.chance * 100 ];
return [ this.chance ];
}
/**
@ -3652,7 +3652,7 @@ export class EnemyEndureChanceModifier extends EnemyPersistentModifier {
* @returns `true` if {@linkcode Pokemon} endured
*/
override apply(target: Pokemon): boolean {
if (target.battleData.endured || Phaser.Math.RND.realInRange(0, 1) >= (this.chance * this.getStackCount())) {
if (target.battleData.endured || target.randSeedInt(100) >= (this.chance * this.getStackCount())) {
return false;
}

View File

@ -47,7 +47,18 @@ class DefaultOverrides {
/** a specific seed (default: a random string of 24 characters) */
readonly SEED_OVERRIDE: string = "";
readonly WEATHER_OVERRIDE: WeatherType = WeatherType.NONE;
readonly BATTLE_TYPE_OVERRIDE: "double" | "single" | null = null;
/**
* If `null`, ignore this override.
*
* If `"single"`, set every non-trainer battle to be a single battle.
*
* If `"double"`, set every battle (including trainer battles) to be a double battle.
*
* If `"even-doubles"`, follow the `"double"` rule on even wave numbers, and follow the `"single"` rule on odd wave numbers.
*
* If `"odd-doubles"`, follow the `"double"` rule on odd wave numbers, and follow the `"single"` rule on even wave numbers.
*/
readonly BATTLE_TYPE_OVERRIDE: BattleStyle | null = null;
readonly STARTING_WAVE_OVERRIDE: number = 0;
readonly STARTING_BIOME_OVERRIDE: Biome = Biome.TOWN;
readonly ARENA_TINT_OVERRIDE: TimeOfDay | null = null;
@ -229,3 +240,5 @@ export default {
...defaultOverrides,
...overrides
} satisfies InstanceType<typeof DefaultOverrides>;
export type BattleStyle = "double" | "single" | "even-doubles" | "odd-doubles";

View File

@ -679,7 +679,7 @@ export class GameData {
return ret;
}
return k.endsWith("Attr") && ![ "natureAttr", "abilityAttr", "passiveAttr" ].includes(k) ? BigInt(v) : v;
return k.endsWith("Attr") && ![ "natureAttr", "abilityAttr", "passiveAttr" ].includes(k) ? BigInt(v ?? 0) : v;
}) as SystemSaveData;
}
@ -1540,7 +1540,7 @@ export class GameData {
entry.caughtAttr = defaultStarterAttr;
entry.natureAttr = 1 << (defaultStarterNatures[ds] + 1);
for (const i in entry.ivs) {
entry.ivs[i] = 10;
entry.ivs[i] = 15;
}
}

View File

@ -1,4 +1,6 @@
import { Status } from "#app/data/status-effect";
import { Abilities } from "#enums/abilities";
import { GameModes, getGameMode } from "#app/game-mode";
import { BattleEndPhase } from "#app/phases/battle-end-phase";
import { TurnInitPhase } from "#app/phases/turn-init-phase";
import { Moves } from "#enums/moves";
@ -6,9 +8,11 @@ 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 { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
describe("Double Battles", () => {
const DOUBLE_CHANCE = 8; // Normal chance of double battle is 1/8
let phaserGame: Phaser.Game;
let game: GameManager;
@ -56,4 +60,40 @@ describe("Double Battles", () => {
await game.phaseInterceptor.to(TurnInitPhase);
expect(game.scene.getPlayerField().filter(p => !p.isFainted())).toHaveLength(2);
}, 20000);
it("randomly chooses between single and double battles if there is no battle type override", async () => {
let rngSweepProgress = 0; // Will simulate RNG rolls by slowly increasing from 0 to 1
let doubleCount = 0;
let singleCount = 0;
vi.spyOn(Phaser.Math.RND, "realInRange").mockImplementation((min: number, max: number) => {
return rngSweepProgress * (max - min) + min;
});
game.override.enemyMoveset(Moves.SPLASH)
.moveset(Moves.SPLASH)
.enemyAbility(Abilities.BALL_FETCH)
.ability(Abilities.BALL_FETCH);
// Play through endless, waves 1 to 9, counting number of double battles from waves 2 to 9
await game.classicMode.startBattle([ Species.BULBASAUR ]);
game.scene.gameMode = getGameMode(GameModes.ENDLESS);
for (let i = 0; i < DOUBLE_CHANCE; i++) {
rngSweepProgress = (i + 0.5) / DOUBLE_CHANCE;
game.move.select(Moves.SPLASH);
await game.doKillOpponents();
await game.toNextWave();
if (game.scene.getEnemyParty().length === 1) {
singleCount++;
} else if (game.scene.getEnemyParty().length === 2) {
doubleCount++;
}
}
expect(doubleCount).toBe(1);
expect(singleCount).toBe(DOUBLE_CHANCE - 1);
});
});

View File

@ -2,6 +2,7 @@ import { BattlerIndex } from "#app/battle";
import { Abilities } from "#app/enums/abilities";
import { Moves } from "#app/enums/moves";
import { Species } from "#app/enums/species";
import { Type } from "#enums/type";
import { Challenges } from "#enums/challenges";
import GameManager from "#test/utils/gameManager";
import Phaser from "phaser";
@ -29,7 +30,7 @@ describe("Moves - Freeze-Dry", () => {
.enemyMoveset(Moves.SPLASH)
.starterSpecies(Species.FEEBAS)
.ability(Abilities.BALL_FETCH)
.moveset([ Moves.FREEZE_DRY ]);
.moveset([ Moves.FREEZE_DRY, Moves.FORESTS_CURSE, Moves.SOAK ]);
});
it("should deal 2x damage to pure water types", async () => {
@ -98,6 +99,71 @@ describe("Moves - Freeze-Dry", () => {
expect(enemy.hp).toBeLessThan(enemy.getMaxHp());
});
it("should deal 8x damage to water/ground/grass type under Forest's Curse", async () => {
game.override.enemySpecies(Species.QUAGSIRE);
await game.classicMode.startBattle();
const enemy = game.scene.getEnemyPokemon()!;
vi.spyOn(enemy, "getMoveEffectiveness");
game.move.select(Moves.FORESTS_CURSE);
await game.toNextTurn();
game.move.select(Moves.FREEZE_DRY);
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]);
await game.phaseInterceptor.to("MoveEffectPhase");
expect(enemy.getMoveEffectiveness).toHaveReturnedWith(8);
});
it("should deal 2x damage to steel type terastallized into water", async () => {
game.override.enemySpecies(Species.SKARMORY)
.enemyHeldItems([{ name: "TERA_SHARD", type: Type.WATER }]);
await game.classicMode.startBattle();
const enemy = game.scene.getEnemyPokemon()!;
vi.spyOn(enemy, "getMoveEffectiveness");
game.move.select(Moves.FREEZE_DRY);
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]);
await game.phaseInterceptor.to("MoveEffectPhase");
expect(enemy.getMoveEffectiveness).toHaveReturnedWith(2);
});
it("should deal 0.5x damage to water type terastallized into fire", async () => {
game.override.enemySpecies(Species.PELIPPER)
.enemyHeldItems([{ name: "TERA_SHARD", type: Type.FIRE }]);
await game.classicMode.startBattle();
const enemy = game.scene.getEnemyPokemon()!;
vi.spyOn(enemy, "getMoveEffectiveness");
game.move.select(Moves.FREEZE_DRY);
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]);
await game.phaseInterceptor.to("MoveEffectPhase");
expect(enemy.getMoveEffectiveness).toHaveReturnedWith(0.5);
});
it("should deal 0.5x damage to water type Terapagos with Tera Shell", async () => {
game.override.enemySpecies(Species.TERAPAGOS)
.enemyAbility(Abilities.TERA_SHELL);
await game.classicMode.startBattle();
const enemy = game.scene.getEnemyPokemon()!;
vi.spyOn(enemy, "getMoveEffectiveness");
game.move.select(Moves.SOAK);
await game.toNextTurn();
game.move.select(Moves.FREEZE_DRY);
await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]);
await game.phaseInterceptor.to("MoveEffectPhase");
expect(enemy.getMoveEffectiveness).toHaveReturnedWith(0.5);
});
it("should deal 2x damage to water type under Normalize", async () => {
game.override.ability(Abilities.NORMALIZE);
await game.classicMode.startBattle();

View File

@ -62,7 +62,7 @@ describe("Moves - Gastro Acid", () => {
});
it("fails if used on an enemy with an already-suppressed ability", async () => {
game.override.battleType(null);
game.override.battleType("single");
await game.startBattle();

View File

@ -4,7 +4,7 @@ import { Abilities } from "#app/enums/abilities";
import * as GameMode from "#app/game-mode";
import { GameModes, getGameMode } from "#app/game-mode";
import { ModifierOverride } from "#app/modifier/modifier-type";
import Overrides from "#app/overrides";
import Overrides, { BattleStyle } from "#app/overrides";
import { Unlockables } from "#app/system/unlockables";
import { Biome } from "#enums/biome";
import { Moves } from "#enums/moves";
@ -238,13 +238,14 @@ export class OverridesHelper extends GameManagerHelper {
}
/**
* Override the battle type (single or double)
* Override the battle type (e.g., single or double).
* @see {@linkcode Overrides.BATTLE_TYPE_OVERRIDE}
* @param battleType battle type to set
* @returns `this`
*/
public battleType(battleType: "single" | "double" | null): this {
public battleType(battleType: BattleStyle | null): this {
vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue(battleType);
this.log(`Battle type set to ${battleType} only!`);
this.log(battleType === null ? "Battle type override disabled!" : `Battle type set to ${battleType}!`);
return this;
}