[Refactor] Replace forceBypass with bypassFaint flag (#1839)
* replace forceBypass with bypassFaint flag * add another path alias for src/test * make form override work for the whole party instead of the first pokemon * add tests for all abilities that are touched by this change * remove unnecessary overrides from tests * move SpeciesFormChangeTimeOfDayTrigger outside arena reset logic * remove alll resetMock calls, rename it to test
This commit is contained in:
parent
16e14376c6
commit
0970c2cd4e
|
@ -54,6 +54,7 @@
|
|||
},
|
||||
"imports": {
|
||||
"#app": "./src/main.js",
|
||||
"#app/*": "./src/*"
|
||||
"#app/*": "./src/*",
|
||||
"#test/*": "./src/test/*"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1098,18 +1098,18 @@ export default class BattleScene extends SceneBase {
|
|||
if (pokemon.hasAbility(Abilities.ICE_FACE)) {
|
||||
pokemon.formIndex = 0;
|
||||
}
|
||||
|
||||
pokemon.resetBattleData();
|
||||
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, pokemon);
|
||||
}
|
||||
|
||||
this.unshiftPhase(new ShowTrainerPhase(this));
|
||||
}
|
||||
|
||||
for (const pokemon of this.getParty()) {
|
||||
if (pokemon) {
|
||||
if (resetArenaState) {
|
||||
pokemon.resetBattleData();
|
||||
applyPostBattleInitAbAttrs(PostBattleInitAbAttr, pokemon, true);
|
||||
}
|
||||
this.triggerPokemonFormChange(pokemon, SpeciesFormChangeTimeOfDayTrigger);
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.gameMode.hasRandomBiomes && !isNewBiome) {
|
||||
this.pushPhase(new NextEncounterPhase(this));
|
||||
} else {
|
||||
|
|
|
@ -3525,7 +3525,7 @@ export class IceFaceMoveImmunityAbAttr extends MoveImmunityAbAttr {
|
|||
function applyAbAttrsInternal<TAttr extends AbAttr>(attrType: { new(...args: any[]): TAttr },
|
||||
pokemon: Pokemon, applyFunc: AbAttrApplyFunc<TAttr>, args: any[], isAsync: boolean = false, showAbilityInstant: boolean = false, quiet: boolean = false, passive: boolean = false): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
if (!pokemon.canApplyAbility(passive, args[0])) {
|
||||
if (!pokemon.canApplyAbility(passive)) {
|
||||
if (!passive) {
|
||||
return applyAbAttrsInternal(attrType, pokemon, applyFunc, args, isAsync, showAbilityInstant, quiet, true).then(() => resolve());
|
||||
} else {
|
||||
|
@ -4238,7 +4238,8 @@ export function initAbilities() {
|
|||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(UnsuppressableAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr),
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.bypassFaint(),
|
||||
new Ability(Abilities.VICTORY_STAR, 5)
|
||||
.attr(BattleStatMultiplierAbAttr, BattleStat.ACC, 1.1)
|
||||
.partial(),
|
||||
|
@ -4347,6 +4348,7 @@ export function initAbilities() {
|
|||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(UnsuppressableAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.bypassFaint()
|
||||
.partial(),
|
||||
new Ability(Abilities.STAKEOUT, 7)
|
||||
.attr(MovePowerBoostAbAttr, (user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()].command === Command.POKEMON, 2),
|
||||
|
@ -4379,7 +4381,8 @@ export function initAbilities() {
|
|||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(UnsuppressableAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr),
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.bypassFaint(),
|
||||
new Ability(Abilities.DISGUISE, 7)
|
||||
.attr(PreDefendMovePowerToOneAbAttr, (target, user, move) => target.formIndex === 0 && target.getAttackTypeEffectiveness(move.type, user) > 0)
|
||||
.attr(PostSummonFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1)
|
||||
|
@ -4392,6 +4395,7 @@ export function initAbilities() {
|
|||
.attr(UnsuppressableAbilityAbAttr)
|
||||
.attr(NoTransformAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.bypassFaint()
|
||||
.ignorable()
|
||||
.partial(),
|
||||
new Ability(Abilities.BATTLE_BOND, 7)
|
||||
|
@ -4400,7 +4404,8 @@ export function initAbilities() {
|
|||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(UnsuppressableAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr),
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.bypassFaint(),
|
||||
new Ability(Abilities.POWER_CONSTRUCT, 7) // TODO: 10% Power Construct Zygarde isn't accounted for yet. If changed, update Zygarde's getSpeciesFormIndex entry accordingly
|
||||
.attr(PostBattleInitFormChangeAbAttr, () => 2)
|
||||
.attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2)
|
||||
|
@ -4409,6 +4414,7 @@ export function initAbilities() {
|
|||
.attr(UnswappableAbilityAbAttr)
|
||||
.attr(UnsuppressableAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.bypassFaint()
|
||||
.partial(),
|
||||
new Ability(Abilities.CORROSION, 7) // TODO: Test Corrosion against Magic Bounce once it is implemented
|
||||
.attr(IgnoreTypeStatusEffectImmunityAbAttr, [StatusEffect.POISON, StatusEffect.TOXIC], [Type.STEEL, Type.POISON])
|
||||
|
@ -4639,7 +4645,8 @@ export function initAbilities() {
|
|||
.attr(NoTransformAbilityAbAttr)
|
||||
.attr(NoFusionAbilityAbAttr)
|
||||
.attr(PostBattleInitFormChangeAbAttr, () => 0)
|
||||
.attr(PreSwitchOutFormChangeAbAttr, () => 1),
|
||||
.attr(PreSwitchOutFormChangeAbAttr, () => 1)
|
||||
.bypassFaint(),
|
||||
new Ability(Abilities.COMMANDER, 9)
|
||||
.attr(UncopiableAbilityAbAttr)
|
||||
.attr(UnswappableAbilityAbAttr)
|
||||
|
|
|
@ -1004,7 +1004,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
* @param {boolean} passive If true, check if passive can be applied instead of non-passive
|
||||
* @returns {Ability} The passive ability of the pokemon
|
||||
*/
|
||||
canApplyAbility(passive: boolean = false, forceBypass: boolean = false): boolean {
|
||||
canApplyAbility(passive: boolean = false): boolean {
|
||||
if (passive && !this.hasPassive()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1032,7 +1032,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
return (this.hp || ability.isBypassFaint || forceBypass) && !ability.conditions.find(condition => !condition(this));
|
||||
return (this.hp || ability.isBypassFaint) && !ability.conditions.find(condition => !condition(this));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,6 +15,7 @@ import {TimeOfDay} from "#app/data/enums/time-of-day";
|
|||
import { Gender } from "./data/gender";
|
||||
import { StatusEffect } from "./data/status-effect";
|
||||
import { modifierTypes } from "./modifier/modifier-type";
|
||||
import { allSpecies } from "./data/pokemon-species"; // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
|
||||
/**
|
||||
* Overrides for testing different in game situations
|
||||
|
@ -53,8 +54,18 @@ export const POKEBALL_OVERRIDE: { active: boolean, pokeballs: PokeballCounts } =
|
|||
* PLAYER OVERRIDES
|
||||
*/
|
||||
|
||||
// forms can be found in pokemon-species.ts
|
||||
export const STARTER_FORM_OVERRIDE: integer = 0;
|
||||
/**
|
||||
* Set the form index of any starter in the party whose `speciesId` is inside this override
|
||||
* @see {@link allSpecies} in `src/data/pokemon-species.ts` for form indexes
|
||||
* @example
|
||||
* ```
|
||||
* const STARTER_FORM_OVERRIDES = {
|
||||
* [Species.DARMANITAN]: 1
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export const STARTER_FORM_OVERRIDES: Partial<Record<Species, number>> = {};
|
||||
|
||||
// default 5 or 20 for Daily
|
||||
export const STARTING_LEVEL_OVERRIDE: integer = 0;
|
||||
/**
|
||||
|
|
|
@ -555,6 +555,10 @@ export class SelectStarterPhase extends Phase {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize starters before starting the first battle
|
||||
* @param starters {@linkcode Pokemon} with which to start the first battle
|
||||
*/
|
||||
initBattle(starters: Starter[]) {
|
||||
const party = this.scene.getParty();
|
||||
const loadPokemonAssets: Promise<void>[] = [];
|
||||
|
@ -564,9 +568,13 @@ export class SelectStarterPhase extends Phase {
|
|||
}
|
||||
const starterProps = this.scene.gameData.getSpeciesDexAttrProps(starter.species, starter.dexAttr);
|
||||
let starterFormIndex = Math.min(starterProps.formIndex, Math.max(starter.species.forms.length - 1, 0));
|
||||
if (!i && Overrides.STARTER_SPECIES_OVERRIDE) {
|
||||
starterFormIndex = Overrides.STARTER_FORM_OVERRIDE;
|
||||
if (
|
||||
starter.species.speciesId in Overrides.STARTER_FORM_OVERRIDES &&
|
||||
starter.species.forms[Overrides.STARTER_FORM_OVERRIDES[starter.species.speciesId]]
|
||||
) {
|
||||
starterFormIndex = Overrides.STARTER_FORM_OVERRIDES[starter.species.speciesId];
|
||||
}
|
||||
|
||||
let starterGender = starter.species.malePercent !== null
|
||||
? !starterProps.female ? Gender.MALE : Gender.FEMALE
|
||||
: Gender.GENDERLESS;
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import { getMovePosition } from "#test/utils/gameManagerUtils";
|
||||
import * as Overrides from "#app/overrides";
|
||||
import { Moves } from "#app/data/enums/moves.js";
|
||||
import { Abilities } from "#app/data/enums/abilities.js";
|
||||
import { Species } from "#app/data/enums/species.js";
|
||||
import { Status, StatusEffect } from "#app/data/status-effect.js";
|
||||
import { TurnEndPhase } from "#app/phases.js";
|
||||
import { QuietFormChangePhase } from "#app/form-change-phase.js";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
|
||||
describe("Abilities - BATTLE BOND", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
const moveToUse = Moves.SPLASH;
|
||||
vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||
vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.BATTLE_BOND);
|
||||
vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
|
||||
vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
|
||||
});
|
||||
|
||||
test(
|
||||
"check if fainted pokemon switches to base form on arena reset",
|
||||
async () => {
|
||||
const baseForm = 1,
|
||||
ashForm = 2;
|
||||
vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(4);
|
||||
vi.spyOn(Overrides, "STARTER_FORM_OVERRIDES", "get").mockReturnValue({
|
||||
[Species.GRENINJA]: ashForm,
|
||||
});
|
||||
|
||||
await game.startBattle([Species.MAGIKARP, Species.GRENINJA]);
|
||||
|
||||
const greninja = game.scene.getParty().find((p) => p.species.speciesId === Species.GRENINJA);
|
||||
expect(greninja).not.toBe(undefined);
|
||||
expect(greninja.formIndex).toBe(ashForm);
|
||||
|
||||
greninja.hp = 0;
|
||||
greninja.status = new Status(StatusEffect.FAINT);
|
||||
expect(greninja.isFainted()).toBe(true);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
await game.doKillOpponents();
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
game.doSelectModifier();
|
||||
await game.phaseInterceptor.to(QuietFormChangePhase);
|
||||
|
||||
expect(greninja.formIndex).toBe(baseForm);
|
||||
},
|
||||
TIMEOUT
|
||||
);
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import { getMovePosition } from "#test/utils/gameManagerUtils";
|
||||
import * as Overrides from "#app/overrides";
|
||||
import { Moves } from "#app/data/enums/moves.js";
|
||||
import { Abilities } from "#app/data/enums/abilities.js";
|
||||
import { Species } from "#app/data/enums/species.js";
|
||||
import { Status, StatusEffect } from "#app/data/status-effect.js";
|
||||
import { TurnEndPhase } from "#app/phases.js";
|
||||
import { QuietFormChangePhase } from "#app/form-change-phase.js";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
|
||||
describe("Abilities - DISGUISE", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
const moveToUse = Moves.SPLASH;
|
||||
vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||
vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.DISGUISE);
|
||||
vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
|
||||
vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
|
||||
});
|
||||
|
||||
test(
|
||||
"check if fainted pokemon switched to base form on arena reset",
|
||||
async () => {
|
||||
const baseForm = 0,
|
||||
bustedForm = 1;
|
||||
vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(4);
|
||||
vi.spyOn(Overrides, "STARTER_FORM_OVERRIDES", "get").mockReturnValue({
|
||||
[Species.MIMIKYU]: bustedForm,
|
||||
});
|
||||
|
||||
await game.startBattle([Species.MAGIKARP, Species.MIMIKYU]);
|
||||
|
||||
const mimikyu = game.scene.getParty().find((p) => p.species.speciesId === Species.MIMIKYU);
|
||||
expect(mimikyu).not.toBe(undefined);
|
||||
expect(mimikyu.formIndex).toBe(bustedForm);
|
||||
|
||||
mimikyu.hp = 0;
|
||||
mimikyu.status = new Status(StatusEffect.FAINT);
|
||||
expect(mimikyu.isFainted()).toBe(true);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
await game.doKillOpponents();
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
game.doSelectModifier();
|
||||
await game.phaseInterceptor.to(QuietFormChangePhase);
|
||||
|
||||
expect(mimikyu.formIndex).toBe(baseForm);
|
||||
},
|
||||
TIMEOUT
|
||||
);
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import { getMovePosition } from "#test/utils/gameManagerUtils";
|
||||
import * as Overrides from "#app/overrides";
|
||||
import { Moves } from "#app/data/enums/moves.js";
|
||||
import { Abilities } from "#app/data/enums/abilities.js";
|
||||
import { Species } from "#app/data/enums/species.js";
|
||||
import { Status, StatusEffect } from "#app/data/status-effect.js";
|
||||
import { TurnEndPhase } from "#app/phases.js";
|
||||
import { QuietFormChangePhase } from "#app/form-change-phase.js";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
|
||||
describe("Abilities - POWER CONSTRUCT", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
const moveToUse = Moves.SPLASH;
|
||||
vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||
vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.POWER_CONSTRUCT);
|
||||
vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
|
||||
vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
|
||||
});
|
||||
|
||||
test(
|
||||
"check if fainted pokemon switches to base form on arena reset",
|
||||
async () => {
|
||||
const baseForm = 2,
|
||||
completeForm = 4;
|
||||
vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(4);
|
||||
vi.spyOn(Overrides, "STARTER_FORM_OVERRIDES", "get").mockReturnValue({
|
||||
[Species.ZYGARDE]: completeForm,
|
||||
});
|
||||
|
||||
await game.startBattle([Species.MAGIKARP, Species.ZYGARDE]);
|
||||
|
||||
const zygarde = game.scene.getParty().find((p) => p.species.speciesId === Species.ZYGARDE);
|
||||
expect(zygarde).not.toBe(undefined);
|
||||
expect(zygarde.formIndex).toBe(completeForm);
|
||||
|
||||
zygarde.hp = 0;
|
||||
zygarde.status = new Status(StatusEffect.FAINT);
|
||||
expect(zygarde.isFainted()).toBe(true);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
await game.doKillOpponents();
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
game.doSelectModifier();
|
||||
await game.phaseInterceptor.to(QuietFormChangePhase);
|
||||
|
||||
expect(zygarde.formIndex).toBe(baseForm);
|
||||
},
|
||||
TIMEOUT
|
||||
);
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import { getMovePosition } from "#test/utils/gameManagerUtils";
|
||||
import * as Overrides from "#app/overrides";
|
||||
import { Moves } from "#app/data/enums/moves.js";
|
||||
import { Abilities } from "#app/data/enums/abilities.js";
|
||||
import { Species } from "#app/data/enums/species.js";
|
||||
import { Status, StatusEffect } from "#app/data/status-effect.js";
|
||||
import { TurnEndPhase } from "#app/phases.js";
|
||||
import { QuietFormChangePhase } from "#app/form-change-phase.js";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
|
||||
describe("Abilities - SCHOOLING", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
const moveToUse = Moves.SPLASH;
|
||||
vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||
vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SCHOOLING);
|
||||
vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
|
||||
vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
|
||||
});
|
||||
|
||||
test(
|
||||
"check if fainted pokemon switches to base form on arena reset",
|
||||
async () => {
|
||||
const soloForm = 0,
|
||||
schoolForm = 1;
|
||||
vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(4);
|
||||
vi.spyOn(Overrides, "STARTER_FORM_OVERRIDES", "get").mockReturnValue({
|
||||
[Species.WISHIWASHI]: schoolForm,
|
||||
});
|
||||
|
||||
await game.startBattle([Species.MAGIKARP, Species.WISHIWASHI]);
|
||||
|
||||
const wishiwashi = game.scene.getParty().find((p) => p.species.speciesId === Species.WISHIWASHI);
|
||||
expect(wishiwashi).not.toBe(undefined);
|
||||
expect(wishiwashi.formIndex).toBe(schoolForm);
|
||||
|
||||
wishiwashi.hp = 0;
|
||||
wishiwashi.status = new Status(StatusEffect.FAINT);
|
||||
expect(wishiwashi.isFainted()).toBe(true);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
await game.doKillOpponents();
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
game.doSelectModifier();
|
||||
await game.phaseInterceptor.to(QuietFormChangePhase);
|
||||
|
||||
expect(wishiwashi.formIndex).toBe(soloForm);
|
||||
},
|
||||
TIMEOUT
|
||||
);
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import { getMovePosition } from "#test/utils/gameManagerUtils";
|
||||
import * as Overrides from "#app/overrides";
|
||||
import { Moves } from "#app/data/enums/moves.js";
|
||||
import { Abilities } from "#app/data/enums/abilities.js";
|
||||
import { Species } from "#app/data/enums/species.js";
|
||||
import { Status, StatusEffect } from "#app/data/status-effect.js";
|
||||
import { TurnEndPhase } from "#app/phases.js";
|
||||
import { QuietFormChangePhase } from "#app/form-change-phase.js";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
|
||||
describe("Abilities - SHIELDS DOWN", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
const moveToUse = Moves.SPLASH;
|
||||
vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||
vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.SHIELDS_DOWN);
|
||||
vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
|
||||
vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
|
||||
});
|
||||
|
||||
test(
|
||||
"check if fainted pokemon switched to base form on arena reset",
|
||||
async () => {
|
||||
const meteorForm = 0,
|
||||
coreForm = 7;
|
||||
vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(4);
|
||||
vi.spyOn(Overrides, "STARTER_FORM_OVERRIDES", "get").mockReturnValue({
|
||||
[Species.MINIOR]: coreForm,
|
||||
});
|
||||
|
||||
await game.startBattle([Species.MAGIKARP, Species.MINIOR]);
|
||||
|
||||
const minior = game.scene.getParty().find((p) => p.species.speciesId === Species.MINIOR);
|
||||
expect(minior).not.toBe(undefined);
|
||||
expect(minior.formIndex).toBe(coreForm);
|
||||
|
||||
minior.hp = 0;
|
||||
minior.status = new Status(StatusEffect.FAINT);
|
||||
expect(minior.isFainted()).toBe(true);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
await game.doKillOpponents();
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
game.doSelectModifier();
|
||||
await game.phaseInterceptor.to(QuietFormChangePhase);
|
||||
|
||||
expect(minior.formIndex).toBe(meteorForm);
|
||||
},
|
||||
TIMEOUT
|
||||
);
|
||||
});
|
|
@ -1,9 +1,9 @@
|
|||
import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import Phaser from "phaser";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import * as overrides from "#app/overrides";
|
||||
import {Abilities} from "#app/data/enums/abilities";
|
||||
import {Species} from "#app/data/enums/species";
|
||||
import * as Overrides from "#app/overrides";
|
||||
import { Abilities } from "#app/data/enums/abilities";
|
||||
import { Species } from "#app/data/enums/species";
|
||||
import {
|
||||
CommandPhase,
|
||||
DamagePhase,
|
||||
|
@ -12,18 +12,21 @@ import {
|
|||
PostSummonPhase,
|
||||
SwitchPhase,
|
||||
SwitchSummonPhase,
|
||||
TurnEndPhase, TurnInitPhase,
|
||||
TurnEndPhase,
|
||||
TurnInitPhase,
|
||||
TurnStartPhase,
|
||||
} from "#app/phases";
|
||||
import {Mode} from "#app/ui/ui";
|
||||
import {Stat} from "#app/data/pokemon-stat";
|
||||
import {Moves} from "#app/data/enums/moves";
|
||||
import {getMovePosition} from "#app/test/utils/gameManagerUtils";
|
||||
import {Command} from "#app/ui/command-ui-handler";
|
||||
import {QuietFormChangePhase} from "#app/form-change-phase";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import { Stat } from "#app/data/pokemon-stat";
|
||||
import { Moves } from "#app/data/enums/moves";
|
||||
import { getMovePosition } from "#app/test/utils/gameManagerUtils";
|
||||
import { Command } from "#app/ui/command-ui-handler";
|
||||
import { QuietFormChangePhase } from "#app/form-change-phase";
|
||||
import { Status, StatusEffect } from "#app/data/status-effect.js";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
|
||||
describe("Abilities - Zen mode", () => {
|
||||
describe("Abilities - ZEN MODE", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
|
@ -40,20 +43,20 @@ describe("Abilities - Zen mode", () => {
|
|||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
const moveToUse = Moves.SPLASH;
|
||||
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
|
||||
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
||||
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE);
|
||||
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100);
|
||||
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
|
||||
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]);
|
||||
vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||
vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
|
||||
vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
||||
vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE);
|
||||
vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100);
|
||||
vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
|
||||
vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
|
||||
});
|
||||
|
||||
it("ZEN MODE - not enough damage to change form", async() => {
|
||||
test(
|
||||
"not enough damage to change form",
|
||||
async () => {
|
||||
const moveToUse = Moves.SPLASH;
|
||||
await game.startBattle([
|
||||
Species.DARMANITAN,
|
||||
]);
|
||||
await game.startBattle([Species.DARMANITAN]);
|
||||
game.scene.getParty()[0].stats[Stat.SPD] = 1;
|
||||
game.scene.getParty()[0].stats[Stat.HP] = 100;
|
||||
game.scene.getParty()[0].hp = 100;
|
||||
|
@ -73,13 +76,15 @@ describe("Abilities - Zen mode", () => {
|
|||
await game.phaseInterceptor.runFrom(DamagePhase).to(TurnEndPhase, false);
|
||||
expect(game.scene.getParty()[0].hp).toBeLessThan(100);
|
||||
expect(game.scene.getParty()[0].formIndex).toBe(0);
|
||||
}, 20000);
|
||||
},
|
||||
TIMEOUT
|
||||
);
|
||||
|
||||
it("ZEN MODE - enough damage to change form", async() => {
|
||||
test(
|
||||
"enough damage to change form",
|
||||
async () => {
|
||||
const moveToUse = Moves.SPLASH;
|
||||
await game.startBattle([
|
||||
Species.DARMANITAN,
|
||||
]);
|
||||
await game.startBattle([Species.DARMANITAN]);
|
||||
game.scene.getParty()[0].stats[Stat.SPD] = 1;
|
||||
game.scene.getParty()[0].stats[Stat.HP] = 1000;
|
||||
game.scene.getParty()[0].hp = 100;
|
||||
|
@ -96,14 +101,15 @@ describe("Abilities - Zen mode", () => {
|
|||
await game.phaseInterceptor.to(TurnInitPhase, false);
|
||||
expect(game.scene.getParty()[0].hp).not.toBe(100);
|
||||
expect(game.scene.getParty()[0].formIndex).not.toBe(0);
|
||||
}, 20000);
|
||||
},
|
||||
TIMEOUT
|
||||
);
|
||||
|
||||
it("ZEN MODE - kill pokemon while on zen mode", async() => {
|
||||
test(
|
||||
"kill pokemon while on zen mode",
|
||||
async () => {
|
||||
const moveToUse = Moves.SPLASH;
|
||||
await game.startBattle([
|
||||
Species.DARMANITAN,
|
||||
Species.CHARIZARD,
|
||||
]);
|
||||
await game.startBattle([Species.DARMANITAN, Species.CHARIZARD]);
|
||||
game.scene.getParty()[0].stats[Stat.SPD] = 1;
|
||||
game.scene.getParty()[0].stats[Stat.HP] = 1000;
|
||||
game.scene.getParty()[0].hp = 100;
|
||||
|
@ -138,5 +144,38 @@ describe("Abilities - Zen mode", () => {
|
|||
await game.phaseInterceptor.run(SwitchPhase);
|
||||
await game.phaseInterceptor.to(PostSummonPhase);
|
||||
expect(game.scene.getParty()[1].formIndex).toBe(1);
|
||||
}, 20000);
|
||||
},
|
||||
TIMEOUT
|
||||
);
|
||||
|
||||
test(
|
||||
"check if fainted pokemon switches to base form on arena reset",
|
||||
async () => {
|
||||
const baseForm = 0,
|
||||
zenForm = 1;
|
||||
vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(4);
|
||||
vi.spyOn(Overrides, "STARTER_FORM_OVERRIDES", "get").mockReturnValue({
|
||||
[Species.DARMANITAN]: zenForm,
|
||||
});
|
||||
|
||||
await game.startBattle([Species.MAGIKARP, Species.DARMANITAN]);
|
||||
|
||||
const darmanitan = game.scene.getParty().find((p) => p.species.speciesId === Species.DARMANITAN);
|
||||
expect(darmanitan).not.toBe(undefined);
|
||||
expect(darmanitan.formIndex).toBe(zenForm);
|
||||
|
||||
darmanitan.hp = 0;
|
||||
darmanitan.status = new Status(StatusEffect.FAINT);
|
||||
expect(darmanitan.isFainted()).toBe(true);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
await game.doKillOpponents();
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
game.doSelectModifier();
|
||||
await game.phaseInterceptor.to(QuietFormChangePhase);
|
||||
|
||||
expect(darmanitan.formIndex).toBe(baseForm);
|
||||
},
|
||||
TIMEOUT
|
||||
);
|
||||
});
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import { getMovePosition } from "#test/utils/gameManagerUtils";
|
||||
import * as Overrides from "#app/overrides";
|
||||
import { Moves } from "#app/data/enums/moves.js";
|
||||
import { Abilities } from "#app/data/enums/abilities.js";
|
||||
import { Species } from "#app/data/enums/species.js";
|
||||
import { Status, StatusEffect } from "#app/data/status-effect.js";
|
||||
import { TurnEndPhase } from "#app/phases.js";
|
||||
import { QuietFormChangePhase } from "#app/form-change-phase.js";
|
||||
|
||||
const TIMEOUT = 20 * 1000;
|
||||
|
||||
describe("Abilities - ZERO TO HERO", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
const moveToUse = Moves.SPLASH;
|
||||
vi.spyOn(Overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||
vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZERO_TO_HERO);
|
||||
vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
|
||||
vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
|
||||
});
|
||||
|
||||
test(
|
||||
"check if fainted pokemon switches to base form on arena reset",
|
||||
async () => {
|
||||
const baseForm = 0,
|
||||
heroForm = 1;
|
||||
vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(4);
|
||||
vi.spyOn(Overrides, "STARTER_FORM_OVERRIDES", "get").mockReturnValue({
|
||||
[Species.PALAFIN]: heroForm,
|
||||
});
|
||||
|
||||
await game.startBattle([Species.MAGIKARP, Species.PALAFIN]);
|
||||
|
||||
const palafin = game.scene.getParty().find((p) => p.species.speciesId === Species.PALAFIN);
|
||||
expect(palafin).not.toBe(undefined);
|
||||
expect(palafin.formIndex).toBe(heroForm);
|
||||
|
||||
palafin.hp = 0;
|
||||
palafin.status = new Status(StatusEffect.FAINT);
|
||||
expect(palafin.isFainted()).toBe(true);
|
||||
|
||||
game.doAttack(getMovePosition(game.scene, 0, Moves.SPLASH));
|
||||
await game.doKillOpponents();
|
||||
await game.phaseInterceptor.to(TurnEndPhase);
|
||||
game.doSelectModifier();
|
||||
await game.phaseInterceptor.to(QuietFormChangePhase);
|
||||
|
||||
expect(palafin.formIndex).toBe(baseForm);
|
||||
},
|
||||
TIMEOUT
|
||||
);
|
||||
});
|
|
@ -12,7 +12,8 @@
|
|||
"baseUrl": "./src",
|
||||
"paths": {
|
||||
"#app/*": ["*.ts"],
|
||||
"#app": ["."]
|
||||
"#app": ["."],
|
||||
"#test/*": ["./test/*.ts"]
|
||||
},
|
||||
"outDir": "./build",
|
||||
"noEmit": true
|
||||
|
|
Loading…
Reference in New Issue