mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-09 08:59:29 +02:00
Merge branch 'beta' into Court-Change-Additions
This commit is contained in:
commit
36ec4c3d3c
@ -30,19 +30,19 @@
|
|||||||
"@biomejs/biome": "2.0.0",
|
"@biomejs/biome": "2.0.0",
|
||||||
"@ls-lint/ls-lint": "2.3.1",
|
"@ls-lint/ls-lint": "2.3.1",
|
||||||
"@types/jsdom": "^21.1.7",
|
"@types/jsdom": "^21.1.7",
|
||||||
"@types/node": "^22.16.3",
|
"@types/node": "^22.16.5",
|
||||||
"@vitest/coverage-istanbul": "^3.2.4",
|
"@vitest/coverage-istanbul": "^3.2.4",
|
||||||
"@vitest/expect": "^3.2.4",
|
"@vitest/expect": "^3.2.4",
|
||||||
"chalk": "^5.4.1",
|
"chalk": "^5.4.1",
|
||||||
"dependency-cruiser": "^16.10.4",
|
"dependency-cruiser": "^16.10.4",
|
||||||
"inquirer": "^12.7.0",
|
"inquirer": "^12.8.2",
|
||||||
"jsdom": "^26.1.0",
|
"jsdom": "^26.1.0",
|
||||||
"lefthook": "^1.12.2",
|
"lefthook": "^1.12.2",
|
||||||
"msw": "^2.10.4",
|
"msw": "^2.10.4",
|
||||||
"phaser3spectorjs": "^0.0.8",
|
"phaser3spectorjs": "^0.0.8",
|
||||||
"typedoc": "^0.28.7",
|
"typedoc": "^0.28.8",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"vite": "^6.3.5",
|
"vite": "^7.0.6",
|
||||||
"vite-tsconfig-paths": "^5.1.4",
|
"vite-tsconfig-paths": "^5.1.4",
|
||||||
"vitest": "^3.2.4",
|
"vitest": "^3.2.4",
|
||||||
"vitest-canvas-mock": "^0.3.3"
|
"vitest-canvas-mock": "^0.3.3"
|
||||||
|
918
pnpm-lock.yaml
918
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
119
src/@types/battler-tags.ts
Normal file
119
src/@types/battler-tags.ts
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// biome-ignore-start lint/correctness/noUnusedImports: Used in a TSDoc comment
|
||||||
|
import type { AbilityBattlerTag, BattlerTagTypeMap, SerializableBattlerTag, TypeBoostTag } from "#data/battler-tags";
|
||||||
|
import type { AbilityId } from "#enums/ability-id";
|
||||||
|
// biome-ignore-end lint/correctness/noUnusedImports: end
|
||||||
|
import type { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subset of {@linkcode BattlerTagType}s that restrict the use of moves.
|
||||||
|
*/
|
||||||
|
export type MoveRestrictionBattlerTagType =
|
||||||
|
| BattlerTagType.THROAT_CHOPPED
|
||||||
|
| BattlerTagType.TORMENT
|
||||||
|
| BattlerTagType.TAUNT
|
||||||
|
| BattlerTagType.IMPRISON
|
||||||
|
| BattlerTagType.HEAL_BLOCK
|
||||||
|
| BattlerTagType.ENCORE
|
||||||
|
| BattlerTagType.DISABLED
|
||||||
|
| BattlerTagType.GORILLA_TACTICS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subset of {@linkcode BattlerTagType}s that block damage from moves.
|
||||||
|
*/
|
||||||
|
export type FormBlockDamageBattlerTagType = BattlerTagType.ICE_FACE | BattlerTagType.DISGUISE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subset of {@linkcode BattlerTagType}s that are related to trapping effects.
|
||||||
|
*/
|
||||||
|
export type TrappingBattlerTagType =
|
||||||
|
| BattlerTagType.BIND
|
||||||
|
| BattlerTagType.WRAP
|
||||||
|
| BattlerTagType.FIRE_SPIN
|
||||||
|
| BattlerTagType.WHIRLPOOL
|
||||||
|
| BattlerTagType.CLAMP
|
||||||
|
| BattlerTagType.SAND_TOMB
|
||||||
|
| BattlerTagType.MAGMA_STORM
|
||||||
|
| BattlerTagType.SNAP_TRAP
|
||||||
|
| BattlerTagType.THUNDER_CAGE
|
||||||
|
| BattlerTagType.INFESTATION
|
||||||
|
| BattlerTagType.INGRAIN
|
||||||
|
| BattlerTagType.OCTOLOCK
|
||||||
|
| BattlerTagType.NO_RETREAT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subset of {@linkcode BattlerTagType}s that are related to protection effects.
|
||||||
|
*/
|
||||||
|
export type ProtectionBattlerTagType = BattlerTagType.PROTECTED | BattlerTagType.SPIKY_SHIELD | DamageProtectedTagType;
|
||||||
|
/**
|
||||||
|
* Subset of {@linkcode BattlerTagType}s related to protection effects that block damage but not status moves.
|
||||||
|
*/
|
||||||
|
export type DamageProtectedTagType = ContactSetStatusProtectedTagType | ContactStatStageChangeProtectedTagType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subset of {@linkcode BattlerTagType}s related to protection effects that set a status effect on the attacker.
|
||||||
|
*/
|
||||||
|
export type ContactSetStatusProtectedTagType = BattlerTagType.BANEFUL_BUNKER | BattlerTagType.BURNING_BULWARK;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subset of {@linkcode BattlerTagType}s related to protection effects that change stat stages of the attacker.
|
||||||
|
*/
|
||||||
|
export type ContactStatStageChangeProtectedTagType =
|
||||||
|
| BattlerTagType.KINGS_SHIELD
|
||||||
|
| BattlerTagType.SILK_TRAP
|
||||||
|
| BattlerTagType.OBSTRUCT;
|
||||||
|
|
||||||
|
/** Subset of {@linkcode BattlerTagType}s that provide the Endure effect */
|
||||||
|
export type EndureTagType = BattlerTagType.ENDURE_TOKEN | BattlerTagType.ENDURING;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subset of {@linkcode BattlerTagType}s that are related to semi-invulnerable states.
|
||||||
|
*/
|
||||||
|
export type SemiInvulnerableTagType =
|
||||||
|
| BattlerTagType.FLYING
|
||||||
|
| BattlerTagType.UNDERGROUND
|
||||||
|
| BattlerTagType.UNDERWATER
|
||||||
|
| BattlerTagType.HIDDEN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subset of {@linkcode BattlerTagType}s corresponding to {@linkcode AbilityBattlerTag}s
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* ⚠️ {@linkcode AbilityId.FLASH_FIRE | Flash Fire}'s {@linkcode BattlerTagType.FIRE_BOOST} is not included as it
|
||||||
|
* subclasses {@linkcode TypeBoostTag} and not `AbilityBattlerTag`.
|
||||||
|
*/
|
||||||
|
export type AbilityBattlerTagType =
|
||||||
|
| BattlerTagType.PROTOSYNTHESIS
|
||||||
|
| BattlerTagType.QUARK_DRIVE
|
||||||
|
| BattlerTagType.UNBURDEN
|
||||||
|
| BattlerTagType.SLOW_START
|
||||||
|
| BattlerTagType.TRUANT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subset of {@linkcode BattlerTagType}s related to abilities that boost the highest stat.
|
||||||
|
*/
|
||||||
|
export type HighestStatBoostTagType =
|
||||||
|
| BattlerTagType.QUARK_DRIVE // formatting
|
||||||
|
| BattlerTagType.PROTOSYNTHESIS;
|
||||||
|
/**
|
||||||
|
* Subset of {@linkcode BattlerTagType}s that are able to persist between turns and should therefore be serialized
|
||||||
|
*/
|
||||||
|
export type SerializableBattlerTagType = keyof {
|
||||||
|
[K in keyof BattlerTagTypeMap as BattlerTagTypeMap[K] extends SerializableBattlerTag
|
||||||
|
? K
|
||||||
|
: never]: BattlerTagTypeMap[K];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subset of {@linkcode BattlerTagType}s that are not able to persist across waves and should therefore not be serialized
|
||||||
|
*/
|
||||||
|
export type NonSerializableBattlerTagType = Exclude<BattlerTagType, SerializableBattlerTagType>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy, typescript-only declaration to ensure that
|
||||||
|
* {@linkcode BattlerTagTypeMap} has an entry for all `BattlerTagType`s.
|
||||||
|
*
|
||||||
|
* If a battler tag is missing from the map, Typescript will throw an error on this statement.
|
||||||
|
*
|
||||||
|
* ⚠️ Does not actually exist at runtime, so it must not be used!
|
||||||
|
*/
|
||||||
|
declare const EnsureAllBattlerTagTypesAreMapped: BattlerTagTypeMap[BattlerTagType] & never;
|
File diff suppressed because it is too large
Load Diff
@ -10800,7 +10800,7 @@ export function initMoves() {
|
|||||||
new SelfStatusMove(MoveId.NO_RETREAT, PokemonType.FIGHTING, -1, 5, -1, 0, 8)
|
new SelfStatusMove(MoveId.NO_RETREAT, PokemonType.FIGHTING, -1, 5, -1, 0, 8)
|
||||||
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true)
|
.attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.NO_RETREAT, true, false)
|
.attr(AddBattlerTagAttr, BattlerTagType.NO_RETREAT, true, false)
|
||||||
.condition((user, target, move) => user.getTag(TrappedTag)?.sourceMove !== MoveId.NO_RETREAT), // fails if the user is currently trapped by No Retreat
|
.condition((user, target, move) => user.getTag(TrappedTag)?.tagType !== BattlerTagType.NO_RETREAT), // fails if the user is currently trapped by No Retreat
|
||||||
new StatusMove(MoveId.TAR_SHOT, PokemonType.ROCK, 100, 15, -1, 0, 8)
|
new StatusMove(MoveId.TAR_SHOT, PokemonType.ROCK, 100, 15, -1, 0, 8)
|
||||||
.attr(StatStageChangeAttr, [ Stat.SPD ], -1)
|
.attr(StatStageChangeAttr, [ Stat.SPD ], -1)
|
||||||
.attr(AddBattlerTagAttr, BattlerTagType.TAR_SHOT, false)
|
.attr(AddBattlerTagAttr, BattlerTagType.TAR_SHOT, false)
|
||||||
|
@ -39,6 +39,7 @@ import { addPokemonDataToDexAndValidateAchievements } from "#mystery-encounters/
|
|||||||
import type { MysteryEncounter } from "#mystery-encounters/mystery-encounter";
|
import type { MysteryEncounter } from "#mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
|
import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
|
||||||
import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
|
import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
|
||||||
|
import { PartySizeRequirement } from "#mystery-encounters/mystery-encounter-requirements";
|
||||||
import { PokemonData } from "#system/pokemon-data";
|
import { PokemonData } from "#system/pokemon-data";
|
||||||
import { MusicPreference } from "#system/settings";
|
import { MusicPreference } from "#system/settings";
|
||||||
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler";
|
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler";
|
||||||
@ -151,7 +152,8 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = MysteryEncounterBuil
|
|||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
MysteryEncounterOptionBuilder.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||||
|
.withSceneRequirement(new PartySizeRequirement([2, 6], true)) // Requires 2 valid party members
|
||||||
.withHasDexProgress(true)
|
.withHasDexProgress(true)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option.1.label`,
|
buttonLabel: `${namespace}:option.1.label`,
|
||||||
@ -257,7 +259,8 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = MysteryEncounterBuil
|
|||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
.withOption(
|
.withOption(
|
||||||
MysteryEncounterOptionBuilder.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT)
|
MysteryEncounterOptionBuilder.newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT)
|
||||||
|
.withSceneRequirement(new PartySizeRequirement([2, 6], true)) // Requires 2 valid party members
|
||||||
.withHasDexProgress(true)
|
.withHasDexProgress(true)
|
||||||
.withDialogue({
|
.withDialogue({
|
||||||
buttonLabel: `${namespace}:option.2.label`,
|
buttonLabel: `${namespace}:option.2.label`,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { type BattlerTag, loadBattlerTag } from "#data/battler-tags";
|
import type { BattlerTag } from "#data/battler-tags";
|
||||||
|
import { loadBattlerTag, SerializableBattlerTag } from "#data/battler-tags";
|
||||||
import { allSpecies } from "#data/data-lists";
|
import { allSpecies } from "#data/data-lists";
|
||||||
import type { Gender } from "#data/gender";
|
import type { Gender } from "#data/gender";
|
||||||
import { PokemonMove } from "#data/moves/pokemon-move";
|
import { PokemonMove } from "#data/moves/pokemon-move";
|
||||||
@ -187,9 +188,11 @@ export class PokemonSummonData {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === "tags") {
|
if (key === "tags" && Array.isArray(value)) {
|
||||||
// load battler tags
|
// load battler tags, discarding any that are not serializable
|
||||||
this.tags = value.map((t: BattlerTag) => loadBattlerTag(t));
|
this.tags = value
|
||||||
|
.map((t: SerializableBattlerTag) => loadBattlerTag(t))
|
||||||
|
.filter((t): t is SerializableBattlerTag => t instanceof SerializableBattlerTag);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this[key] = value;
|
this[key] = value;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
export enum BattlerTagType {
|
export enum BattlerTagType {
|
||||||
NONE = "NONE",
|
|
||||||
RECHARGING = "RECHARGING",
|
RECHARGING = "RECHARGING",
|
||||||
FLINCHED = "FLINCHED",
|
FLINCHED = "FLINCHED",
|
||||||
INTERRUPTED = "INTERRUPTED",
|
INTERRUPTED = "INTERRUPTED",
|
||||||
|
@ -9,6 +9,7 @@ import { AttemptCapturePhase } from "#phases/attempt-capture-phase";
|
|||||||
import { AttemptRunPhase } from "#phases/attempt-run-phase";
|
import { AttemptRunPhase } from "#phases/attempt-run-phase";
|
||||||
import { BattleEndPhase } from "#phases/battle-end-phase";
|
import { BattleEndPhase } from "#phases/battle-end-phase";
|
||||||
import { BerryPhase } from "#phases/berry-phase";
|
import { BerryPhase } from "#phases/berry-phase";
|
||||||
|
import { CheckInterludePhase } from "#phases/check-interlude-phase";
|
||||||
import { CheckStatusEffectPhase } from "#phases/check-status-effect-phase";
|
import { CheckStatusEffectPhase } from "#phases/check-status-effect-phase";
|
||||||
import { CheckSwitchPhase } from "#phases/check-switch-phase";
|
import { CheckSwitchPhase } from "#phases/check-switch-phase";
|
||||||
import { CommandPhase } from "#phases/command-phase";
|
import { CommandPhase } from "#phases/command-phase";
|
||||||
@ -121,6 +122,7 @@ const PHASES = Object.freeze({
|
|||||||
AttemptRunPhase,
|
AttemptRunPhase,
|
||||||
BattleEndPhase,
|
BattleEndPhase,
|
||||||
BerryPhase,
|
BerryPhase,
|
||||||
|
CheckInterludePhase,
|
||||||
CheckStatusEffectPhase,
|
CheckStatusEffectPhase,
|
||||||
CheckSwitchPhase,
|
CheckSwitchPhase,
|
||||||
CommandPhase,
|
CommandPhase,
|
||||||
@ -665,4 +667,15 @@ export class PhaseManager {
|
|||||||
): void {
|
): void {
|
||||||
this.startDynamicPhase(this.create(phase, ...args));
|
this.startDynamicPhase(this.create(phase, ...args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Prevents end of turn effects from triggering when transitioning to a new biome on a X0 wave */
|
||||||
|
public onInterlude(): void {
|
||||||
|
const phasesToRemove = ["WeatherEffectPhase", "BerryPhase", "CheckStatusEffectPhase"];
|
||||||
|
this.phaseQueue = this.phaseQueue.filter(p => !phasesToRemove.includes(p.phaseName));
|
||||||
|
|
||||||
|
const turnEndPhase = this.findPhase<TurnEndPhase>(p => p.phaseName === "TurnEndPhase");
|
||||||
|
if (turnEndPhase) {
|
||||||
|
turnEndPhase.upcomingInterlude = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
18
src/phases/check-interlude-phase.ts
Normal file
18
src/phases/check-interlude-phase.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import { Phase } from "#app/phase";
|
||||||
|
|
||||||
|
export class CheckInterludePhase extends Phase {
|
||||||
|
public override readonly phaseName = "CheckInterludePhase";
|
||||||
|
|
||||||
|
public override start(): void {
|
||||||
|
super.start();
|
||||||
|
const { phaseManager } = globalScene;
|
||||||
|
const { waveIndex } = globalScene.currentBattle;
|
||||||
|
|
||||||
|
if (waveIndex % 10 === 0 && globalScene.getEnemyParty().every(p => p.isFainted())) {
|
||||||
|
phaseManager.onInterlude();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.end();
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,8 @@ import i18next from "i18next";
|
|||||||
|
|
||||||
export class TurnEndPhase extends FieldPhase {
|
export class TurnEndPhase extends FieldPhase {
|
||||||
public readonly phaseName = "TurnEndPhase";
|
public readonly phaseName = "TurnEndPhase";
|
||||||
|
public upcomingInterlude = false;
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
@ -59,9 +61,11 @@ export class TurnEndPhase extends FieldPhase {
|
|||||||
pokemon.tempSummonData.waveTurnCount++;
|
pokemon.tempSummonData.waveTurnCount++;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!this.upcomingInterlude) {
|
||||||
this.executeForAll(handlePokemon);
|
this.executeForAll(handlePokemon);
|
||||||
|
|
||||||
globalScene.arena.lapseTags();
|
globalScene.arena.lapseTags();
|
||||||
|
}
|
||||||
|
|
||||||
if (globalScene.arena.weather && !globalScene.arena.weather.lapse()) {
|
if (globalScene.arena.weather && !globalScene.arena.weather.lapse()) {
|
||||||
globalScene.arena.trySetWeather(WeatherType.NONE);
|
globalScene.arena.trySetWeather(WeatherType.NONE);
|
||||||
|
@ -218,6 +218,7 @@ export class TurnStartPhase extends FieldPhase {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
phaseManager.pushNew("CheckInterludePhase");
|
||||||
|
|
||||||
phaseManager.pushNew("WeatherEffectPhase");
|
phaseManager.pushNew("WeatherEffectPhase");
|
||||||
phaseManager.pushNew("BerryPhase");
|
phaseManager.pushNew("BerryPhase");
|
||||||
@ -227,10 +228,10 @@ export class TurnStartPhase extends FieldPhase {
|
|||||||
|
|
||||||
phaseManager.pushNew("TurnEndPhase");
|
phaseManager.pushNew("TurnEndPhase");
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* this.end() will call shiftPhase(), which dumps everything from PrependQueue (aka everything that is unshifted()) to the front
|
* `this.end()` will call `PhaseManager#shiftPhase()`, which dumps everything from `phaseQueuePrepend`
|
||||||
* of the queue and dequeues to start the next phase
|
* (aka everything that is queued via `unshift()`) to the front of the queue and dequeues to start the next phase.
|
||||||
* this is important since stuff like SwitchSummon, AttemptRun, AttemptCapture Phases break the "flow" and should take precedence
|
* This is important since stuff like `SwitchSummonPhase`, `AttemptRunPhase`, and `AttemptCapturePhase` break the "flow" and should take precedence
|
||||||
*/
|
*/
|
||||||
this.end();
|
this.end();
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ describe("Global Trade System - Mystery Encounter", () => {
|
|||||||
describe("Option 1 - Check Trade Offers", () => {
|
describe("Option 1 - Check Trade Offers", () => {
|
||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option = GlobalTradeSystemEncounter.options[0];
|
const option = GlobalTradeSystemEncounter.options[0];
|
||||||
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
|
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT);
|
||||||
expect(option.dialogue).toBeDefined();
|
expect(option.dialogue).toBeDefined();
|
||||||
expect(option.dialogue).toStrictEqual({
|
expect(option.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option.1.label`,
|
buttonLabel: `${namespace}:option.1.label`,
|
||||||
@ -154,7 +154,7 @@ describe("Global Trade System - Mystery Encounter", () => {
|
|||||||
describe("Option 2 - Wonder Trade", () => {
|
describe("Option 2 - Wonder Trade", () => {
|
||||||
it("should have the correct properties", () => {
|
it("should have the correct properties", () => {
|
||||||
const option = GlobalTradeSystemEncounter.options[1];
|
const option = GlobalTradeSystemEncounter.options[1];
|
||||||
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT);
|
expect(option.optionMode).toBe(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT);
|
||||||
expect(option.dialogue).toBeDefined();
|
expect(option.dialogue).toBeDefined();
|
||||||
expect(option.dialogue).toStrictEqual({
|
expect(option.dialogue).toStrictEqual({
|
||||||
buttonLabel: `${namespace}:option.2.label`,
|
buttonLabel: `${namespace}:option.2.label`,
|
||||||
|
63
test/phases/check-interlude-phase.test.ts
Normal file
63
test/phases/check-interlude-phase.test.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { AbilityId } from "#enums/ability-id";
|
||||||
|
import { BerryType } from "#enums/berry-type";
|
||||||
|
import { MoveId } from "#enums/move-id";
|
||||||
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
import { WeatherType } from "#enums/weather-type";
|
||||||
|
import { GameManager } from "#test/test-utils/game-manager";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
describe("Check Biome End Phase", () => {
|
||||||
|
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
|
||||||
|
.enemySpecies(SpeciesId.MAGIKARP)
|
||||||
|
.enemyMoveset(MoveId.SPLASH)
|
||||||
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
|
.ability(AbilityId.BALL_FETCH)
|
||||||
|
.startingLevel(100)
|
||||||
|
.battleStyle("single");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not trigger end of turn effects when defeating the final pokemon of a biome in classic", async () => {
|
||||||
|
game.override
|
||||||
|
.startingWave(10)
|
||||||
|
.weather(WeatherType.SANDSTORM)
|
||||||
|
.startingHeldItems([{ name: "BERRY", type: BerryType.SITRUS }]);
|
||||||
|
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||||
|
|
||||||
|
const player = game.field.getPlayerPokemon();
|
||||||
|
|
||||||
|
player.hp = 1;
|
||||||
|
|
||||||
|
game.move.use(MoveId.EXTREME_SPEED);
|
||||||
|
await game.toEndOfTurn();
|
||||||
|
|
||||||
|
expect(player.hp).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not prevent end of turn effects when transitioning waves within a biome", async () => {
|
||||||
|
game.override.weather(WeatherType.SANDSTORM);
|
||||||
|
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||||
|
|
||||||
|
const player = game.field.getPlayerPokemon();
|
||||||
|
|
||||||
|
game.move.use(MoveId.EXTREME_SPEED);
|
||||||
|
await game.toEndOfTurn();
|
||||||
|
|
||||||
|
expect(player.hp).toBeLessThan(player.getMaxHp());
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user