mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-06-21 17:12:44 +02:00
Merge branch 'beta' into held-item-refactor
This commit is contained in:
commit
73292fcbe7
@ -4,7 +4,7 @@ module.exports = {
|
|||||||
{
|
{
|
||||||
name: "only-type-imports",
|
name: "only-type-imports",
|
||||||
severity: "error",
|
severity: "error",
|
||||||
comment: "Files in enums and @types may only use type imports.",
|
comment: "Files in 'enums/' and '@types/' must only use type imports.",
|
||||||
from: {
|
from: {
|
||||||
path: ["(^|/)src/@types", "(^|/)src/enums"],
|
path: ["(^|/)src/@types", "(^|/)src/enums"],
|
||||||
},
|
},
|
||||||
@ -14,7 +14,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no-circular-at-runtime",
|
name: "no-circular-at-runtime",
|
||||||
severity: "warn",
|
severity: "error",
|
||||||
comment:
|
comment:
|
||||||
"This dependency is part of a circular relationship. You might want to revise " +
|
"This dependency is part of a circular relationship. You might want to revise " +
|
||||||
"your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ",
|
"your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ",
|
||||||
@ -34,7 +34,7 @@ module.exports = {
|
|||||||
"add an exception for it in your dependency-cruiser configuration. By default " +
|
"add an exception for it in your dependency-cruiser configuration. By default " +
|
||||||
"this rule does not scrutinize dot-files (e.g. .eslintrc.js), TypeScript declaration " +
|
"this rule does not scrutinize dot-files (e.g. .eslintrc.js), TypeScript declaration " +
|
||||||
"files (.d.ts), tsconfig.json and some of the babel and webpack configs.",
|
"files (.d.ts), tsconfig.json and some of the babel and webpack configs.",
|
||||||
severity: "warn",
|
severity: "error",
|
||||||
from: {
|
from: {
|
||||||
orphan: true,
|
orphan: true,
|
||||||
pathNot: [
|
pathNot: [
|
||||||
@ -42,8 +42,7 @@ module.exports = {
|
|||||||
"[.]d[.]ts$", // TypeScript declaration files
|
"[.]d[.]ts$", // TypeScript declaration files
|
||||||
"(^|/)tsconfig[.]json$", // TypeScript config
|
"(^|/)tsconfig[.]json$", // TypeScript config
|
||||||
"(^|/)(?:babel|webpack)[.]config[.](?:js|cjs|mjs|ts|cts|mts|json)$", // other configs
|
"(^|/)(?:babel|webpack)[.]config[.](?:js|cjs|mjs|ts|cts|mts|json)$", // other configs
|
||||||
// anything in src/@types
|
"(^|/)test/.+[.]setup[.]ts", // Vitest setup files
|
||||||
"(^|/)src/@types/",
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
to: {},
|
to: {},
|
||||||
@ -53,7 +52,7 @@ module.exports = {
|
|||||||
comment:
|
comment:
|
||||||
"A module depends on a node core module that has been deprecated. Find an alternative - these are " +
|
"A module depends on a node core module that has been deprecated. Find an alternative - these are " +
|
||||||
"bound to exist - node doesn't deprecate lightly.",
|
"bound to exist - node doesn't deprecate lightly.",
|
||||||
severity: "warn",
|
severity: "error",
|
||||||
from: {},
|
from: {},
|
||||||
to: {
|
to: {
|
||||||
dependencyTypes: ["core"],
|
dependencyTypes: ["core"],
|
||||||
@ -86,7 +85,7 @@ module.exports = {
|
|||||||
comment:
|
comment:
|
||||||
"This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later " +
|
"This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later " +
|
||||||
"version of that module, or find an alternative. Deprecated modules are a security risk.",
|
"version of that module, or find an alternative. Deprecated modules are a security risk.",
|
||||||
severity: "warn",
|
severity: "error",
|
||||||
from: {},
|
from: {},
|
||||||
to: {
|
to: {
|
||||||
dependencyTypes: ["deprecated"],
|
dependencyTypes: ["deprecated"],
|
||||||
@ -122,7 +121,7 @@ module.exports = {
|
|||||||
"Likely this module depends on an external ('npm') package that occurs more than once " +
|
"Likely this module depends on an external ('npm') package that occurs more than once " +
|
||||||
"in your package.json i.e. bot as a devDependencies and in dependencies. This will cause " +
|
"in your package.json i.e. bot as a devDependencies and in dependencies. This will cause " +
|
||||||
"maintenance problems later on.",
|
"maintenance problems later on.",
|
||||||
severity: "warn",
|
severity: "error",
|
||||||
from: {},
|
from: {},
|
||||||
to: {
|
to: {
|
||||||
moreThanOneDependencyType: true,
|
moreThanOneDependencyType: true,
|
||||||
@ -133,7 +132,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
/* rules you might want to tweak for your specific situation: */
|
// rules you might want to tweak for your specific situation:
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "not-to-spec",
|
name: "not-to-spec",
|
||||||
@ -188,7 +187,7 @@ module.exports = {
|
|||||||
"in your package.json. This makes sense if your package is e.g. a plugin, but in " +
|
"in your package.json. This makes sense if your package is e.g. a plugin, but in " +
|
||||||
"other cases - maybe not so much. If the use of a peer dependency is intentional " +
|
"other cases - maybe not so much. If the use of a peer dependency is intentional " +
|
||||||
"add an exception to your dependency-cruiser configuration.",
|
"add an exception to your dependency-cruiser configuration.",
|
||||||
severity: "warn",
|
severity: "error",
|
||||||
from: {},
|
from: {},
|
||||||
to: {
|
to: {
|
||||||
dependencyTypes: ["npm-peer"],
|
dependencyTypes: ["npm-peer"],
|
||||||
@ -196,6 +195,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
options: {
|
options: {
|
||||||
|
exclude: ["src/plugins/vite/*", "src/vite.env.d.ts"],
|
||||||
/* Which modules not to follow further when encountered */
|
/* Which modules not to follow further when encountered */
|
||||||
doNotFollow: {
|
doNotFollow: {
|
||||||
/* path: an array of regular expressions in strings to match against */
|
/* path: an array of regular expressions in strings to match against */
|
||||||
@ -235,7 +235,7 @@ module.exports = {
|
|||||||
true: also detect dependencies that only exist before typescript-to-javascript compilation
|
true: also detect dependencies that only exist before typescript-to-javascript compilation
|
||||||
"specify": for each dependency identify whether it only exists before compilation or also after
|
"specify": for each dependency identify whether it only exists before compilation or also after
|
||||||
*/
|
*/
|
||||||
// tsPreCompilationDeps: false,
|
tsPreCompilationDeps: true,
|
||||||
|
|
||||||
/* list of extensions to scan that aren't javascript or compile-to-javascript.
|
/* list of extensions to scan that aren't javascript or compile-to-javascript.
|
||||||
Empty by default. Only put extensions in here that you want to take into
|
Empty by default. Only put extensions in here that you want to take into
|
||||||
|
42
.github/workflows/linting.yml
vendored
Normal file
42
.github/workflows/linting.yml
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
name: Linting
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- beta
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- beta
|
||||||
|
merge_group:
|
||||||
|
types: [checks_requested]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run-linters:
|
||||||
|
name: Run linters
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out Git repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: 'recursive'
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- name: Install Node.js dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run ESLint
|
||||||
|
run: npm run eslint-ci
|
||||||
|
|
||||||
|
- name: Lint with Biome
|
||||||
|
run: npm run biome-ci
|
||||||
|
|
||||||
|
- name: Check dependencies with depcruise
|
||||||
|
run: npm run depcruise
|
41
.github/workflows/quality.yml
vendored
41
.github/workflows/quality.yml
vendored
@ -1,41 +0,0 @@
|
|||||||
name: Biome Code Quality
|
|
||||||
|
|
||||||
on:
|
|
||||||
# Trigger the workflow on push or pull request,
|
|
||||||
# but only for the main branch
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main # Trigger on push events to the main branch
|
|
||||||
- beta # Trigger on push events to the beta branch
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- main # Trigger on pull request events targeting the main branch
|
|
||||||
- beta # Trigger on pull request events targeting the beta branch
|
|
||||||
merge_group:
|
|
||||||
types: [checks_requested]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
run-linters: # Define a job named "run-linters"
|
|
||||||
name: Run linters # Human-readable name for the job
|
|
||||||
runs-on: ubuntu-latest # Specify the latest Ubuntu runner for the job
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check out Git repository # Step to check out the repository
|
|
||||||
uses: actions/checkout@v4 # Use the checkout action version 4
|
|
||||||
with:
|
|
||||||
submodules: 'recursive'
|
|
||||||
|
|
||||||
- name: Set up Node.js # Step to set up Node.js environment
|
|
||||||
uses: actions/setup-node@v4 # Use the setup-node action version 4
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- name: Install Node.js dependencies # Step to install Node.js dependencies
|
|
||||||
run: npm ci # Use 'npm ci' to install dependencies
|
|
||||||
|
|
||||||
- name: eslint # Step to run linters
|
|
||||||
run: npm run eslint-ci
|
|
||||||
|
|
||||||
- name: Lint with Biome # Step to run linters
|
|
||||||
run: npm run biome-ci
|
|
@ -47,8 +47,8 @@
|
|||||||
"correctness": {
|
"correctness": {
|
||||||
"noUndeclaredVariables": "off",
|
"noUndeclaredVariables": "off",
|
||||||
"noUnusedVariables": "error",
|
"noUnusedVariables": "error",
|
||||||
"noSwitchDeclarations": "warn", // TODO: refactor and make this an error
|
"noSwitchDeclarations": "error",
|
||||||
"noVoidTypeReturn": "warn", // TODO: Refactor and make this an error
|
"noVoidTypeReturn": "error",
|
||||||
"noUnusedImports": "error"
|
"noUnusedImports": "error"
|
||||||
},
|
},
|
||||||
"style": {
|
"style": {
|
||||||
@ -85,7 +85,7 @@
|
|||||||
"useLiteralKeys": "off",
|
"useLiteralKeys": "off",
|
||||||
"noForEach": "off", // Foreach vs for of is not that simple.
|
"noForEach": "off", // Foreach vs for of is not that simple.
|
||||||
"noUselessSwitchCase": "off", // Explicit > Implicit
|
"noUselessSwitchCase": "off", // Explicit > Implicit
|
||||||
"noUselessConstructor": "warn", // TODO: Refactor and make this an error
|
"noUselessConstructor": "error",
|
||||||
"noBannedTypes": "warn" // TODO: Refactor and make this an error
|
"noBannedTypes": "warn" // TODO: Refactor and make this an error
|
||||||
},
|
},
|
||||||
"nursery": {
|
"nursery": {
|
||||||
|
@ -18,9 +18,9 @@
|
|||||||
"eslint": "eslint --fix .",
|
"eslint": "eslint --fix .",
|
||||||
"eslint-ci": "eslint .",
|
"eslint-ci": "eslint .",
|
||||||
"biome": "biome check --write --changed --no-errors-on-unmatched",
|
"biome": "biome check --write --changed --no-errors-on-unmatched",
|
||||||
"biome-ci": "biome ci --diagnostic-level=error --reporter=github --changed --no-errors-on-unmatched",
|
"biome-ci": "biome ci --diagnostic-level=error --reporter=github --no-errors-on-unmatched",
|
||||||
"docs": "typedoc",
|
"docs": "typedoc",
|
||||||
"depcruise": "depcruise src",
|
"depcruise": "depcruise src test",
|
||||||
"depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg",
|
"depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg",
|
||||||
"postinstall": "npx lefthook install && npx lefthook run post-merge",
|
"postinstall": "npx lefthook install && npx lefthook run post-merge",
|
||||||
"update-version:patch": "npm version patch --force --no-git-tag-version",
|
"update-version:patch": "npm version patch --force --no-git-tag-version",
|
||||||
|
@ -29,4 +29,4 @@ export type ModifierString = keyof ModifierConstructorMap;
|
|||||||
|
|
||||||
export type ModifierPool = {
|
export type ModifierPool = {
|
||||||
[tier: string]: WeightedModifierType[];
|
[tier: string]: WeightedModifierType[];
|
||||||
}
|
};
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { allMoves } from "./data-lists";
|
import { allMoves } from "#app/data/data-lists";
|
||||||
import { MoveFlags } from "#enums/MoveFlags";
|
import { MoveFlags } from "#enums/MoveFlags";
|
||||||
import type Pokemon from "../field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { type nil, getFrameMs, getEnumKeys, getEnumValues, animationFileName, coerceArray } from "../utils/common";
|
import {
|
||||||
|
type nil,
|
||||||
|
getFrameMs,
|
||||||
|
getEnumKeys,
|
||||||
|
getEnumValues,
|
||||||
|
animationFileName,
|
||||||
|
coerceArray,
|
||||||
|
isNullOrUndefined,
|
||||||
|
} from "#app/utils/common";
|
||||||
import type { BattlerIndex } from "#enums/battler-index";
|
import type { BattlerIndex } from "#enums/battler-index";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { SubstituteTag } from "./battler-tags";
|
|
||||||
import { isNullOrUndefined } from "../utils/common";
|
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
import { EncounterAnim } from "#enums/encounter-anims";
|
import { EncounterAnim } from "#enums/encounter-anims";
|
||||||
import { AnimBlendType, AnimFrameTarget, AnimFocus, ChargeAnim, CommonAnim } from "#enums/move-anims-common";
|
import { AnimBlendType, AnimFrameTarget, AnimFocus, ChargeAnim, CommonAnim } from "#enums/move-anims-common";
|
||||||
@ -845,7 +851,7 @@ export abstract class BattleAnim {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const targetSubstitute = !!onSubstitute && user !== target ? target.getTag(SubstituteTag) : null;
|
const targetSubstitute = !!onSubstitute && user !== target ? target.getTag(BattlerTagType.SUBSTITUTE) : null;
|
||||||
|
|
||||||
const userSprite = user.getSprite();
|
const userSprite = user.getSprite();
|
||||||
const targetSprite = targetSubstitute?.sprite ?? target.getSprite();
|
const targetSprite = targetSubstitute?.sprite ?? target.getSprite();
|
||||||
|
@ -125,16 +125,6 @@ export interface TerrainBattlerTag {
|
|||||||
* Players and enemies should not be allowed to select restricted moves.
|
* Players and enemies should not be allowed to select restricted moves.
|
||||||
*/
|
*/
|
||||||
export abstract class MoveRestrictionBattlerTag extends BattlerTag {
|
export abstract class MoveRestrictionBattlerTag extends BattlerTag {
|
||||||
constructor(
|
|
||||||
tagType: BattlerTagType,
|
|
||||||
lapseType: BattlerTagLapseType | BattlerTagLapseType[],
|
|
||||||
turnCount: number,
|
|
||||||
sourceMove?: MoveId,
|
|
||||||
sourceId?: number,
|
|
||||||
) {
|
|
||||||
super(tagType, lapseType, turnCount, sourceMove, sourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
|
||||||
if (lapseType === BattlerTagLapseType.PRE_MOVE) {
|
if (lapseType === BattlerTagLapseType.PRE_MOVE) {
|
||||||
@ -1470,16 +1460,6 @@ export class WrapTag extends DamagingTrapTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export abstract class VortexTrapTag extends DamagingTrapTag {
|
export abstract class VortexTrapTag extends DamagingTrapTag {
|
||||||
constructor(
|
|
||||||
tagType: BattlerTagType,
|
|
||||||
commonAnim: CommonAnim,
|
|
||||||
turnCount: number,
|
|
||||||
sourceMove: MoveId,
|
|
||||||
sourceId: number,
|
|
||||||
) {
|
|
||||||
super(tagType, commonAnim, turnCount, sourceMove, sourceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTrapMessage(pokemon: Pokemon): string {
|
getTrapMessage(pokemon: Pokemon): string {
|
||||||
return i18next.t("battlerTags:vortexOnTrap", {
|
return i18next.t("battlerTags:vortexOnTrap", {
|
||||||
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
|
||||||
|
@ -11,10 +11,7 @@ import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requir
|
|||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { ModifierTier } from "#enums/modifier-tier";
|
import { ModifierTier } from "#enums/modifier-tier";
|
||||||
import type { ModifierTypeOption } from "#app/modifier/modifier-type";
|
import type { ModifierTypeOption } from "#app/modifier/modifier-type";
|
||||||
import {
|
import { getPlayerModifierTypeOptions, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
||||||
getPlayerModifierTypeOptions,
|
|
||||||
regenerateModifierPoolThresholds,
|
|
||||||
} from "#app/modifier/modifier-type";
|
|
||||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
@ -7,10 +7,7 @@ import { TrainerSlot } from "#enums/trainer-slot";
|
|||||||
import { ModifierTier } from "#enums/modifier-tier";
|
import { ModifierTier } from "#enums/modifier-tier";
|
||||||
import { MusicPreference } from "#app/system/settings/settings";
|
import { MusicPreference } from "#app/system/settings/settings";
|
||||||
import type { ModifierTypeOption } from "#app/modifier/modifier-type";
|
import type { ModifierTypeOption } from "#app/modifier/modifier-type";
|
||||||
import {
|
import { getPlayerModifierTypeOptions, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
|
||||||
getPlayerModifierTypeOptions,
|
|
||||||
regenerateModifierPoolThresholds,
|
|
||||||
} from "#app/modifier/modifier-type";
|
|
||||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
// biome-ignore lint/correctness/noUnusedImports: Used in tsdoc
|
|
||||||
import type ConfirmUiHandler from "#app/ui/confirm-ui-handler";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by {@linkcode ConfirmUiHandler} to determine whether the cursor should start on Yes or No
|
|
||||||
*/
|
|
||||||
export const ConfirmUiMode = Object.freeze({
|
|
||||||
/** Start cursor on Yes */
|
|
||||||
DEFAULT_YES: 1,
|
|
||||||
/** Start cursor on No */
|
|
||||||
DEFAULT_NO: 2
|
|
||||||
});
|
|
||||||
export type ConfirmUiMode = typeof ConfirmUiMode[keyof typeof ConfirmUiMode];
|
|
@ -263,7 +263,7 @@ export class Arena {
|
|||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SpeciesId.LYCANROC:
|
case SpeciesId.LYCANROC: {
|
||||||
const timeOfDay = this.getTimeOfDay();
|
const timeOfDay = this.getTimeOfDay();
|
||||||
switch (timeOfDay) {
|
switch (timeOfDay) {
|
||||||
case TimeOfDay.DAY:
|
case TimeOfDay.DAY:
|
||||||
@ -275,6 +275,7 @@ export class Arena {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -4369,14 +4369,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
// biome-ignore lint: there are a ton of issues..
|
// biome-ignore lint: there are a ton of issues..
|
||||||
faintCry(callback: Function): void {
|
faintCry(callback: Function): void {
|
||||||
if (this.fusionSpecies && this.getSpeciesForm() !== this.getFusionSpeciesForm()) {
|
if (this.fusionSpecies && this.getSpeciesForm() !== this.getFusionSpeciesForm()) {
|
||||||
return this.fusionFaintCry(callback);
|
this.fusionFaintCry(callback);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = this.species.getCryKey(this.formIndex);
|
const key = this.species.getCryKey(this.formIndex);
|
||||||
let rate = 0.85;
|
let rate = 0.85;
|
||||||
const cry = globalScene.playSound(key, { rate: rate }) as AnySound;
|
const cry = globalScene.playSound(key, { rate: rate }) as AnySound;
|
||||||
if (!cry || globalScene.fieldVolume === 0) {
|
if (!cry || globalScene.fieldVolume === 0) {
|
||||||
return callback();
|
callback();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
const sprite = this.getSprite();
|
const sprite = this.getSprite();
|
||||||
const tintSprite = this.getTintSprite();
|
const tintSprite = this.getTintSprite();
|
||||||
@ -4444,7 +4446,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
rate: rate,
|
rate: rate,
|
||||||
}) as AnySound;
|
}) as AnySound;
|
||||||
if (!cry || !fusionCry || globalScene.fieldVolume === 0) {
|
if (!cry || !fusionCry || globalScene.fieldVolume === 0) {
|
||||||
return callback();
|
callback();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
fusionCry.stop();
|
fusionCry.stop();
|
||||||
duration = Math.min(duration, fusionCry.totalDuration * 1000);
|
duration = Math.min(duration, fusionCry.totalDuration * 1000);
|
||||||
|
@ -1990,8 +1990,6 @@ export interface ModifierPool {
|
|||||||
[tier: string]: WeightedModifierType[];
|
[tier: string]: WeightedModifierType[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const modifierPool: ModifierPool = {};
|
|
||||||
|
|
||||||
let modifierPoolThresholds = {};
|
let modifierPoolThresholds = {};
|
||||||
let ignoredPoolIndexes = {};
|
let ignoredPoolIndexes = {};
|
||||||
|
|
||||||
@ -2510,7 +2508,7 @@ function determineTier(
|
|||||||
}
|
}
|
||||||
|
|
||||||
tier += upgradeCount;
|
tier += upgradeCount;
|
||||||
while (tier && (!modifierPool.hasOwnProperty(tier) || !modifierPool[tier].length)) {
|
while (tier && (!pool.hasOwnProperty(tier) || !pool[tier].length)) {
|
||||||
tier--;
|
tier--;
|
||||||
if (upgradeCount) {
|
if (upgradeCount) {
|
||||||
upgradeCount--;
|
upgradeCount--;
|
||||||
@ -2521,7 +2519,7 @@ function determineTier(
|
|||||||
if (tier < ModifierTier.MASTER && allowLuckUpgrades) {
|
if (tier < ModifierTier.MASTER && allowLuckUpgrades) {
|
||||||
const partyLuckValue = getPartyLuckValue(party);
|
const partyLuckValue = getPartyLuckValue(party);
|
||||||
const upgradeOdds = Math.floor(128 / ((partyLuckValue + 4) / 4));
|
const upgradeOdds = Math.floor(128 / ((partyLuckValue + 4) / 4));
|
||||||
while (modifierPool.hasOwnProperty(tier + upgradeCount + 1) && modifierPool[tier + upgradeCount + 1].length) {
|
while (pool.hasOwnProperty(tier + upgradeCount + 1) && pool[tier + upgradeCount + 1].length) {
|
||||||
if (randSeedInt(upgradeOdds) < 4) {
|
if (randSeedInt(upgradeOdds) < 4) {
|
||||||
upgradeCount++;
|
upgradeCount++;
|
||||||
} else {
|
} else {
|
||||||
@ -2538,6 +2536,7 @@ function determineTier(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getDefaultModifierTypeForTier(tier: ModifierTier): ModifierType {
|
export function getDefaultModifierTypeForTier(tier: ModifierTier): ModifierType {
|
||||||
|
const modifierPool = getModifierPoolForType(ModifierPoolType.PLAYER);
|
||||||
let modifierType: ModifierType | WeightedModifierType = modifierPool[tier || ModifierTier.COMMON][0];
|
let modifierType: ModifierType | WeightedModifierType = modifierPool[tier || ModifierTier.COMMON][0];
|
||||||
if (modifierType instanceof WeightedModifierType) {
|
if (modifierType instanceof WeightedModifierType) {
|
||||||
modifierType = (modifierType as WeightedModifierType).modifierType;
|
modifierType = (modifierType as WeightedModifierType).modifierType;
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
import { ModifierTier } from "#enums/modifier-tier";
|
import { ModifierTier } from "#enums/modifier-tier";
|
||||||
import {
|
import { regenerateModifierPoolThresholds, getEnemyBuffModifierForWave } from "#app/modifier/modifier-type";
|
||||||
regenerateModifierPoolThresholds,
|
|
||||||
getEnemyBuffModifierForWave,
|
|
||||||
} from "#app/modifier/modifier-type";
|
|
||||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||||
import { EnemyPersistentModifier } from "#app/modifier/modifier";
|
import { EnemyPersistentModifier } from "#app/modifier/modifier";
|
||||||
import { Phase } from "#app/phase";
|
import { Phase } from "#app/phase";
|
||||||
|
@ -149,7 +149,7 @@ export class CommandPhase extends FieldPhase {
|
|||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case Command.TERA:
|
case Command.TERA:
|
||||||
case Command.FIGHT:
|
case Command.FIGHT: {
|
||||||
let useStruggle = false;
|
let useStruggle = false;
|
||||||
const turnMove: TurnMove | undefined = args.length === 2 ? (args[1] as TurnMove) : undefined;
|
const turnMove: TurnMove | undefined = args.length === 2 ? (args[1] as TurnMove) : undefined;
|
||||||
if (
|
if (
|
||||||
@ -233,7 +233,8 @@ export class CommandPhase extends FieldPhase {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Command.BALL:
|
}
|
||||||
|
case Command.BALL: {
|
||||||
const notInDex =
|
const notInDex =
|
||||||
globalScene
|
globalScene
|
||||||
.getEnemyField()
|
.getEnemyField()
|
||||||
@ -337,8 +338,9 @@ export class CommandPhase extends FieldPhase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case Command.POKEMON:
|
case Command.POKEMON:
|
||||||
case Command.RUN:
|
case Command.RUN: {
|
||||||
const isSwitch = command === Command.POKEMON;
|
const isSwitch = command === Command.POKEMON;
|
||||||
const { currentBattle, arena } = globalScene;
|
const { currentBattle, arena } = globalScene;
|
||||||
const mysteryEncounterFleeAllowed = currentBattle.mysteryEncounter?.fleeAllowed;
|
const mysteryEncounterFleeAllowed = currentBattle.mysteryEncounter?.fleeAllowed;
|
||||||
@ -445,6 +447,7 @@ export class CommandPhase extends FieldPhase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -12,7 +12,6 @@ import { UiMode } from "#enums/ui-mode";
|
|||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase";
|
import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { ConfirmUiMode } from "#enums/confirm-ui-mode";
|
|
||||||
import { LearnMoveType } from "#enums/learn-move-type";
|
import { LearnMoveType } from "#enums/learn-move-type";
|
||||||
|
|
||||||
export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
||||||
@ -164,10 +163,6 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
|
|||||||
globalScene.ui.setMode(this.messageMode);
|
globalScene.ui.setMode(this.messageMode);
|
||||||
this.replaceMoveCheck(move, pokemon);
|
this.replaceMoveCheck(move, pokemon);
|
||||||
},
|
},
|
||||||
false,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
ConfirmUiMode.DEFAULT_NO,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,8 @@ export class MovePhase extends BattlePhase {
|
|||||||
this.showMoveText();
|
this.showMoveText();
|
||||||
this.showFailedText();
|
this.showFailedText();
|
||||||
}
|
}
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pokemon.turnData.acted = true;
|
this.pokemon.turnData.acted = true;
|
||||||
@ -310,7 +311,8 @@ export class MovePhase extends BattlePhase {
|
|||||||
if (fail) {
|
if (fail) {
|
||||||
this.showMoveText();
|
this.showMoveText();
|
||||||
this.showFailedText();
|
this.showFailedText();
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,8 @@ export class PokemonAnimPhase extends BattlePhase {
|
|||||||
private doSubstituteAddAnim(): void {
|
private doSubstituteAddAnim(): void {
|
||||||
const substitute = this.pokemon.getTag(SubstituteTag);
|
const substitute = this.pokemon.getTag(SubstituteTag);
|
||||||
if (isNullOrUndefined(substitute)) {
|
if (isNullOrUndefined(substitute)) {
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSprite = () => {
|
const getSprite = () => {
|
||||||
@ -116,12 +117,14 @@ export class PokemonAnimPhase extends BattlePhase {
|
|||||||
|
|
||||||
private doSubstitutePreMoveAnim(): void {
|
private doSubstitutePreMoveAnim(): void {
|
||||||
if (this.fieldAssets.length !== 1) {
|
if (this.fieldAssets.length !== 1) {
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const subSprite = this.fieldAssets[0];
|
const subSprite = this.fieldAssets[0];
|
||||||
if (subSprite === undefined) {
|
if (subSprite === undefined) {
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.tweens.add({
|
globalScene.tweens.add({
|
||||||
@ -145,12 +148,14 @@ export class PokemonAnimPhase extends BattlePhase {
|
|||||||
|
|
||||||
private doSubstitutePostMoveAnim(): void {
|
private doSubstitutePostMoveAnim(): void {
|
||||||
if (this.fieldAssets.length !== 1) {
|
if (this.fieldAssets.length !== 1) {
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const subSprite = this.fieldAssets[0];
|
const subSprite = this.fieldAssets[0];
|
||||||
if (subSprite === undefined) {
|
if (subSprite === undefined) {
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
globalScene.tweens.add({
|
globalScene.tweens.add({
|
||||||
@ -174,12 +179,14 @@ export class PokemonAnimPhase extends BattlePhase {
|
|||||||
|
|
||||||
private doSubstituteRemoveAnim(): void {
|
private doSubstituteRemoveAnim(): void {
|
||||||
if (this.fieldAssets.length !== 1) {
|
if (this.fieldAssets.length !== 1) {
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const subSprite = this.fieldAssets[0];
|
const subSprite = this.fieldAssets[0];
|
||||||
if (subSprite === undefined) {
|
if (subSprite === undefined) {
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSprite = () => {
|
const getSprite = () => {
|
||||||
@ -244,12 +251,14 @@ export class PokemonAnimPhase extends BattlePhase {
|
|||||||
|
|
||||||
private doCommanderApplyAnim(): void {
|
private doCommanderApplyAnim(): void {
|
||||||
if (!globalScene.currentBattle?.double) {
|
if (!globalScene.currentBattle?.double) {
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
const dondozo = this.pokemon.getAlly();
|
const dondozo = this.pokemon.getAlly();
|
||||||
|
|
||||||
if (dondozo?.species?.speciesId !== SpeciesId.DONDOZO) {
|
if (dondozo?.species?.speciesId !== SpeciesId.DONDOZO) {
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tatsugiriX = this.pokemon.x + this.pokemon.getSprite().x;
|
const tatsugiriX = this.pokemon.x + this.pokemon.getSprite().x;
|
||||||
@ -329,7 +338,8 @@ export class PokemonAnimPhase extends BattlePhase {
|
|||||||
const tatsugiri = this.pokemon.getAlly();
|
const tatsugiri = this.pokemon.getAlly();
|
||||||
if (isNullOrUndefined(tatsugiri)) {
|
if (isNullOrUndefined(tatsugiri)) {
|
||||||
console.warn("Aborting COMMANDER_REMOVE anim: Tatsugiri is undefined");
|
console.warn("Aborting COMMANDER_REMOVE anim: Tatsugiri is undefined");
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tatsuSprite = globalScene.addPokemonSprite(
|
const tatsuSprite = globalScene.addPokemonSprite(
|
||||||
|
@ -29,7 +29,8 @@ export class PokemonTransformPhase extends PokemonPhase {
|
|||||||
const target = globalScene.getField(true).find(p => p.getBattlerIndex() === this.targetIndex);
|
const target = globalScene.getField(true).find(p => p.getBattlerIndex() === this.targetIndex);
|
||||||
|
|
||||||
if (!target) {
|
if (!target) {
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
user.summonData.speciesForm = target.getSpeciesForm();
|
user.summonData.speciesForm = target.getSpeciesForm();
|
||||||
|
@ -29,7 +29,8 @@ export class QuietFormChangePhase extends BattlePhase {
|
|||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
if (this.pokemon.formIndex === this.pokemon.species.forms.findIndex(f => f.formKey === this.formChange.formKey)) {
|
if (this.pokemon.formIndex === this.pokemon.species.forms.findIndex(f => f.formKey === this.formChange.formKey)) {
|
||||||
return this.end();
|
this.end();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const preName = getPokemonNameWithAffix(this.pokemon);
|
const preName = getPokemonNameWithAffix(this.pokemon);
|
||||||
|
@ -174,7 +174,24 @@ export async function initI18n(): Promise<void> {
|
|||||||
"es-MX": ["es-ES", "en"],
|
"es-MX": ["es-ES", "en"],
|
||||||
default: ["en"],
|
default: ["en"],
|
||||||
},
|
},
|
||||||
supportedLngs: ["en", "es-ES", "es-MX", "fr", "it", "de", "zh-CN", "zh-TW", "pt-BR", "ko", "ja", "ca", "da", "tr", "ro", "ru"],
|
supportedLngs: [
|
||||||
|
"en",
|
||||||
|
"es-ES",
|
||||||
|
"es-MX",
|
||||||
|
"fr",
|
||||||
|
"it",
|
||||||
|
"de",
|
||||||
|
"zh-CN",
|
||||||
|
"zh-TW",
|
||||||
|
"pt-BR",
|
||||||
|
"ko",
|
||||||
|
"ja",
|
||||||
|
"ca",
|
||||||
|
"da",
|
||||||
|
"tr",
|
||||||
|
"ro",
|
||||||
|
"ru",
|
||||||
|
],
|
||||||
backend: {
|
backend: {
|
||||||
loadPath(lng: string, [ns]: string[]) {
|
loadPath(lng: string, [ns]: string[]) {
|
||||||
let fileName: string;
|
let fileName: string;
|
||||||
|
@ -32,7 +32,10 @@ const pressAction = i18next.t("settings:pressActionToAssign");
|
|||||||
|
|
||||||
export const settingGamepadOptions = {
|
export const settingGamepadOptions = {
|
||||||
[SettingGamepad.Controller]: [i18next.t("settings:controllerDefault"), i18next.t("settings:controllerChange")],
|
[SettingGamepad.Controller]: [i18next.t("settings:controllerDefault"), i18next.t("settings:controllerChange")],
|
||||||
[SettingGamepad.Gamepad_Support]: [i18next.t("settings:gamepadSupportAuto"), i18next.t("settings:gamepadSupportDisabled")],
|
[SettingGamepad.Gamepad_Support]: [
|
||||||
|
i18next.t("settings:gamepadSupportAuto"),
|
||||||
|
i18next.t("settings:gamepadSupportDisabled"),
|
||||||
|
],
|
||||||
[SettingGamepad.Button_Up]: [`KEY ${Button.UP.toString()}`, pressAction],
|
[SettingGamepad.Button_Up]: [`KEY ${Button.UP.toString()}`, pressAction],
|
||||||
[SettingGamepad.Button_Down]: [`KEY ${Button.DOWN.toString()}`, pressAction],
|
[SettingGamepad.Button_Down]: [`KEY ${Button.DOWN.toString()}`, pressAction],
|
||||||
[SettingGamepad.Button_Left]: [`KEY ${Button.LEFT.toString()}`, pressAction],
|
[SettingGamepad.Button_Left]: [`KEY ${Button.LEFT.toString()}`, pressAction],
|
||||||
|
@ -959,7 +959,7 @@ export function setSetting(setting: string, value: number): boolean {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Türkçe (Needs Help)",
|
label: "Türkçe (Needs Help)",
|
||||||
handler: () => changeLocaleHandler("tr")
|
handler: () => changeLocaleHandler("tr"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Русский (Needs Help)",
|
label: "Русский (Needs Help)",
|
||||||
@ -967,11 +967,11 @@ export function setSetting(setting: string, value: number): boolean {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Dansk (Needs Help)",
|
label: "Dansk (Needs Help)",
|
||||||
handler: () => changeLocaleHandler("da")
|
handler: () => changeLocaleHandler("da"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Română (Needs Help)",
|
label: "Română (Needs Help)",
|
||||||
handler: () => changeLocaleHandler("ro")
|
handler: () => changeLocaleHandler("ro"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: i18next.t("settings:back"),
|
label: i18next.t("settings:back"),
|
||||||
|
@ -56,10 +56,6 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
|
|||||||
protected defaultTextStyle: TextStyle = TextStyle.WINDOW;
|
protected defaultTextStyle: TextStyle = TextStyle.WINDOW;
|
||||||
protected textContent: string;
|
protected textContent: string;
|
||||||
|
|
||||||
constructor(mode: UiMode | null) {
|
|
||||||
super(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract getWindowWidth(): number;
|
abstract getWindowWidth(): number;
|
||||||
|
|
||||||
getWindowHeight(): number {
|
getWindowHeight(): number {
|
||||||
|
@ -69,7 +69,7 @@ export default class AdminUiHandler extends FormModalUiHandler {
|
|||||||
case AdminMode.SEARCH:
|
case AdminMode.SEARCH:
|
||||||
inputFieldConfigs.push({ label: "Username" });
|
inputFieldConfigs.push({ label: "Username" });
|
||||||
break;
|
break;
|
||||||
case AdminMode.ADMIN:
|
case AdminMode.ADMIN: {
|
||||||
const adminResult = this.adminResult ?? {
|
const adminResult = this.adminResult ?? {
|
||||||
username: "",
|
username: "",
|
||||||
discordId: "",
|
discordId: "",
|
||||||
@ -90,6 +90,7 @@ export default class AdminUiHandler extends FormModalUiHandler {
|
|||||||
inputFieldConfigs.push({ label: "Last played", isReadOnly: true });
|
inputFieldConfigs.push({ label: "Last played", isReadOnly: true });
|
||||||
inputFieldConfigs.push({ label: "Registered", isReadOnly: true });
|
inputFieldConfigs.push({ label: "Registered", isReadOnly: true });
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return inputFieldConfigs;
|
return inputFieldConfigs;
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,8 @@ import { UiMode } from "#enums/ui-mode";
|
|||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { ConfirmUiMode } from "#enums/confirm-ui-mode";
|
|
||||||
|
|
||||||
export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler {
|
export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler {
|
||||||
private confirmUiMode: ConfirmUiMode;
|
|
||||||
|
|
||||||
public static readonly windowWidth: number = 48;
|
public static readonly windowWidth: number = 48;
|
||||||
|
|
||||||
private switchCheck: boolean;
|
private switchCheck: boolean;
|
||||||
@ -108,16 +105,7 @@ export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler {
|
|||||||
|
|
||||||
this.optionSelectContainer.setPosition(globalScene.game.canvas.width / 6 - 1 + xOffset, -48 + yOffset);
|
this.optionSelectContainer.setPosition(globalScene.game.canvas.width / 6 - 1 + xOffset, -48 + yOffset);
|
||||||
|
|
||||||
this.confirmUiMode = args.length >= 6 ? (args[5] as ConfirmUiMode) : ConfirmUiMode.DEFAULT_YES;
|
this.setCursor(this.switchCheck ? this.switchCheckCursor : 0);
|
||||||
|
|
||||||
switch (this.confirmUiMode) {
|
|
||||||
case ConfirmUiMode.DEFAULT_YES:
|
|
||||||
this.setCursor(this.switchCheck ? this.switchCheckCursor : 0);
|
|
||||||
break;
|
|
||||||
case ConfirmUiMode.DEFAULT_NO:
|
|
||||||
this.setCursor(this.switchCheck ? this.switchCheckCursor : 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -169,12 +169,13 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container {
|
|||||||
entryContainer.add(scoreLabel);
|
entryContainer.add(scoreLabel);
|
||||||
|
|
||||||
switch (this.category) {
|
switch (this.category) {
|
||||||
case ScoreboardCategory.DAILY:
|
case ScoreboardCategory.DAILY: {
|
||||||
const waveLabel = addTextObject(68, 0, wave, TextStyle.WINDOW, {
|
const waveLabel = addTextObject(68, 0, wave, TextStyle.WINDOW, {
|
||||||
fontSize: "54px",
|
fontSize: "54px",
|
||||||
});
|
});
|
||||||
entryContainer.add(waveLabel);
|
entryContainer.add(waveLabel);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case ScoreboardCategory.WEEKLY:
|
case ScoreboardCategory.WEEKLY:
|
||||||
scoreLabel.x -= 16;
|
scoreLabel.x -= 16;
|
||||||
break;
|
break;
|
||||||
|
@ -131,7 +131,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
gachaInfoContainer.add(gachaUpLabel);
|
gachaInfoContainer.add(gachaUpLabel);
|
||||||
|
|
||||||
switch (gachaType as GachaType) {
|
switch (gachaType as GachaType) {
|
||||||
case GachaType.LEGENDARY:
|
case GachaType.LEGENDARY: {
|
||||||
if (["de", "es-ES"].includes(currentLanguage)) {
|
if (["de", "es-ES"].includes(currentLanguage)) {
|
||||||
gachaUpLabel.setAlign("center");
|
gachaUpLabel.setAlign("center");
|
||||||
gachaUpLabel.setY(0);
|
gachaUpLabel.setY(0);
|
||||||
@ -152,6 +152,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
|
|
||||||
gachaInfoContainer.add(pokemonIcon);
|
gachaInfoContainer.add(pokemonIcon);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case GachaType.MOVE:
|
case GachaType.MOVE:
|
||||||
if (["de", "es-ES", "fr", "pt-BR", "ru"].includes(currentLanguage)) {
|
if (["de", "es-ES", "fr", "pt-BR", "ru"].includes(currentLanguage)) {
|
||||||
gachaUpLabel.setAlign("center");
|
gachaUpLabel.setAlign("center");
|
||||||
@ -623,11 +624,12 @@ export default class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
updateGachaInfo(gachaType: GachaType): void {
|
updateGachaInfo(gachaType: GachaType): void {
|
||||||
const infoContainer = this.gachaInfoContainers[gachaType];
|
const infoContainer = this.gachaInfoContainers[gachaType];
|
||||||
switch (gachaType as GachaType) {
|
switch (gachaType as GachaType) {
|
||||||
case GachaType.LEGENDARY:
|
case GachaType.LEGENDARY: {
|
||||||
const species = getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(new Date().getTime()));
|
const species = getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(new Date().getTime()));
|
||||||
const pokemonIcon = infoContainer.getAt(1) as Phaser.GameObjects.Sprite;
|
const pokemonIcon = infoContainer.getAt(1) as Phaser.GameObjects.Sprite;
|
||||||
pokemonIcon.setTexture(species.getIconAtlasKey(), species.getIconId(false));
|
pokemonIcon.setTexture(species.getIconAtlasKey(), species.getIconId(false));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,7 +686,7 @@ export default class MenuUiHandler extends MessageUiHandler {
|
|||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MenuOptions.LOG_OUT:
|
case MenuOptions.LOG_OUT: {
|
||||||
success = true;
|
success = true;
|
||||||
const doLogout = () => {
|
const doLogout = () => {
|
||||||
ui.setMode(UiMode.LOADING, {
|
ui.setMode(UiMode.LOADING, {
|
||||||
@ -718,6 +718,7 @@ export default class MenuUiHandler extends MessageUiHandler {
|
|||||||
doLogout();
|
doLogout();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (button === Button.CANCEL) {
|
} else if (button === Button.CANCEL) {
|
||||||
success = true;
|
success = true;
|
||||||
|
@ -1359,7 +1359,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||||||
case PartyOption.MOVE_1:
|
case PartyOption.MOVE_1:
|
||||||
case PartyOption.MOVE_2:
|
case PartyOption.MOVE_2:
|
||||||
case PartyOption.MOVE_3:
|
case PartyOption.MOVE_3:
|
||||||
case PartyOption.MOVE_4:
|
case PartyOption.MOVE_4: {
|
||||||
const move = pokemon.moveset[option - PartyOption.MOVE_1];
|
const move = pokemon.moveset[option - PartyOption.MOVE_1];
|
||||||
if (this.showMovePp) {
|
if (this.showMovePp) {
|
||||||
const maxPP = move.getMovePp();
|
const maxPP = move.getMovePp();
|
||||||
@ -1384,6 +1384,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER) {
|
} else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER) {
|
||||||
const learnableLevelMoves = pokemon.getLearnableLevelMoves();
|
const learnableLevelMoves = pokemon.getLearnableLevelMoves();
|
||||||
|
@ -568,7 +568,7 @@ export default class RunInfoUiHandler extends UiHandler {
|
|||||||
case GameModes.SPLICED_ENDLESS:
|
case GameModes.SPLICED_ENDLESS:
|
||||||
modeText.appendText(`${i18next.t("gameMode:endlessSpliced")}`, false);
|
modeText.appendText(`${i18next.t("gameMode:endlessSpliced")}`, false);
|
||||||
break;
|
break;
|
||||||
case GameModes.CHALLENGE:
|
case GameModes.CHALLENGE: {
|
||||||
modeText.appendText(`${i18next.t("gameMode:challenge")}`, false);
|
modeText.appendText(`${i18next.t("gameMode:challenge")}`, false);
|
||||||
modeText.appendText(`${i18next.t("runHistory:challengeRules")}: `);
|
modeText.appendText(`${i18next.t("runHistory:challengeRules")}: `);
|
||||||
modeText.setWrapMode(1); // wrap by word
|
modeText.setWrapMode(1); // wrap by word
|
||||||
@ -583,6 +583,7 @@ export default class RunInfoUiHandler extends UiHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case GameModes.ENDLESS:
|
case GameModes.ENDLESS:
|
||||||
modeText.appendText(`${i18next.t("gameMode:endless")}`, false);
|
modeText.appendText(`${i18next.t("gameMode:endless")}`, false);
|
||||||
break;
|
break;
|
||||||
@ -688,7 +689,7 @@ export default class RunInfoUiHandler extends UiHandler {
|
|||||||
case Challenges.SINGLE_GENERATION:
|
case Challenges.SINGLE_GENERATION:
|
||||||
rules.push(i18next.t(`runHistory:challengeMonoGen${this.runInfo.challenges[i].value}`));
|
rules.push(i18next.t(`runHistory:challengeMonoGen${this.runInfo.challenges[i].value}`));
|
||||||
break;
|
break;
|
||||||
case Challenges.SINGLE_TYPE:
|
case Challenges.SINGLE_TYPE: {
|
||||||
const typeRule = PokemonType[this.runInfo.challenges[i].value - 1];
|
const typeRule = PokemonType[this.runInfo.challenges[i].value - 1];
|
||||||
const typeTextColor = `[color=${TypeColor[typeRule]}]`;
|
const typeTextColor = `[color=${TypeColor[typeRule]}]`;
|
||||||
const typeShadowColor = `[shadow=${TypeShadow[typeRule]}]`;
|
const typeShadowColor = `[shadow=${TypeShadow[typeRule]}]`;
|
||||||
@ -696,16 +697,18 @@ export default class RunInfoUiHandler extends UiHandler {
|
|||||||
typeTextColor + typeShadowColor + i18next.t(`pokemonInfo:Type.${typeRule}`)! + "[/color]" + "[/shadow]";
|
typeTextColor + typeShadowColor + i18next.t(`pokemonInfo:Type.${typeRule}`)! + "[/color]" + "[/shadow]";
|
||||||
rules.push(typeText);
|
rules.push(typeText);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case Challenges.INVERSE_BATTLE:
|
case Challenges.INVERSE_BATTLE:
|
||||||
rules.push(i18next.t("challenges:inverseBattle.shortName"));
|
rules.push(i18next.t("challenges:inverseBattle.shortName"));
|
||||||
break;
|
break;
|
||||||
default:
|
default: {
|
||||||
const localisationKey = Challenges[this.runInfo.challenges[i].id]
|
const localisationKey = Challenges[this.runInfo.challenges[i].id]
|
||||||
.split("_")
|
.split("_")
|
||||||
.map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()))
|
.map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()))
|
||||||
.join("");
|
.join("");
|
||||||
rules.push(i18next.t(`challenges:${localisationKey}.name`));
|
rules.push(i18next.t(`challenges:${localisationKey}.name`));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,12 +332,13 @@ export default class AbstractSettingsUiHandler extends MessageUiHandler {
|
|||||||
case Button.CYCLE_SHINY:
|
case Button.CYCLE_SHINY:
|
||||||
success = this.navigationContainer.navigate(button);
|
success = this.navigationContainer.navigate(button);
|
||||||
break;
|
break;
|
||||||
case Button.ACTION:
|
case Button.ACTION: {
|
||||||
const setting: Setting = this.settings[cursor];
|
const setting: Setting = this.settings[cursor];
|
||||||
if (setting?.activatable) {
|
if (setting?.activatable) {
|
||||||
success = this.activateSetting(setting);
|
success = this.activateSetting(setting);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1763,7 +1763,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
}
|
}
|
||||||
} else if (this.randomCursorObj.visible) {
|
} else if (this.randomCursorObj.visible) {
|
||||||
switch (button) {
|
switch (button) {
|
||||||
case Button.ACTION:
|
case Button.ACTION: {
|
||||||
if (this.starterSpecies.length >= 6) {
|
if (this.starterSpecies.length >= 6) {
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
@ -1815,6 +1815,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case Button.UP:
|
case Button.UP:
|
||||||
this.randomCursorObj.setVisible(false);
|
this.randomCursorObj.setVisible(false);
|
||||||
this.filterBarCursor = this.filterBar.numFilters - 1;
|
this.filterBarCursor = this.filterBar.numFilters - 1;
|
||||||
|
@ -10,10 +10,6 @@ import { UiMode } from "#enums/ui-mode";
|
|||||||
export default class TestDialogueUiHandler extends FormModalUiHandler {
|
export default class TestDialogueUiHandler extends FormModalUiHandler {
|
||||||
keys: string[];
|
keys: string[];
|
||||||
|
|
||||||
constructor(mode) {
|
|
||||||
super(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
super.setup();
|
super.setup();
|
||||||
|
|
||||||
|
@ -50,5 +50,5 @@ describe("Ability Timing", () => {
|
|||||||
|
|
||||||
await game.phaseInterceptor.to("MessagePhase");
|
await game.phaseInterceptor.to("MessagePhase");
|
||||||
expect(i18next.t).toHaveBeenCalledWith("battle:statFell", expect.objectContaining({ count: 1 }));
|
expect(i18next.t).toHaveBeenCalledWith("battle:statFell", expect.objectContaining({ count: 1 }));
|
||||||
}, 5000);
|
});
|
||||||
});
|
});
|
||||||
|
@ -26,11 +26,12 @@ describe("Abilities - Battery", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("double");
|
game.override
|
||||||
game.override.enemySpecies(SpeciesId.SHUCKLE);
|
.battleStyle("double")
|
||||||
game.override.enemyAbility(AbilityId.BALL_FETCH);
|
.enemySpecies(SpeciesId.SHUCKLE)
|
||||||
game.override.moveset([MoveId.TACKLE, MoveId.BREAKING_SWIPE, MoveId.SPLASH, MoveId.DAZZLING_GLEAM]);
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
.moveset([MoveId.TACKLE, MoveId.BREAKING_SWIPE, MoveId.SPLASH, MoveId.DAZZLING_GLEAM])
|
||||||
|
.enemyMoveset(MoveId.SPLASH);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("raises the power of allies' special moves by 30%", async () => {
|
it("raises the power of allies' special moves by 30%", async () => {
|
||||||
|
@ -47,7 +47,7 @@ describe("Abilities - Beast Boost", () => {
|
|||||||
await game.phaseInterceptor.to("VictoryPhase");
|
await game.phaseInterceptor.to("VictoryPhase");
|
||||||
|
|
||||||
expect(playerPokemon.getStatStage(Stat.DEF)).toBe(1);
|
expect(playerPokemon.getStatStage(Stat.DEF)).toBe(1);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("should use in-battle overriden stats when determining the stat stage to raise by 1", async () => {
|
it("should use in-battle overriden stats when determining the stat stage to raise by 1", async () => {
|
||||||
game.override.enemyMoveset([MoveId.GUARD_SPLIT]);
|
game.override.enemyMoveset([MoveId.GUARD_SPLIT]);
|
||||||
@ -66,7 +66,7 @@ describe("Abilities - Beast Boost", () => {
|
|||||||
await game.phaseInterceptor.to("VictoryPhase");
|
await game.phaseInterceptor.to("VictoryPhase");
|
||||||
|
|
||||||
expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(1);
|
expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(1);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("should have order preference in case of stat ties", async () => {
|
it("should have order preference in case of stat ties", async () => {
|
||||||
// Order preference follows the order of EFFECTIVE_STAT
|
// Order preference follows the order of EFFECTIVE_STAT
|
||||||
@ -84,5 +84,5 @@ describe("Abilities - Beast Boost", () => {
|
|||||||
await game.phaseInterceptor.to("VictoryPhase");
|
await game.phaseInterceptor.to("VictoryPhase");
|
||||||
|
|
||||||
expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(1);
|
expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(1);
|
||||||
}, 20000);
|
});
|
||||||
});
|
});
|
||||||
|
@ -36,7 +36,7 @@ describe("Abilities - Contrary", () => {
|
|||||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(1);
|
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(1);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
describe("With Clear Body", () => {
|
describe("With Clear Body", () => {
|
||||||
it("should apply positive effects", async () => {
|
it("should apply positive effects", async () => {
|
||||||
|
@ -24,10 +24,11 @@ describe("Abilities - COSTAR", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("double");
|
game.override
|
||||||
game.override.ability(AbilityId.COSTAR);
|
.battleStyle("double")
|
||||||
game.override.moveset([MoveId.SPLASH, MoveId.NASTY_PLOT]);
|
.ability(AbilityId.COSTAR)
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
.moveset([MoveId.SPLASH, MoveId.NASTY_PLOT])
|
||||||
|
.enemyMoveset(MoveId.SPLASH);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("ability copies positive stat stages", async () => {
|
test("ability copies positive stat stages", async () => {
|
||||||
|
@ -66,8 +66,7 @@ describe("Abilities - Disguise", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("takes no damage from the first hit of a multihit move and transforms to Busted form, then takes damage from the second hit", async () => {
|
it("takes no damage from the first hit of a multihit move and transforms to Busted form, then takes damage from the second hit", async () => {
|
||||||
game.override.moveset([MoveId.SURGING_STRIKES]);
|
game.override.moveset([MoveId.SURGING_STRIKES]).enemyLevel(5);
|
||||||
game.override.enemyLevel(5);
|
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle();
|
||||||
|
|
||||||
const mimikyu = game.scene.getEnemyPokemon()!;
|
const mimikyu = game.scene.getEnemyPokemon()!;
|
||||||
@ -106,8 +105,7 @@ describe("Abilities - Disguise", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("persists form change when switched out", async () => {
|
it("persists form change when switched out", async () => {
|
||||||
game.override.enemyMoveset([MoveId.SHADOW_SNEAK]);
|
game.override.enemyMoveset([MoveId.SHADOW_SNEAK]).starterSpecies(0);
|
||||||
game.override.starterSpecies(0);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MIMIKYU, SpeciesId.FURRET]);
|
await game.classicMode.startBattle([SpeciesId.MIMIKYU, SpeciesId.FURRET]);
|
||||||
|
|
||||||
@ -131,8 +129,7 @@ describe("Abilities - Disguise", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("persists form change when wave changes with no arena reset", async () => {
|
it("persists form change when wave changes with no arena reset", async () => {
|
||||||
game.override.starterSpecies(0);
|
game.override.starterSpecies(0).starterForms({
|
||||||
game.override.starterForms({
|
|
||||||
[SpeciesId.MIMIKYU]: bustedForm,
|
[SpeciesId.MIMIKYU]: bustedForm,
|
||||||
});
|
});
|
||||||
await game.classicMode.startBattle([SpeciesId.FURRET, SpeciesId.MIMIKYU]);
|
await game.classicMode.startBattle([SpeciesId.FURRET, SpeciesId.MIMIKYU]);
|
||||||
@ -148,11 +145,12 @@ describe("Abilities - Disguise", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("reverts to Disguised form on arena reset", async () => {
|
it("reverts to Disguised form on arena reset", async () => {
|
||||||
game.override.startingWave(4);
|
game.override
|
||||||
game.override.starterSpecies(SpeciesId.MIMIKYU);
|
.startingWave(4)
|
||||||
game.override.starterForms({
|
.starterSpecies(SpeciesId.MIMIKYU)
|
||||||
[SpeciesId.MIMIKYU]: bustedForm,
|
.starterForms({
|
||||||
});
|
[SpeciesId.MIMIKYU]: bustedForm,
|
||||||
|
});
|
||||||
|
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle();
|
||||||
|
|
||||||
@ -168,11 +166,12 @@ describe("Abilities - Disguise", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("reverts to Disguised form on biome change when fainted", async () => {
|
it("reverts to Disguised form on biome change when fainted", async () => {
|
||||||
game.override.startingWave(10);
|
game.override
|
||||||
game.override.starterSpecies(0);
|
.startingWave(10)
|
||||||
game.override.starterForms({
|
.starterSpecies(0)
|
||||||
[SpeciesId.MIMIKYU]: bustedForm,
|
.starterForms({
|
||||||
});
|
[SpeciesId.MIMIKYU]: bustedForm,
|
||||||
|
});
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MIMIKYU, SpeciesId.FURRET]);
|
await game.classicMode.startBattle([SpeciesId.MIMIKYU, SpeciesId.FURRET]);
|
||||||
|
|
||||||
@ -206,8 +205,7 @@ describe("Abilities - Disguise", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("activates when Aerilate circumvents immunity to the move's base type", async () => {
|
it("activates when Aerilate circumvents immunity to the move's base type", async () => {
|
||||||
game.override.ability(AbilityId.AERILATE);
|
game.override.ability(AbilityId.AERILATE).moveset([MoveId.TACKLE]);
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle();
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ describe("Abilities - Flash Fire", () => {
|
|||||||
game.move.select(MoveId.SPLASH);
|
game.move.select(MoveId.SPLASH);
|
||||||
await game.phaseInterceptor.to(TurnEndPhase);
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
expect(blissey.hp).toBe(blissey.getMaxHp());
|
expect(blissey.hp).toBe(blissey.getMaxHp());
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("not activate if the Pokémon is protected from the Fire-type move", async () => {
|
it("not activate if the Pokémon is protected from the Fire-type move", async () => {
|
||||||
game.override.enemyMoveset([MoveId.EMBER]).moveset([MoveId.PROTECT]);
|
game.override.enemyMoveset([MoveId.EMBER]).moveset([MoveId.PROTECT]);
|
||||||
@ -55,7 +55,7 @@ describe("Abilities - Flash Fire", () => {
|
|||||||
game.move.select(MoveId.PROTECT);
|
game.move.select(MoveId.PROTECT);
|
||||||
await game.phaseInterceptor.to(TurnEndPhase);
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
expect(blissey!.getTag(BattlerTagType.FIRE_BOOST)).toBeUndefined();
|
expect(blissey!.getTag(BattlerTagType.FIRE_BOOST)).toBeUndefined();
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("activated by Will-O-Wisp", async () => {
|
it("activated by Will-O-Wisp", async () => {
|
||||||
game.override.enemyMoveset([MoveId.WILL_O_WISP]).moveset(MoveId.SPLASH);
|
game.override.enemyMoveset([MoveId.WILL_O_WISP]).moveset(MoveId.SPLASH);
|
||||||
@ -70,11 +70,10 @@ describe("Abilities - Flash Fire", () => {
|
|||||||
|
|
||||||
await game.phaseInterceptor.to(TurnEndPhase);
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
expect(blissey!.getTag(BattlerTagType.FIRE_BOOST)).toBeDefined();
|
expect(blissey!.getTag(BattlerTagType.FIRE_BOOST)).toBeDefined();
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("activated after being frozen", async () => {
|
it("activated after being frozen", async () => {
|
||||||
game.override.enemyMoveset([MoveId.EMBER]).moveset(MoveId.SPLASH);
|
game.override.enemyMoveset([MoveId.EMBER]).moveset(MoveId.SPLASH).statusEffect(StatusEffect.FREEZE);
|
||||||
game.override.statusEffect(StatusEffect.FREEZE);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BLISSEY]);
|
await game.classicMode.startBattle([SpeciesId.BLISSEY]);
|
||||||
|
|
||||||
const blissey = game.scene.getPlayerPokemon()!;
|
const blissey = game.scene.getPlayerPokemon()!;
|
||||||
@ -83,7 +82,7 @@ describe("Abilities - Flash Fire", () => {
|
|||||||
|
|
||||||
await game.phaseInterceptor.to(TurnEndPhase);
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
expect(blissey!.getTag(BattlerTagType.FIRE_BOOST)).toBeDefined();
|
expect(blissey!.getTag(BattlerTagType.FIRE_BOOST)).toBeDefined();
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("not passing with baton pass", async () => {
|
it("not passing with baton pass", async () => {
|
||||||
game.override.enemyMoveset([MoveId.EMBER]).moveset([MoveId.BATON_PASS]);
|
game.override.enemyMoveset([MoveId.EMBER]).moveset([MoveId.BATON_PASS]);
|
||||||
@ -99,11 +98,14 @@ describe("Abilities - Flash Fire", () => {
|
|||||||
const chansey = game.scene.getPlayerPokemon()!;
|
const chansey = game.scene.getPlayerPokemon()!;
|
||||||
expect(game.scene.getPlayerPokemon()!.species.speciesId).toBe(SpeciesId.CHANSEY);
|
expect(game.scene.getPlayerPokemon()!.species.speciesId).toBe(SpeciesId.CHANSEY);
|
||||||
expect(chansey!.getTag(BattlerTagType.FIRE_BOOST)).toBeUndefined();
|
expect(chansey!.getTag(BattlerTagType.FIRE_BOOST)).toBeUndefined();
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("boosts Fire-type move when the ability is activated", async () => {
|
it("boosts Fire-type move when the ability is activated", async () => {
|
||||||
game.override.enemyMoveset([MoveId.FIRE_PLEDGE]).moveset([MoveId.EMBER, MoveId.SPLASH]);
|
game.override
|
||||||
game.override.enemyAbility(AbilityId.FLASH_FIRE).ability(AbilityId.NONE);
|
.enemyMoveset([MoveId.FIRE_PLEDGE])
|
||||||
|
.moveset([MoveId.EMBER, MoveId.SPLASH])
|
||||||
|
.enemyAbility(AbilityId.FLASH_FIRE)
|
||||||
|
.ability(AbilityId.NONE);
|
||||||
await game.classicMode.startBattle([SpeciesId.BLISSEY]);
|
await game.classicMode.startBattle([SpeciesId.BLISSEY]);
|
||||||
const blissey = game.scene.getPlayerPokemon()!;
|
const blissey = game.scene.getPlayerPokemon()!;
|
||||||
const initialHP = 1000;
|
const initialHP = 1000;
|
||||||
@ -124,12 +126,15 @@ describe("Abilities - Flash Fire", () => {
|
|||||||
const flashFireDmg = initialHP - blissey.hp;
|
const flashFireDmg = initialHP - blissey.hp;
|
||||||
|
|
||||||
expect(flashFireDmg).toBeGreaterThan(originalDmg);
|
expect(flashFireDmg).toBeGreaterThan(originalDmg);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("still activates regardless of accuracy check", async () => {
|
it("still activates regardless of accuracy check", async () => {
|
||||||
game.override.moveset(MoveId.FIRE_PLEDGE).enemyMoveset(MoveId.EMBER);
|
game.override
|
||||||
game.override.enemyAbility(AbilityId.NONE).ability(AbilityId.FLASH_FIRE);
|
.moveset(MoveId.FIRE_PLEDGE)
|
||||||
game.override.enemySpecies(SpeciesId.BLISSEY);
|
.enemyMoveset(MoveId.EMBER)
|
||||||
|
.enemyAbility(AbilityId.NONE)
|
||||||
|
.ability(AbilityId.FLASH_FIRE)
|
||||||
|
.enemySpecies(SpeciesId.BLISSEY);
|
||||||
await game.classicMode.startBattle([SpeciesId.RATTATA]);
|
await game.classicMode.startBattle([SpeciesId.RATTATA]);
|
||||||
|
|
||||||
const blissey = game.scene.getEnemyPokemon()!;
|
const blissey = game.scene.getEnemyPokemon()!;
|
||||||
@ -153,5 +158,5 @@ describe("Abilities - Flash Fire", () => {
|
|||||||
const flashFireDmg = initialHP - blissey.hp;
|
const flashFireDmg = initialHP - blissey.hp;
|
||||||
|
|
||||||
expect(flashFireDmg).toBeGreaterThan(originalDmg);
|
expect(flashFireDmg).toBeGreaterThan(originalDmg);
|
||||||
}, 20000);
|
});
|
||||||
});
|
});
|
||||||
|
@ -47,9 +47,10 @@ describe("Abilities - Flower Gift", () => {
|
|||||||
allyAbility = AbilityId.BALL_FETCH,
|
allyAbility = AbilityId.BALL_FETCH,
|
||||||
enemyAbility = AbilityId.BALL_FETCH,
|
enemyAbility = AbilityId.BALL_FETCH,
|
||||||
): Promise<[number, number]> => {
|
): Promise<[number, number]> => {
|
||||||
game.override.battleStyle("double");
|
game.override
|
||||||
game.override.moveset([MoveId.SPLASH, MoveId.SUNNY_DAY, move, MoveId.HEAL_PULSE]);
|
.battleStyle("double")
|
||||||
game.override.enemyMoveset([MoveId.SPLASH, MoveId.HEAL_PULSE]);
|
.moveset([MoveId.SPLASH, MoveId.SUNNY_DAY, move, MoveId.HEAL_PULSE])
|
||||||
|
.enemyMoveset([MoveId.SPLASH, MoveId.HEAL_PULSE]);
|
||||||
const target_index = allyAttacker ? BattlerIndex.ENEMY : BattlerIndex.PLAYER_2;
|
const target_index = allyAttacker ? BattlerIndex.ENEMY : BattlerIndex.PLAYER_2;
|
||||||
const attacker_index = allyAttacker ? BattlerIndex.PLAYER_2 : BattlerIndex.ENEMY;
|
const attacker_index = allyAttacker ? BattlerIndex.PLAYER_2 : BattlerIndex.ENEMY;
|
||||||
const ally_move = allyAttacker ? move : MoveId.SPLASH;
|
const ally_move = allyAttacker ? move : MoveId.SPLASH;
|
||||||
|
@ -89,7 +89,6 @@ describe("Abilities - Flower Veil", () => {
|
|||||||
await game.move.selectEnemyMove(MoveId.THUNDER_WAVE);
|
await game.move.selectEnemyMove(MoveId.THUNDER_WAVE);
|
||||||
await game.toNextTurn();
|
await game.toNextTurn();
|
||||||
expect(game.scene.getPlayerPokemon()!.status).toBeUndefined();
|
expect(game.scene.getPlayerPokemon()!.status).toBeUndefined();
|
||||||
vi.spyOn(allMoves[MoveId.THUNDER_WAVE], "accuracy", "get").mockClear();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not prevent status conditions for a non-grass user and its non-grass allies", async () => {
|
it("should not prevent status conditions for a non-grass user and its non-grass allies", async () => {
|
||||||
|
@ -63,9 +63,10 @@ describe("Abilities - Good As Gold", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not block any status moves that target the field, one side, or all pokemon", async () => {
|
it("should not block any status moves that target the field, one side, or all pokemon", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override
|
||||||
game.override.enemyMoveset([MoveId.STEALTH_ROCK, MoveId.HAZE]);
|
.battleStyle("double")
|
||||||
game.override.moveset([MoveId.SWORDS_DANCE, MoveId.SAFEGUARD]);
|
.enemyMoveset([MoveId.STEALTH_ROCK, MoveId.HAZE])
|
||||||
|
.moveset([MoveId.SWORDS_DANCE, MoveId.SAFEGUARD]);
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.FEEBAS]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.FEEBAS]);
|
||||||
const [good_as_gold, ball_fetch] = game.scene.getPlayerField();
|
const [good_as_gold, ball_fetch] = game.scene.getPlayerField();
|
||||||
|
|
||||||
@ -85,8 +86,7 @@ describe("Abilities - Good As Gold", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not block field targeted effects in singles", async () => {
|
it("should not block field targeted effects in singles", async () => {
|
||||||
game.override.battleStyle("single");
|
game.override.battleStyle("single").enemyMoveset([MoveId.SPIKES]);
|
||||||
game.override.enemyMoveset([MoveId.SPIKES]);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
game.move.select(MoveId.SPLASH, 0);
|
game.move.select(MoveId.SPLASH, 0);
|
||||||
@ -96,8 +96,7 @@ describe("Abilities - Good As Gold", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should block the ally's helping hand", async () => {
|
it("should block the ally's helping hand", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double").moveset([MoveId.HELPING_HAND, MoveId.TACKLE]);
|
||||||
game.override.moveset([MoveId.HELPING_HAND, MoveId.TACKLE]);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.FEEBAS]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.FEEBAS]);
|
||||||
|
|
||||||
game.move.select(MoveId.HELPING_HAND, 0);
|
game.move.select(MoveId.HELPING_HAND, 0);
|
||||||
@ -129,8 +128,7 @@ describe("Abilities - Good As Gold", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not block field targeted effects like rain dance", async () => {
|
it("should not block field targeted effects like rain dance", async () => {
|
||||||
game.override.battleStyle("single");
|
game.override.battleStyle("single").enemyMoveset([MoveId.RAIN_DANCE]);
|
||||||
game.override.enemyMoveset([MoveId.RAIN_DANCE]);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
game.move.use(MoveId.SPLASH, 0);
|
game.move.use(MoveId.SPLASH, 0);
|
||||||
|
@ -4,17 +4,15 @@ import { SpeciesId } from "#enums/species-id";
|
|||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import GameManager from "#test/testUtils/gameManager";
|
import GameManager from "#test/testUtils/gameManager";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi, type MockInstance } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import { isNullOrUndefined } from "#app/utils/common";
|
import { isNullOrUndefined } from "#app/utils/common";
|
||||||
import { allAbilities } from "#app/data/data-lists";
|
import { allAbilities } from "#app/data/data-lists";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import type { PostTurnResetStatusAbAttr } from "#app/@types/ability-types";
|
import { PostTurnResetStatusAbAttr } from "#app/data/abilities/ability";
|
||||||
|
|
||||||
describe("Abilities - Healer", () => {
|
describe("Abilities - Healer", () => {
|
||||||
let phaserGame: Phaser.Game;
|
let phaserGame: Phaser.Game;
|
||||||
let game: GameManager;
|
let game: GameManager;
|
||||||
let healerAttrSpy: MockInstance;
|
|
||||||
let healerAttr: PostTurnResetStatusAbAttr;
|
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
phaserGame = new Phaser.Game({
|
phaserGame = new Phaser.Game({
|
||||||
@ -24,7 +22,6 @@ describe("Abilities - Healer", () => {
|
|||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
game.phaseInterceptor.restoreOg();
|
game.phaseInterceptor.restoreOg();
|
||||||
healerAttrSpy.mockRestore();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -38,30 +35,28 @@ describe("Abilities - Healer", () => {
|
|||||||
.enemyAbility(AbilityId.BALL_FETCH)
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
.enemyMoveset(MoveId.SPLASH);
|
.enemyMoveset(MoveId.SPLASH);
|
||||||
|
|
||||||
healerAttr = allAbilities[AbilityId.HEALER].getAttrs("PostTurnResetStatusAbAttr")[0];
|
// Mock healer to have a 100% chance of healing its ally
|
||||||
healerAttrSpy = vi
|
vi.spyOn(allAbilities[AbilityId.HEALER].getAttrs("PostTurnResetStatusAbAttr")[0], "getCondition").mockReturnValue(
|
||||||
.spyOn(healerAttr, "getCondition")
|
(pokemon: Pokemon) => !isNullOrUndefined(pokemon.getAlly()),
|
||||||
.mockReturnValue((pokemon: Pokemon) => !isNullOrUndefined(pokemon.getAlly()));
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not queue a message phase for healing if the ally has fainted", async () => {
|
it("should not queue a message phase for healing if the ally has fainted", async () => {
|
||||||
|
const abSpy = vi.spyOn(PostTurnResetStatusAbAttr.prototype, "canApplyPostTurn");
|
||||||
game.override.moveset([MoveId.SPLASH, MoveId.LUNAR_DANCE]);
|
game.override.moveset([MoveId.SPLASH, MoveId.LUNAR_DANCE]);
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
const user = game.scene.getPlayerPokemon()!;
|
const user = game.scene.getPlayerPokemon()!;
|
||||||
// Only want one magikarp to have the ability.
|
// Only want one magikarp to have the ability
|
||||||
vi.spyOn(user, "getAbility").mockReturnValue(allAbilities[AbilityId.HEALER]);
|
vi.spyOn(user, "getAbility").mockReturnValue(allAbilities[AbilityId.HEALER]);
|
||||||
game.move.select(MoveId.SPLASH);
|
game.move.select(MoveId.SPLASH);
|
||||||
// faint the ally
|
// faint the ally
|
||||||
game.move.select(MoveId.LUNAR_DANCE, 1);
|
game.move.select(MoveId.LUNAR_DANCE, 1);
|
||||||
const abSpy = vi.spyOn(healerAttr, "canApplyPostTurn");
|
|
||||||
await game.phaseInterceptor.to("TurnEndPhase");
|
await game.phaseInterceptor.to("TurnEndPhase");
|
||||||
|
|
||||||
// It's not enough to just test that the ally still has its status.
|
// It's not enough to just test that the ally still has its status.
|
||||||
// We need to ensure that the ability failed to meet its condition
|
// We need to ensure that the ability failed to meet its condition
|
||||||
expect(abSpy).toHaveReturnedWith(false);
|
expect(abSpy).toHaveReturnedWith(false);
|
||||||
|
|
||||||
// Explicitly restore the mock to ensure pollution doesn't happen
|
|
||||||
abSpy.mockRestore();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should heal the status of an ally if the ally has a status", async () => {
|
it("should heal the status of an ally if the ally has a status", async () => {
|
||||||
|
@ -75,8 +75,7 @@ describe("Abilities - Hustle", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("does not affect OHKO moves", async () => {
|
it("does not affect OHKO moves", async () => {
|
||||||
game.override.startingLevel(100);
|
game.override.startingLevel(100).enemyLevel(30);
|
||||||
game.override.enemyLevel(30);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.PIKACHU]);
|
await game.classicMode.startBattle([SpeciesId.PIKACHU]);
|
||||||
const pikachu = game.scene.getPlayerPokemon()!;
|
const pikachu = game.scene.getPlayerPokemon()!;
|
||||||
|
@ -30,10 +30,11 @@ describe("Abilities - Ice Face", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.enemySpecies(SpeciesId.EISCUE);
|
.battleStyle("single")
|
||||||
game.override.enemyAbility(AbilityId.ICE_FACE);
|
.enemySpecies(SpeciesId.EISCUE)
|
||||||
game.override.moveset([MoveId.TACKLE, MoveId.ICE_BEAM, MoveId.TOXIC_THREAD, MoveId.HAIL]);
|
.enemyAbility(AbilityId.ICE_FACE)
|
||||||
|
.moveset([MoveId.TACKLE, MoveId.ICE_BEAM, MoveId.TOXIC_THREAD, MoveId.HAIL]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("takes no damage from physical move and transforms to Noice", async () => {
|
it("takes no damage from physical move and transforms to Noice", async () => {
|
||||||
@ -51,8 +52,7 @@ describe("Abilities - Ice Face", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("takes no damage from the first hit of multihit physical move and transforms to Noice", async () => {
|
it("takes no damage from the first hit of multihit physical move and transforms to Noice", async () => {
|
||||||
game.override.moveset([MoveId.SURGING_STRIKES]);
|
game.override.moveset([MoveId.SURGING_STRIKES]).enemyLevel(1);
|
||||||
game.override.enemyLevel(1);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.HITMONLEE]);
|
await game.classicMode.startBattle([SpeciesId.HITMONLEE]);
|
||||||
|
|
||||||
game.move.select(MoveId.SURGING_STRIKES);
|
game.move.select(MoveId.SURGING_STRIKES);
|
||||||
@ -196,12 +196,13 @@ describe("Abilities - Ice Face", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("reverts to Ice Face on arena reset", async () => {
|
it("reverts to Ice Face on arena reset", async () => {
|
||||||
game.override.startingWave(4);
|
game.override
|
||||||
game.override.startingLevel(4);
|
.startingWave(4)
|
||||||
game.override.enemySpecies(SpeciesId.MAGIKARP);
|
.startingLevel(4)
|
||||||
game.override.starterForms({
|
.enemySpecies(SpeciesId.MAGIKARP)
|
||||||
[SpeciesId.EISCUE]: noiceForm,
|
.starterForms({
|
||||||
});
|
[SpeciesId.EISCUE]: noiceForm,
|
||||||
|
});
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.EISCUE]);
|
await game.classicMode.startBattle([SpeciesId.EISCUE]);
|
||||||
|
|
||||||
|
@ -116,26 +116,23 @@ describe("Abilities - Illusion", () => {
|
|||||||
expect(psychicEffectiveness).above(flameThrowerEffectiveness);
|
expect(psychicEffectiveness).above(flameThrowerEffectiveness);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not break from indirect damage", async () => {
|
it("should not break from indirect damage from status, weather or recoil", async () => {
|
||||||
game.override.enemySpecies(SpeciesId.GIGALITH);
|
game.override.enemySpecies(SpeciesId.GIGALITH).enemyAbility(AbilityId.SAND_STREAM);
|
||||||
game.override.enemyAbility(AbilityId.SAND_STREAM);
|
|
||||||
game.override.enemyMoveset(MoveId.WILL_O_WISP);
|
|
||||||
game.override.moveset([MoveId.FLARE_BLITZ]);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.ZOROARK, SpeciesId.AZUMARILL]);
|
await game.classicMode.startBattle([SpeciesId.ZOROARK, SpeciesId.AZUMARILL]);
|
||||||
|
|
||||||
game.move.select(MoveId.FLARE_BLITZ);
|
game.move.use(MoveId.FLARE_BLITZ);
|
||||||
|
await game.move.forceEnemyMove(MoveId.WILL_O_WISP);
|
||||||
await game.phaseInterceptor.to("TurnEndPhase");
|
await game.toEndOfTurn();
|
||||||
|
|
||||||
const zoroark = game.scene.getPlayerPokemon()!;
|
const zoroark = game.scene.getPlayerPokemon()!;
|
||||||
|
|
||||||
expect(!!zoroark.summonData.illusion).equals(true);
|
expect(!!zoroark.summonData.illusion).equals(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("copies the the name, nickname, gender, shininess, and pokeball from the illusion source", async () => {
|
it("copies the the name, nickname, gender, shininess, and pokeball from the illusion source", async () => {
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
game.override.enemyMoveset(MoveId.SPLASH);
|
||||||
await game.classicMode.startBattle([SpeciesId.ABRA, SpeciesId.ZOROARK, SpeciesId.AXEW]);
|
await game.classicMode.startBattle([SpeciesId.ABRA, SpeciesId.ZOROARK, SpeciesId.AXEW]);
|
||||||
|
|
||||||
const axew = game.scene.getPlayerParty().at(2)!;
|
const axew = game.scene.getPlayerParty().at(2)!;
|
||||||
axew.shiny = true;
|
axew.shiny = true;
|
||||||
axew.nickname = btoa(unescape(encodeURIComponent("axew nickname")));
|
axew.nickname = btoa(unescape(encodeURIComponent("axew nickname")));
|
||||||
|
@ -162,8 +162,7 @@ describe("Abilities - Imposter", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should stay transformed with the correct form after reload", async () => {
|
it("should stay transformed with the correct form after reload", async () => {
|
||||||
game.override.moveset([MoveId.ABSORB]);
|
game.override.moveset([MoveId.ABSORB]).enemySpecies(SpeciesId.UNOWN);
|
||||||
game.override.enemySpecies(SpeciesId.UNOWN);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.DITTO]);
|
await game.classicMode.startBattle([SpeciesId.DITTO]);
|
||||||
|
|
||||||
const enemy = game.scene.getEnemyPokemon()!;
|
const enemy = game.scene.getEnemyPokemon()!;
|
||||||
|
@ -62,7 +62,7 @@ describe("Abilities - Intimidate", () => {
|
|||||||
expect(playerPokemon.species.speciesId).toBe(SpeciesId.POOCHYENA);
|
expect(playerPokemon.species.speciesId).toBe(SpeciesId.POOCHYENA);
|
||||||
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(0);
|
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(0);
|
||||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-2);
|
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-2);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("should lower ATK stat stage by 1 for every enemy Pokemon in a double battle on entry", async () => {
|
it("should lower ATK stat stage by 1 for every enemy Pokemon in a double battle on entry", async () => {
|
||||||
game.override.battleStyle("double").startingWave(3);
|
game.override.battleStyle("double").startingWave(3);
|
||||||
@ -85,11 +85,10 @@ describe("Abilities - Intimidate", () => {
|
|||||||
expect(enemyField[1].getStatStage(Stat.ATK)).toBe(-2);
|
expect(enemyField[1].getStatStage(Stat.ATK)).toBe(-2);
|
||||||
expect(playerField[0].getStatStage(Stat.ATK)).toBe(-2);
|
expect(playerField[0].getStatStage(Stat.ATK)).toBe(-2);
|
||||||
expect(playerField[1].getStatStage(Stat.ATK)).toBe(-2);
|
expect(playerField[1].getStatStage(Stat.ATK)).toBe(-2);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("should not activate again if there is no switch or new entry", async () => {
|
it("should not activate again if there is no switch or new entry", async () => {
|
||||||
game.override.startingWave(2);
|
game.override.startingWave(2).moveset([MoveId.SPLASH]);
|
||||||
game.override.moveset([MoveId.SPLASH]);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]);
|
await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]);
|
||||||
|
|
||||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||||
@ -103,7 +102,7 @@ describe("Abilities - Intimidate", () => {
|
|||||||
|
|
||||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-1);
|
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-1);
|
||||||
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(-1);
|
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(-1);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("should lower ATK stat stage by 1 for every switch", async () => {
|
it("should lower ATK stat stage by 1 for every switch", async () => {
|
||||||
game.override.moveset([MoveId.SPLASH]).enemyMoveset([MoveId.VOLT_SWITCH]).startingWave(5);
|
game.override.moveset([MoveId.SPLASH]).enemyMoveset([MoveId.VOLT_SWITCH]).startingWave(5);
|
||||||
@ -130,5 +129,5 @@ describe("Abilities - Intimidate", () => {
|
|||||||
|
|
||||||
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(-3);
|
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(-3);
|
||||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0);
|
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0);
|
||||||
}, 200000);
|
});
|
||||||
});
|
});
|
||||||
|
@ -22,10 +22,11 @@ describe("Abilities - Intrepid Sword", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.enemySpecies(SpeciesId.ZACIAN);
|
.battleStyle("single")
|
||||||
game.override.enemyAbility(AbilityId.INTREPID_SWORD);
|
.enemySpecies(SpeciesId.ZACIAN)
|
||||||
game.override.ability(AbilityId.INTREPID_SWORD);
|
.enemyAbility(AbilityId.INTREPID_SWORD)
|
||||||
|
.ability(AbilityId.INTREPID_SWORD);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should raise ATK stat stage by 1 on entry", async () => {
|
it("should raise ATK stat stage by 1 on entry", async () => {
|
||||||
@ -38,5 +39,5 @@ describe("Abilities - Intrepid Sword", () => {
|
|||||||
|
|
||||||
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(1);
|
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(1);
|
||||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(1);
|
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(1);
|
||||||
}, 20000);
|
});
|
||||||
});
|
});
|
||||||
|
@ -108,8 +108,7 @@ describe("Abilities - Libero", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("ability applies correctly even if the type has changed by another ability", async () => {
|
test("ability applies correctly even if the type has changed by another ability", async () => {
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
game.override.moveset([MoveId.TACKLE]).passiveAbility(AbilityId.REFRIGERATE);
|
||||||
game.override.passiveAbility(AbilityId.REFRIGERATE);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -156,8 +155,7 @@ describe("Abilities - Libero", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("ability applies correctly even if the pokemon's move misses", async () => {
|
test("ability applies correctly even if the pokemon's move misses", async () => {
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
game.override.moveset([MoveId.TACKLE]).enemyMoveset(MoveId.SPLASH);
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -188,8 +186,7 @@ describe("Abilities - Libero", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("ability applies correctly even if the pokemon's move fails because of type immunity", async () => {
|
test("ability applies correctly even if the pokemon's move fails because of type immunity", async () => {
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
game.override.moveset([MoveId.TACKLE]).enemySpecies(SpeciesId.GASTLY);
|
||||||
game.override.enemySpecies(SpeciesId.GASTLY);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -262,8 +259,7 @@ describe("Abilities - Libero", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("ability applies correctly even if the pokemon's Trick-or-Treat fails", async () => {
|
test("ability applies correctly even if the pokemon's Trick-or-Treat fails", async () => {
|
||||||
game.override.moveset([MoveId.TRICK_OR_TREAT]);
|
game.override.moveset([MoveId.TRICK_OR_TREAT]).enemySpecies(SpeciesId.GASTLY);
|
||||||
game.override.enemySpecies(SpeciesId.GASTLY);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
|
@ -41,18 +41,16 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
it("should reflect basic status moves", async () => {
|
it("should reflect basic status moves", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
game.move.select(MoveId.GROWL);
|
game.move.use(MoveId.GROWL);
|
||||||
await game.phaseInterceptor.to("BerryPhase");
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
expect(game.scene.getPlayerPokemon()!.getStatStage(Stat.ATK)).toBe(-1);
|
expect(game.scene.getPlayerPokemon()!.getStatStage(Stat.ATK)).toBe(-1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not bounce moves while the target is in the semi-invulnerable state", async () => {
|
it("should not bounce moves while the target is in the semi-invulnerable state", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
game.override.moveset([MoveId.GROWL]);
|
|
||||||
game.override.enemyMoveset([MoveId.FLY]);
|
|
||||||
|
|
||||||
game.move.select(MoveId.GROWL);
|
game.move.use(MoveId.GROWL);
|
||||||
await game.move.selectEnemyMove(MoveId.FLY);
|
await game.move.forceEnemyMove(MoveId.FLY);
|
||||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||||
await game.phaseInterceptor.to("BerryPhase");
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
@ -61,11 +59,10 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
|
|
||||||
it("should individually bounce back multi-target moves", async () => {
|
it("should individually bounce back multi-target moves", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double");
|
||||||
game.override.moveset([MoveId.GROWL, MoveId.SPLASH]);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
game.move.select(MoveId.GROWL, 0);
|
game.move.use(MoveId.GROWL, 0);
|
||||||
game.move.select(MoveId.SPLASH, 1);
|
game.move.use(MoveId.SPLASH, 1);
|
||||||
await game.phaseInterceptor.to("BerryPhase");
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
const user = game.scene.getPlayerField()[0];
|
const user = game.scene.getPlayerField()[0];
|
||||||
@ -75,9 +72,8 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
it("should still bounce back a move that would otherwise fail", async () => {
|
it("should still bounce back a move that would otherwise fail", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
game.scene.getEnemyPokemon()?.setStatStage(Stat.ATK, -6);
|
game.scene.getEnemyPokemon()?.setStatStage(Stat.ATK, -6);
|
||||||
game.override.moveset([MoveId.GROWL]);
|
|
||||||
|
|
||||||
game.move.select(MoveId.GROWL);
|
game.move.use(MoveId.GROWL);
|
||||||
await game.phaseInterceptor.to("BerryPhase");
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
expect(game.scene.getPlayerPokemon()!.getStatStage(Stat.ATK)).toBe(-1);
|
expect(game.scene.getPlayerPokemon()!.getStatStage(Stat.ATK)).toBe(-1);
|
||||||
@ -107,29 +103,26 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
game.override.ability(AbilityId.MOLD_BREAKER);
|
game.override.ability(AbilityId.MOLD_BREAKER);
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
game.move.select(MoveId.GROWL);
|
game.move.use(MoveId.GROWL);
|
||||||
await game.phaseInterceptor.to("BerryPhase");
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
|
|
||||||
expect(game.scene.getEnemyPokemon()!.getStatStage(Stat.ATK)).toBe(-1);
|
expect(game.scene.getEnemyPokemon()!.getStatStage(Stat.ATK)).toBe(-1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should bounce back a spread status move against both pokemon", async () => {
|
it("should bounce back a spread status move against both pokemon", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double").enemyMoveset([MoveId.SPLASH]);
|
||||||
game.override.moveset([MoveId.GROWL, MoveId.SPLASH]);
|
|
||||||
game.override.enemyMoveset([MoveId.SPLASH]);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
game.move.select(MoveId.GROWL, 0);
|
game.move.use(MoveId.GROWL, 0);
|
||||||
game.move.select(MoveId.SPLASH, 1);
|
game.move.use(MoveId.SPLASH, 1);
|
||||||
|
|
||||||
await game.phaseInterceptor.to("BerryPhase");
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
expect(game.scene.getPlayerField().every(p => p.getStatStage(Stat.ATK) === -2)).toBeTruthy();
|
expect(game.scene.getPlayerField().every(p => p.getStatStage(Stat.ATK) === -2)).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should only bounce spikes back once in doubles when both targets have magic bounce", async () => {
|
it("should only bounce spikes back once in doubles when both targets have magic bounce", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double").moveset([MoveId.SPIKES]);
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
game.override.moveset([MoveId.SPIKES]);
|
|
||||||
|
|
||||||
game.move.select(MoveId.SPIKES);
|
game.move.select(MoveId.SPIKES);
|
||||||
await game.phaseInterceptor.to("BerryPhase");
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
@ -139,8 +132,7 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should bounce spikes even when the target is protected", async () => {
|
it("should bounce spikes even when the target is protected", async () => {
|
||||||
game.override.moveset([MoveId.SPIKES]);
|
game.override.moveset([MoveId.SPIKES]).enemyMoveset([MoveId.PROTECT]);
|
||||||
game.override.enemyMoveset([MoveId.PROTECT]);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
game.move.select(MoveId.SPIKES);
|
game.move.select(MoveId.SPIKES);
|
||||||
@ -149,8 +141,7 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not bounce spikes when the target is in the semi-invulnerable state", async () => {
|
it("should not bounce spikes when the target is in the semi-invulnerable state", async () => {
|
||||||
game.override.moveset([MoveId.SPIKES]);
|
game.override.moveset([MoveId.SPIKES]).enemyMoveset([MoveId.FLY]);
|
||||||
game.override.enemyMoveset([MoveId.FLY]);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
game.move.select(MoveId.SPIKES);
|
game.move.select(MoveId.SPIKES);
|
||||||
@ -160,9 +151,8 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not bounce back curse", async () => {
|
it("should not bounce back curse", async () => {
|
||||||
game.override.starterSpecies(SpeciesId.GASTLY);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.GASTLY]);
|
|
||||||
game.override.moveset([MoveId.CURSE]);
|
game.override.moveset([MoveId.CURSE]);
|
||||||
|
await game.classicMode.startBattle([SpeciesId.GASTLY]);
|
||||||
|
|
||||||
game.move.select(MoveId.CURSE);
|
game.move.select(MoveId.CURSE);
|
||||||
await game.phaseInterceptor.to("BerryPhase");
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
@ -171,8 +161,7 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not cause encore to be interrupted after bouncing", async () => {
|
it("should not cause encore to be interrupted after bouncing", async () => {
|
||||||
game.override.moveset([MoveId.SPLASH, MoveId.GROWL, MoveId.ENCORE]);
|
game.override.moveset([MoveId.SPLASH, MoveId.GROWL, MoveId.ENCORE]).enemyMoveset([MoveId.TACKLE, MoveId.GROWL]);
|
||||||
game.override.enemyMoveset([MoveId.TACKLE, MoveId.GROWL]);
|
|
||||||
// game.override.ability(AbilityId.MOLD_BREAKER);
|
// game.override.ability(AbilityId.MOLD_BREAKER);
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||||
@ -199,9 +188,10 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
|
|
||||||
// TODO: encore is failing if the last move was virtual.
|
// TODO: encore is failing if the last move was virtual.
|
||||||
it.todo("should not cause the bounced move to count for encore", async () => {
|
it.todo("should not cause the bounced move to count for encore", async () => {
|
||||||
game.override.moveset([MoveId.SPLASH, MoveId.GROWL, MoveId.ENCORE]);
|
game.override
|
||||||
game.override.enemyMoveset([MoveId.GROWL, MoveId.TACKLE]);
|
.moveset([MoveId.SPLASH, MoveId.GROWL, MoveId.ENCORE])
|
||||||
game.override.enemyAbility(AbilityId.MAGIC_BOUNCE);
|
.enemyMoveset([MoveId.GROWL, MoveId.TACKLE])
|
||||||
|
.enemyAbility(AbilityId.MAGIC_BOUNCE);
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
const playerPokemon = game.scene.getPlayerPokemon()!;
|
const playerPokemon = game.scene.getPlayerPokemon()!;
|
||||||
@ -227,9 +217,8 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
|
|
||||||
// TODO: stomping tantrum should consider moves that were bounced.
|
// TODO: stomping tantrum should consider moves that were bounced.
|
||||||
it.todo("should cause stomping tantrum to double in power when the last move was bounced", async () => {
|
it.todo("should cause stomping tantrum to double in power when the last move was bounced", async () => {
|
||||||
game.override.battleStyle("single");
|
game.override.battleStyle("single").moveset([MoveId.STOMPING_TANTRUM, MoveId.CHARM]);
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
game.override.moveset([MoveId.STOMPING_TANTRUM, MoveId.CHARM]);
|
|
||||||
|
|
||||||
const stomping_tantrum = allMoves[MoveId.STOMPING_TANTRUM];
|
const stomping_tantrum = allMoves[MoveId.STOMPING_TANTRUM];
|
||||||
vi.spyOn(stomping_tantrum, "calculateBattlePower");
|
vi.spyOn(stomping_tantrum, "calculateBattlePower");
|
||||||
@ -242,36 +231,30 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
expect(stomping_tantrum.calculateBattlePower).toHaveReturnedWith(150);
|
expect(stomping_tantrum.calculateBattlePower).toHaveReturnedWith(150);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: stomping tantrum should consider moves that were bounced.
|
// TODO: stomping tantrum should consider moves that were bounced
|
||||||
it.todo(
|
it.todo("should boost enemy's stomping tantrum after failed bounce", async () => {
|
||||||
"should properly cause the enemy's stomping tantrum to be doubled in power after bouncing and failing",
|
game.override.enemyMoveset([MoveId.STOMPING_TANTRUM, MoveId.SPLASH, MoveId.CHARM]);
|
||||||
async () => {
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||||
game.override.enemyMoveset([MoveId.STOMPING_TANTRUM, MoveId.SPLASH, MoveId.CHARM]);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
|
||||||
|
|
||||||
const stomping_tantrum = allMoves[MoveId.STOMPING_TANTRUM];
|
const stomping_tantrum = allMoves[MoveId.STOMPING_TANTRUM];
|
||||||
const enemy = game.scene.getEnemyPokemon()!;
|
const enemy = game.scene.getEnemyPokemon()!;
|
||||||
vi.spyOn(stomping_tantrum, "calculateBattlePower");
|
vi.spyOn(stomping_tantrum, "calculateBattlePower");
|
||||||
|
|
||||||
game.move.select(MoveId.SPORE);
|
// Spore gets reflected back onto us
|
||||||
await game.move.selectEnemyMove(MoveId.CHARM);
|
game.move.select(MoveId.SPORE);
|
||||||
await game.phaseInterceptor.to("TurnEndPhase");
|
await game.move.selectEnemyMove(MoveId.CHARM);
|
||||||
expect(enemy.getLastXMoves(1)[0].result).toBe("success");
|
await game.toNextTurn();
|
||||||
|
expect(enemy.getLastXMoves(1)[0].result).toBe("success");
|
||||||
|
|
||||||
await game.phaseInterceptor.to("BerryPhase");
|
game.move.select(MoveId.SPORE);
|
||||||
expect(stomping_tantrum.calculateBattlePower).toHaveReturnedWith(75);
|
await game.move.selectEnemyMove(MoveId.STOMPING_TANTRUM);
|
||||||
|
await game.toNextTurn();
|
||||||
await game.toNextTurn();
|
expect(stomping_tantrum.calculateBattlePower).toHaveReturnedWith(150);
|
||||||
game.move.select(MoveId.GROWL);
|
});
|
||||||
await game.phaseInterceptor.to("BerryPhase");
|
|
||||||
expect(stomping_tantrum.calculateBattlePower).toHaveReturnedWith(75);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
it("should respect immunities when bouncing a move", async () => {
|
it("should respect immunities when bouncing a move", async () => {
|
||||||
vi.spyOn(allMoves[MoveId.THUNDER_WAVE], "accuracy", "get").mockReturnValue(100);
|
vi.spyOn(allMoves[MoveId.THUNDER_WAVE], "accuracy", "get").mockReturnValue(100);
|
||||||
game.override.moveset([MoveId.THUNDER_WAVE, MoveId.GROWL]);
|
game.override.moveset([MoveId.THUNDER_WAVE, MoveId.GROWL]).ability(AbilityId.SOUNDPROOF);
|
||||||
game.override.ability(AbilityId.SOUNDPROOF);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.PHANPY]);
|
await game.classicMode.startBattle([SpeciesId.PHANPY]);
|
||||||
|
|
||||||
// Turn 1 - thunder wave immunity test
|
// Turn 1 - thunder wave immunity test
|
||||||
@ -309,8 +292,7 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should always apply the leftmost available target's magic bounce when bouncing moves like sticky webs in doubles", async () => {
|
it("should always apply the leftmost available target's magic bounce when bouncing moves like sticky webs in doubles", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double").moveset([MoveId.STICKY_WEB, MoveId.SPLASH, MoveId.TRICK_ROOM]);
|
||||||
game.override.moveset([MoveId.STICKY_WEB, MoveId.SPLASH, MoveId.TRICK_ROOM]);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MAGIKARP]);
|
||||||
const [enemy_1, enemy_2] = game.scene.getEnemyField();
|
const [enemy_1, enemy_2] = game.scene.getEnemyField();
|
||||||
@ -345,6 +327,7 @@ describe("Abilities - Magic Bounce", () => {
|
|||||||
it("should not bounce back status moves that hit through semi-invulnerable states", async () => {
|
it("should not bounce back status moves that hit through semi-invulnerable states", async () => {
|
||||||
game.override.moveset([MoveId.TOXIC, MoveId.CHARM]);
|
game.override.moveset([MoveId.TOXIC, MoveId.CHARM]);
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||||
|
|
||||||
game.move.select(MoveId.TOXIC);
|
game.move.select(MoveId.TOXIC);
|
||||||
await game.move.selectEnemyMove(MoveId.FLY);
|
await game.move.selectEnemyMove(MoveId.FLY);
|
||||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||||
|
@ -30,16 +30,16 @@ describe("Abilities - Magic Guard", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
|
|
||||||
/** Player Pokemon overrides */
|
game.override
|
||||||
game.override.ability(AbilityId.MAGIC_GUARD);
|
/** Player Pokemon overrides */
|
||||||
game.override.moveset([MoveId.SPLASH]);
|
.ability(AbilityId.MAGIC_GUARD)
|
||||||
game.override.startingLevel(100);
|
.moveset([MoveId.SPLASH])
|
||||||
|
.startingLevel(100)
|
||||||
/** Enemy Pokemon overrides */
|
/** Enemy Pokemon overrides */
|
||||||
game.override.enemySpecies(SpeciesId.SNORLAX);
|
.enemySpecies(SpeciesId.SNORLAX)
|
||||||
game.override.enemyAbility(AbilityId.INSOMNIA);
|
.enemyAbility(AbilityId.INSOMNIA)
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
.enemyMoveset(MoveId.SPLASH)
|
||||||
game.override.enemyLevel(100);
|
.enemyLevel(100);
|
||||||
});
|
});
|
||||||
|
|
||||||
//Bulbapedia Reference: https://bulbapedia.bulbagarden.net/wiki/Magic_Guard_(Ability)
|
//Bulbapedia Reference: https://bulbapedia.bulbagarden.net/wiki/Magic_Guard_(Ability)
|
||||||
@ -89,8 +89,9 @@ describe("Abilities - Magic Guard", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("ability effect should not persist when the ability is replaced", async () => {
|
it("ability effect should not persist when the ability is replaced", async () => {
|
||||||
game.override.enemyMoveset([MoveId.WORRY_SEED, MoveId.WORRY_SEED, MoveId.WORRY_SEED, MoveId.WORRY_SEED]);
|
game.override
|
||||||
game.override.statusEffect(StatusEffect.POISON);
|
.enemyMoveset([MoveId.WORRY_SEED, MoveId.WORRY_SEED, MoveId.WORRY_SEED, MoveId.WORRY_SEED])
|
||||||
|
.statusEffect(StatusEffect.POISON);
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -108,8 +109,7 @@ describe("Abilities - Magic Guard", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Magic Guard prevents damage caused by burn but other non-damaging effects are still applied", async () => {
|
it("Magic Guard prevents damage caused by burn but other non-damaging effects are still applied", async () => {
|
||||||
game.override.enemyStatusEffect(StatusEffect.BURN);
|
game.override.enemyStatusEffect(StatusEffect.BURN).enemyAbility(AbilityId.MAGIC_GUARD);
|
||||||
game.override.enemyAbility(AbilityId.MAGIC_GUARD);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -130,8 +130,7 @@ describe("Abilities - Magic Guard", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Magic Guard prevents damage caused by toxic but other non-damaging effects are still applied", async () => {
|
it("Magic Guard prevents damage caused by toxic but other non-damaging effects are still applied", async () => {
|
||||||
game.override.enemyStatusEffect(StatusEffect.TOXIC);
|
game.override.enemyStatusEffect(StatusEffect.TOXIC).enemyAbility(AbilityId.MAGIC_GUARD);
|
||||||
game.override.enemyAbility(AbilityId.MAGIC_GUARD);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -208,8 +207,7 @@ describe("Abilities - Magic Guard", () => {
|
|||||||
|
|
||||||
it("Magic Guard prevents against damage from volatile status effects", async () => {
|
it("Magic Guard prevents against damage from volatile status effects", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.DUSKULL]);
|
await game.classicMode.startBattle([SpeciesId.DUSKULL]);
|
||||||
game.override.moveset([MoveId.CURSE]);
|
game.override.moveset([MoveId.CURSE]).enemyAbility(AbilityId.MAGIC_GUARD);
|
||||||
game.override.enemyAbility(AbilityId.MAGIC_GUARD);
|
|
||||||
|
|
||||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
|
||||||
@ -331,8 +329,9 @@ describe("Abilities - Magic Guard", () => {
|
|||||||
//Tests the ability Bad Dreams
|
//Tests the ability Bad Dreams
|
||||||
game.override.statusEffect(StatusEffect.SLEEP);
|
game.override.statusEffect(StatusEffect.SLEEP);
|
||||||
//enemy pokemon is given Spore just in case player pokemon somehow awakens during test
|
//enemy pokemon is given Spore just in case player pokemon somehow awakens during test
|
||||||
game.override.enemyMoveset([MoveId.SPORE, MoveId.SPORE, MoveId.SPORE, MoveId.SPORE]);
|
game.override
|
||||||
game.override.enemyAbility(AbilityId.BAD_DREAMS);
|
.enemyMoveset([MoveId.SPORE, MoveId.SPORE, MoveId.SPORE, MoveId.SPORE])
|
||||||
|
.enemyAbility(AbilityId.BAD_DREAMS);
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -353,8 +352,7 @@ describe("Abilities - Magic Guard", () => {
|
|||||||
|
|
||||||
it("Magic Guard prevents damage from abilities with PostFaintContactDamageAbAttr", async () => {
|
it("Magic Guard prevents damage from abilities with PostFaintContactDamageAbAttr", async () => {
|
||||||
//Tests the abilities Innards Out/Aftermath
|
//Tests the abilities Innards Out/Aftermath
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
game.override.moveset([MoveId.TACKLE]).enemyAbility(AbilityId.AFTERMATH);
|
||||||
game.override.enemyAbility(AbilityId.AFTERMATH);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -377,8 +375,7 @@ describe("Abilities - Magic Guard", () => {
|
|||||||
|
|
||||||
it("Magic Guard prevents damage from abilities with PostDefendContactDamageAbAttr", async () => {
|
it("Magic Guard prevents damage from abilities with PostDefendContactDamageAbAttr", async () => {
|
||||||
//Tests the abilities Iron Barbs/Rough Skin
|
//Tests the abilities Iron Barbs/Rough Skin
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
game.override.moveset([MoveId.TACKLE]).enemyAbility(AbilityId.IRON_BARBS);
|
||||||
game.override.enemyAbility(AbilityId.IRON_BARBS);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -400,8 +397,7 @@ describe("Abilities - Magic Guard", () => {
|
|||||||
|
|
||||||
it("Magic Guard prevents damage from abilities with ReverseDrainAbAttr", async () => {
|
it("Magic Guard prevents damage from abilities with ReverseDrainAbAttr", async () => {
|
||||||
//Tests the ability Liquid Ooze
|
//Tests the ability Liquid Ooze
|
||||||
game.override.moveset([MoveId.ABSORB]);
|
game.override.moveset([MoveId.ABSORB]).enemyAbility(AbilityId.LIQUID_OOZE);
|
||||||
game.override.enemyAbility(AbilityId.LIQUID_OOZE);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -422,9 +418,7 @@ describe("Abilities - Magic Guard", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Magic Guard prevents HP loss from abilities with PostWeatherLapseDamageAbAttr", async () => {
|
it("Magic Guard prevents HP loss from abilities with PostWeatherLapseDamageAbAttr", async () => {
|
||||||
//Tests the abilities Solar Power/Dry Skin
|
game.override.passiveAbility(AbilityId.SOLAR_POWER).weather(WeatherType.SUNNY);
|
||||||
game.override.passiveAbility(AbilityId.SOLAR_POWER);
|
|
||||||
game.override.weather(WeatherType.SUNNY);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
const leadPokemon = game.scene.getPlayerPokemon()!;
|
const leadPokemon = game.scene.getPlayerPokemon()!;
|
||||||
|
@ -37,8 +37,7 @@ describe("Ability - Mirror Armor", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Player side + single battle Intimidate - opponent loses stats", async () => {
|
it("Player side + single battle Intimidate - opponent loses stats", async () => {
|
||||||
game.override.ability(AbilityId.MIRROR_ARMOR);
|
game.override.ability(AbilityId.MIRROR_ARMOR).enemyAbility(AbilityId.INTIMIDATE);
|
||||||
game.override.enemyAbility(AbilityId.INTIMIDATE);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||||
|
|
||||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
@ -54,8 +53,7 @@ describe("Ability - Mirror Armor", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Enemy side + single battle Intimidate - player loses stats", async () => {
|
it("Enemy side + single battle Intimidate - player loses stats", async () => {
|
||||||
game.override.enemyAbility(AbilityId.MIRROR_ARMOR);
|
game.override.enemyAbility(AbilityId.MIRROR_ARMOR).ability(AbilityId.INTIMIDATE);
|
||||||
game.override.ability(AbilityId.INTIMIDATE);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||||
|
|
||||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
@ -71,9 +69,7 @@ describe("Ability - Mirror Armor", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Player side + double battle Intimidate - opponents each lose -2 atk", async () => {
|
it("Player side + double battle Intimidate - opponents each lose -2 atk", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double").ability(AbilityId.MIRROR_ARMOR).enemyAbility(AbilityId.INTIMIDATE);
|
||||||
game.override.ability(AbilityId.MIRROR_ARMOR);
|
|
||||||
game.override.enemyAbility(AbilityId.INTIMIDATE);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.CHARMANDER]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.CHARMANDER]);
|
||||||
|
|
||||||
const [enemy1, enemy2] = game.scene.getEnemyField();
|
const [enemy1, enemy2] = game.scene.getEnemyField();
|
||||||
@ -93,9 +89,7 @@ describe("Ability - Mirror Armor", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Enemy side + double battle Intimidate - players each lose -2 atk", async () => {
|
it("Enemy side + double battle Intimidate - players each lose -2 atk", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double").enemyAbility(AbilityId.MIRROR_ARMOR).ability(AbilityId.INTIMIDATE);
|
||||||
game.override.enemyAbility(AbilityId.MIRROR_ARMOR);
|
|
||||||
game.override.ability(AbilityId.INTIMIDATE);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.CHARMANDER]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.CHARMANDER]);
|
||||||
|
|
||||||
const [enemy1, enemy2] = game.scene.getEnemyField();
|
const [enemy1, enemy2] = game.scene.getEnemyField();
|
||||||
@ -115,8 +109,7 @@ describe("Ability - Mirror Armor", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Player side + single battle Intimidate + Tickle - opponent loses stats", async () => {
|
it("Player side + single battle Intimidate + Tickle - opponent loses stats", async () => {
|
||||||
game.override.ability(AbilityId.MIRROR_ARMOR);
|
game.override.ability(AbilityId.MIRROR_ARMOR).enemyAbility(AbilityId.INTIMIDATE);
|
||||||
game.override.enemyAbility(AbilityId.INTIMIDATE);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||||
|
|
||||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
@ -134,9 +127,7 @@ describe("Ability - Mirror Armor", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Player side + double battle Intimidate + Tickle - opponents each lose -3 atk, -1 def", async () => {
|
it("Player side + double battle Intimidate + Tickle - opponents each lose -3 atk, -1 def", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double").ability(AbilityId.MIRROR_ARMOR).enemyAbility(AbilityId.INTIMIDATE);
|
||||||
game.override.ability(AbilityId.MIRROR_ARMOR);
|
|
||||||
game.override.enemyAbility(AbilityId.INTIMIDATE);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.CHARMANDER]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.CHARMANDER]);
|
||||||
|
|
||||||
const [enemy1, enemy2] = game.scene.getEnemyField();
|
const [enemy1, enemy2] = game.scene.getEnemyField();
|
||||||
@ -159,8 +150,7 @@ describe("Ability - Mirror Armor", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Enemy side + single battle Intimidate + Tickle - player loses stats", async () => {
|
it("Enemy side + single battle Intimidate + Tickle - player loses stats", async () => {
|
||||||
game.override.enemyAbility(AbilityId.MIRROR_ARMOR);
|
game.override.enemyAbility(AbilityId.MIRROR_ARMOR).ability(AbilityId.INTIMIDATE);
|
||||||
game.override.ability(AbilityId.INTIMIDATE);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||||
|
|
||||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
@ -178,8 +168,7 @@ describe("Ability - Mirror Armor", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Player side + single battle Intimidate + oppoenent has white smoke - no one loses stats", async () => {
|
it("Player side + single battle Intimidate + oppoenent has white smoke - no one loses stats", async () => {
|
||||||
game.override.enemyAbility(AbilityId.WHITE_SMOKE);
|
game.override.enemyAbility(AbilityId.WHITE_SMOKE).ability(AbilityId.MIRROR_ARMOR);
|
||||||
game.override.ability(AbilityId.MIRROR_ARMOR);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||||
|
|
||||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
@ -197,8 +186,7 @@ describe("Ability - Mirror Armor", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Enemy side + single battle Intimidate + player has white smoke - no one loses stats", async () => {
|
it("Enemy side + single battle Intimidate + player has white smoke - no one loses stats", async () => {
|
||||||
game.override.ability(AbilityId.WHITE_SMOKE);
|
game.override.ability(AbilityId.WHITE_SMOKE).enemyAbility(AbilityId.MIRROR_ARMOR);
|
||||||
game.override.enemyAbility(AbilityId.MIRROR_ARMOR);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||||
|
|
||||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
@ -252,9 +240,7 @@ describe("Ability - Mirror Armor", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Both sides have mirror armor - does not loop, player loses attack", async () => {
|
it("Both sides have mirror armor - does not loop, player loses attack", async () => {
|
||||||
game.override.enemyAbility(AbilityId.MIRROR_ARMOR);
|
game.override.enemyAbility(AbilityId.MIRROR_ARMOR).ability(AbilityId.MIRROR_ARMOR).ability(AbilityId.INTIMIDATE);
|
||||||
game.override.ability(AbilityId.MIRROR_ARMOR);
|
|
||||||
game.override.ability(AbilityId.INTIMIDATE);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||||
|
|
||||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
@ -288,8 +274,7 @@ describe("Ability - Mirror Armor", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Double battle + sticky web applied player side - player switches out and enemy 1 should lose -1 speed", async () => {
|
it("Double battle + sticky web applied player side - player switches out and enemy 1 should lose -1 speed", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double").ability(AbilityId.MIRROR_ARMOR);
|
||||||
game.override.ability(AbilityId.MIRROR_ARMOR);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.CHARMANDER, SpeciesId.SQUIRTLE]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.CHARMANDER, SpeciesId.SQUIRTLE]);
|
||||||
|
|
||||||
const [enemy1, enemy2] = game.scene.getEnemyField();
|
const [enemy1, enemy2] = game.scene.getEnemyField();
|
||||||
|
@ -27,13 +27,14 @@ describe("Abilities - Moxie", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
const moveToUse = MoveId.AERIAL_ACE;
|
const moveToUse = MoveId.AERIAL_ACE;
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.enemySpecies(SpeciesId.RATTATA);
|
.battleStyle("single")
|
||||||
game.override.enemyAbility(AbilityId.MOXIE);
|
.enemySpecies(SpeciesId.RATTATA)
|
||||||
game.override.ability(AbilityId.MOXIE);
|
.enemyAbility(AbilityId.MOXIE)
|
||||||
game.override.startingLevel(2000);
|
.ability(AbilityId.MOXIE)
|
||||||
game.override.moveset([moveToUse]);
|
.startingLevel(2000)
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
.moveset([moveToUse])
|
||||||
|
.enemyMoveset(MoveId.SPLASH);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should raise ATK stat stage by 1 when winning a battle", async () => {
|
it("should raise ATK stat stage by 1 when winning a battle", async () => {
|
||||||
@ -48,7 +49,7 @@ describe("Abilities - Moxie", () => {
|
|||||||
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(VictoryPhase);
|
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(VictoryPhase);
|
||||||
|
|
||||||
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(1);
|
expect(playerPokemon.getStatStage(Stat.ATK)).toBe(1);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
// TODO: Activate this test when MOXIE is corrected to work on faint and not on battle victory
|
// TODO: Activate this test when MOXIE is corrected to work on faint and not on battle victory
|
||||||
it.todo(
|
it.todo(
|
||||||
|
@ -63,7 +63,7 @@ describe("Abilities - Mycelium Might", () => {
|
|||||||
|
|
||||||
// Despite the opponent's ability (Clear Body), its ATK stat stage is still reduced.
|
// Despite the opponent's ability (Clear Body), its ATK stat stage is still reduced.
|
||||||
expect(enemyPokemon?.getStatStage(Stat.ATK)).toBe(-1);
|
expect(enemyPokemon?.getStatStage(Stat.ATK)).toBe(-1);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("will still go first if a status move that is in a higher priority bracket than the opponent's move is used", async () => {
|
it("will still go first if a status move that is in a higher priority bracket than the opponent's move is used", async () => {
|
||||||
game.override.enemyMoveset(MoveId.TACKLE);
|
game.override.enemyMoveset(MoveId.TACKLE);
|
||||||
@ -86,7 +86,7 @@ describe("Abilities - Mycelium Might", () => {
|
|||||||
await game.phaseInterceptor.to(TurnEndPhase);
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
// Despite the opponent's ability (Clear Body), its ATK stat stage is still reduced.
|
// Despite the opponent's ability (Clear Body), its ATK stat stage is still reduced.
|
||||||
expect(enemyPokemon?.getStatStage(Stat.ATK)).toBe(-1);
|
expect(enemyPokemon?.getStatStage(Stat.ATK)).toBe(-1);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("will not affect non-status moves", async () => {
|
it("will not affect non-status moves", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
|
await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
|
||||||
@ -105,5 +105,5 @@ describe("Abilities - Mycelium Might", () => {
|
|||||||
// This means that the commandOrder should be identical to the speedOrder
|
// This means that the commandOrder should be identical to the speedOrder
|
||||||
expect(speedOrder).toEqual([playerIndex, enemyIndex]);
|
expect(speedOrder).toEqual([playerIndex, enemyIndex]);
|
||||||
expect(commandOrder).toEqual([playerIndex, enemyIndex]);
|
expect(commandOrder).toEqual([playerIndex, enemyIndex]);
|
||||||
}, 20000);
|
});
|
||||||
});
|
});
|
||||||
|
@ -45,8 +45,9 @@ describe("Abilities - Normalize", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not apply the old type boost item after changing a move's type", async () => {
|
it("should not apply the old type boost item after changing a move's type", async () => {
|
||||||
game.override.startingHeldItems([{ name: "ATTACK_TYPE_BOOSTER", count: 1, type: PokemonType.GRASS }]);
|
game.override
|
||||||
game.override.moveset([MoveId.LEAFAGE]);
|
.startingHeldItems([{ name: "ATTACK_TYPE_BOOSTER", count: 1, type: PokemonType.GRASS }])
|
||||||
|
.moveset([MoveId.LEAFAGE]);
|
||||||
|
|
||||||
const powerSpy = vi.spyOn(allMoves[MoveId.LEAFAGE], "calculateBattlePower");
|
const powerSpy = vi.spyOn(allMoves[MoveId.LEAFAGE], "calculateBattlePower");
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
@ -58,8 +59,9 @@ describe("Abilities - Normalize", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should apply silk scarf's power boost after changing a move's type", async () => {
|
it("should apply silk scarf's power boost after changing a move's type", async () => {
|
||||||
game.override.startingHeldItems([{ name: "ATTACK_TYPE_BOOSTER", count: 1, type: PokemonType.NORMAL }]);
|
game.override
|
||||||
game.override.moveset([MoveId.LEAFAGE]);
|
.startingHeldItems([{ name: "ATTACK_TYPE_BOOSTER", count: 1, type: PokemonType.NORMAL }])
|
||||||
|
.moveset([MoveId.LEAFAGE]);
|
||||||
|
|
||||||
const powerSpy = vi.spyOn(allMoves[MoveId.LEAFAGE], "calculateBattlePower");
|
const powerSpy = vi.spyOn(allMoves[MoveId.LEAFAGE], "calculateBattlePower");
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
@ -26,14 +26,15 @@ describe("Abilities - Parental Bond", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.disableCrits();
|
.battleStyle("single")
|
||||||
game.override.ability(AbilityId.PARENTAL_BOND);
|
.disableCrits()
|
||||||
game.override.enemySpecies(SpeciesId.SNORLAX);
|
.ability(AbilityId.PARENTAL_BOND)
|
||||||
game.override.enemyAbility(AbilityId.FUR_COAT);
|
.enemySpecies(SpeciesId.SNORLAX)
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
.enemyAbility(AbilityId.FUR_COAT)
|
||||||
game.override.startingLevel(100);
|
.enemyMoveset(MoveId.SPLASH)
|
||||||
game.override.enemyLevel(100);
|
.startingLevel(100)
|
||||||
|
.enemyLevel(100);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should add second strike to attack move", async () => {
|
it("should add second strike to attack move", async () => {
|
||||||
@ -61,8 +62,7 @@ describe("Abilities - Parental Bond", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should apply secondary effects to both strikes", async () => {
|
it("should apply secondary effects to both strikes", async () => {
|
||||||
game.override.moveset([MoveId.POWER_UP_PUNCH]);
|
game.override.moveset([MoveId.POWER_UP_PUNCH]).enemySpecies(SpeciesId.AMOONGUSS);
|
||||||
game.override.enemySpecies(SpeciesId.AMOONGUSS);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -148,8 +148,7 @@ describe("Abilities - Parental Bond", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not apply multiplier to counter moves", async () => {
|
it("should not apply multiplier to counter moves", async () => {
|
||||||
game.override.moveset([MoveId.COUNTER]);
|
game.override.moveset([MoveId.COUNTER]).enemyMoveset([MoveId.TACKLE]);
|
||||||
game.override.enemyMoveset([MoveId.TACKLE]);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.SHUCKLE]);
|
await game.classicMode.startBattle([SpeciesId.SHUCKLE]);
|
||||||
|
|
||||||
@ -167,9 +166,7 @@ describe("Abilities - Parental Bond", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not apply to multi-target moves", async () => {
|
it("should not apply to multi-target moves", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double").moveset([MoveId.EARTHQUAKE]).passiveAbility(AbilityId.LEVITATE);
|
||||||
game.override.moveset([MoveId.EARTHQUAKE]);
|
|
||||||
game.override.passiveAbility(AbilityId.LEVITATE);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.FEEBAS]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.FEEBAS]);
|
||||||
|
|
||||||
@ -237,8 +234,7 @@ describe("Abilities - Parental Bond", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Moves boosted by this ability and Multi-Lens should strike 3 times", async () => {
|
it("Moves boosted by this ability and Multi-Lens should strike 3 times", async () => {
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
game.override.moveset([MoveId.TACKLE]).startingHeldItems([{ name: "MULTI_LENS", count: 1 }]);
|
||||||
game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -252,8 +248,7 @@ describe("Abilities - Parental Bond", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Seismic Toss boosted by this ability and Multi-Lens should strike 3 times", async () => {
|
it("Seismic Toss boosted by this ability and Multi-Lens should strike 3 times", async () => {
|
||||||
game.override.moveset([MoveId.SEISMIC_TOSS]);
|
game.override.moveset([MoveId.SEISMIC_TOSS]).startingHeldItems([{ name: "MULTI_LENS", count: 1 }]);
|
||||||
game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -378,8 +373,7 @@ describe("Abilities - Parental Bond", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not cause user to hit into King's Shield more than once", async () => {
|
it("should not cause user to hit into King's Shield more than once", async () => {
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
game.override.moveset([MoveId.TACKLE]).enemyMoveset([MoveId.KINGS_SHIELD]);
|
||||||
game.override.enemyMoveset([MoveId.KINGS_SHIELD]);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -393,8 +387,7 @@ describe("Abilities - Parental Bond", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not cause user to hit into Storm Drain more than once", async () => {
|
it("should not cause user to hit into Storm Drain more than once", async () => {
|
||||||
game.override.moveset([MoveId.WATER_GUN]);
|
game.override.moveset([MoveId.WATER_GUN]).enemyAbility(AbilityId.STORM_DRAIN);
|
||||||
game.override.enemyAbility(AbilityId.STORM_DRAIN);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
|
@ -21,19 +21,18 @@ describe("Abilities - Perish Song", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.disableCrits();
|
.battleStyle("single")
|
||||||
|
.disableCrits()
|
||||||
game.override.enemySpecies(SpeciesId.MAGIKARP);
|
.enemySpecies(SpeciesId.MAGIKARP)
|
||||||
game.override.enemyAbility(AbilityId.BALL_FETCH);
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
|
.starterSpecies(SpeciesId.CURSOLA)
|
||||||
game.override.starterSpecies(SpeciesId.CURSOLA);
|
.ability(AbilityId.PERISH_BODY)
|
||||||
game.override.ability(AbilityId.PERISH_BODY);
|
.moveset([MoveId.SPLASH])
|
||||||
game.override.moveset([MoveId.SPLASH]);
|
.enemyMoveset([MoveId.AQUA_JET]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should trigger when hit with damaging move", async () => {
|
it("should trigger when hit with damaging move", async () => {
|
||||||
game.override.enemyMoveset([MoveId.AQUA_JET]);
|
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle();
|
||||||
const cursola = game.scene.getPlayerPokemon();
|
const cursola = game.scene.getPlayerPokemon();
|
||||||
const magikarp = game.scene.getEnemyPokemon();
|
const magikarp = game.scene.getEnemyPokemon();
|
||||||
@ -46,7 +45,7 @@ describe("Abilities - Perish Song", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should trigger even when fainting", async () => {
|
it("should trigger even when fainting", async () => {
|
||||||
game.override.enemyMoveset([MoveId.AQUA_JET]).enemyLevel(100).startingLevel(1);
|
game.override.enemyLevel(100).startingLevel(1);
|
||||||
await game.classicMode.startBattle([SpeciesId.CURSOLA, SpeciesId.FEEBAS]);
|
await game.classicMode.startBattle([SpeciesId.CURSOLA, SpeciesId.FEEBAS]);
|
||||||
const magikarp = game.scene.getEnemyPokemon();
|
const magikarp = game.scene.getEnemyPokemon();
|
||||||
|
|
||||||
@ -87,9 +86,10 @@ describe("Abilities - Perish Song", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should activate if cursola already has perish song, but not reset its counter", async () => {
|
it("should activate if cursola already has perish song, but not reset its counter", async () => {
|
||||||
game.override.enemyMoveset([MoveId.PERISH_SONG, MoveId.AQUA_JET, MoveId.SPLASH]);
|
game.override
|
||||||
game.override.moveset([MoveId.WHIRLWIND, MoveId.SPLASH]);
|
.enemyMoveset([MoveId.PERISH_SONG, MoveId.AQUA_JET, MoveId.SPLASH])
|
||||||
game.override.startingWave(5);
|
.moveset([MoveId.WHIRLWIND, MoveId.SPLASH])
|
||||||
|
.startingWave(5);
|
||||||
await game.classicMode.startBattle([SpeciesId.CURSOLA]);
|
await game.classicMode.startBattle([SpeciesId.CURSOLA]);
|
||||||
const cursola = game.scene.getPlayerPokemon();
|
const cursola = game.scene.getPlayerPokemon();
|
||||||
|
|
||||||
|
@ -35,8 +35,7 @@ describe("Abilities - POWER CONSTRUCT", () => {
|
|||||||
test("check if fainted 50% Power Construct Pokemon switches to base form on arena reset", async () => {
|
test("check if fainted 50% Power Construct Pokemon switches to base form on arena reset", async () => {
|
||||||
const baseForm = 2,
|
const baseForm = 2,
|
||||||
completeForm = 4;
|
completeForm = 4;
|
||||||
game.override.startingWave(4);
|
game.override.startingWave(4).starterForms({
|
||||||
game.override.starterForms({
|
|
||||||
[SpeciesId.ZYGARDE]: completeForm,
|
[SpeciesId.ZYGARDE]: completeForm,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -62,8 +61,7 @@ describe("Abilities - POWER CONSTRUCT", () => {
|
|||||||
test("check if fainted 10% Power Construct Pokemon switches to base form on arena reset", async () => {
|
test("check if fainted 10% Power Construct Pokemon switches to base form on arena reset", async () => {
|
||||||
const baseForm = 3,
|
const baseForm = 3,
|
||||||
completeForm = 5;
|
completeForm = 5;
|
||||||
game.override.startingWave(4);
|
game.override.startingWave(4).starterForms({
|
||||||
game.override.starterForms({
|
|
||||||
[SpeciesId.ZYGARDE]: completeForm,
|
[SpeciesId.ZYGARDE]: completeForm,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -26,11 +26,12 @@ describe("Abilities - Power Spot", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("double");
|
game.override
|
||||||
game.override.moveset([MoveId.TACKLE, MoveId.BREAKING_SWIPE, MoveId.SPLASH, MoveId.DAZZLING_GLEAM]);
|
.battleStyle("double")
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
.moveset([MoveId.TACKLE, MoveId.BREAKING_SWIPE, MoveId.SPLASH, MoveId.DAZZLING_GLEAM])
|
||||||
game.override.enemySpecies(SpeciesId.SHUCKLE);
|
.enemyMoveset(MoveId.SPLASH)
|
||||||
game.override.enemyAbility(AbilityId.BALL_FETCH);
|
.enemySpecies(SpeciesId.SHUCKLE)
|
||||||
|
.enemyAbility(AbilityId.BALL_FETCH);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("raises the power of allies' special moves by 30%", async () => {
|
it("raises the power of allies' special moves by 30%", async () => {
|
||||||
|
@ -108,8 +108,7 @@ describe("Abilities - Protean", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("ability applies correctly even if the type has changed by another ability", async () => {
|
test("ability applies correctly even if the type has changed by another ability", async () => {
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
game.override.moveset([MoveId.TACKLE]).passiveAbility(AbilityId.REFRIGERATE);
|
||||||
game.override.passiveAbility(AbilityId.REFRIGERATE);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -156,8 +155,7 @@ describe("Abilities - Protean", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("ability applies correctly even if the pokemon's move misses", async () => {
|
test("ability applies correctly even if the pokemon's move misses", async () => {
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
game.override.moveset([MoveId.TACKLE]).enemyMoveset(MoveId.SPLASH);
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -188,8 +186,7 @@ describe("Abilities - Protean", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("ability applies correctly even if the pokemon's move fails because of type immunity", async () => {
|
test("ability applies correctly even if the pokemon's move fails because of type immunity", async () => {
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
game.override.moveset([MoveId.TACKLE]).enemySpecies(SpeciesId.GASTLY);
|
||||||
game.override.enemySpecies(SpeciesId.GASTLY);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
@ -262,8 +259,7 @@ describe("Abilities - Protean", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("ability applies correctly even if the pokemon's Trick-or-Treat fails", async () => {
|
test("ability applies correctly even if the pokemon's Trick-or-Treat fails", async () => {
|
||||||
game.override.moveset([MoveId.TRICK_OR_TREAT]);
|
game.override.moveset([MoveId.TRICK_OR_TREAT]).enemySpecies(SpeciesId.GASTLY);
|
||||||
game.override.enemySpecies(SpeciesId.GASTLY);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
|
|
||||||
|
@ -23,16 +23,15 @@ describe("Abilities - Quick Draw", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
|
.battleStyle("single")
|
||||||
game.override.starterSpecies(SpeciesId.MAGIKARP);
|
.starterSpecies(SpeciesId.MAGIKARP)
|
||||||
game.override.ability(AbilityId.QUICK_DRAW);
|
.ability(AbilityId.QUICK_DRAW)
|
||||||
game.override.moveset([MoveId.TACKLE, MoveId.TAIL_WHIP]);
|
.moveset([MoveId.TACKLE, MoveId.TAIL_WHIP])
|
||||||
|
.enemyLevel(100)
|
||||||
game.override.enemyLevel(100);
|
.enemySpecies(SpeciesId.MAGIKARP)
|
||||||
game.override.enemySpecies(SpeciesId.MAGIKARP);
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
game.override.enemyAbility(AbilityId.BALL_FETCH);
|
.enemyMoveset([MoveId.TACKLE]);
|
||||||
game.override.enemyMoveset([MoveId.TACKLE]);
|
|
||||||
|
|
||||||
vi.spyOn(
|
vi.spyOn(
|
||||||
allAbilities[AbilityId.QUICK_DRAW].getAttrs("BypassSpeedChanceAbAttr")[0],
|
allAbilities[AbilityId.QUICK_DRAW].getAttrs("BypassSpeedChanceAbAttr")[0],
|
||||||
@ -55,8 +54,8 @@ describe("Abilities - Quick Draw", () => {
|
|||||||
|
|
||||||
expect(pokemon.isFainted()).toBe(false);
|
expect(pokemon.isFainted()).toBe(false);
|
||||||
expect(enemy.isFainted()).toBe(true);
|
expect(enemy.isFainted()).toBe(true);
|
||||||
expect(pokemon.waveData.abilitiesApplied).contain(AbilityId.QUICK_DRAW);
|
expect(pokemon.waveData.abilitiesApplied).toContain(AbilityId.QUICK_DRAW);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
test(
|
test(
|
||||||
"does not triggered by non damage moves",
|
"does not triggered by non damage moves",
|
||||||
@ -97,6 +96,6 @@ describe("Abilities - Quick Draw", () => {
|
|||||||
|
|
||||||
expect(pokemon.isFainted()).toBe(true);
|
expect(pokemon.isFainted()).toBe(true);
|
||||||
expect(enemy.isFainted()).toBe(false);
|
expect(enemy.isFainted()).toBe(false);
|
||||||
expect(pokemon.waveData.abilitiesApplied).contain(AbilityId.QUICK_DRAW);
|
expect(pokemon.waveData.abilitiesApplied).toContain(AbilityId.QUICK_DRAW);
|
||||||
}, 20000);
|
});
|
||||||
});
|
});
|
||||||
|
@ -22,15 +22,14 @@ describe("Abilities - Sand Spit", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.disableCrits();
|
.battleStyle("single")
|
||||||
|
.disableCrits()
|
||||||
game.override.enemySpecies(SpeciesId.MAGIKARP);
|
.enemySpecies(SpeciesId.MAGIKARP)
|
||||||
game.override.enemyAbility(AbilityId.BALL_FETCH);
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
|
.starterSpecies(SpeciesId.SILICOBRA)
|
||||||
game.override.starterSpecies(SpeciesId.SILICOBRA);
|
.ability(AbilityId.SAND_SPIT)
|
||||||
game.override.ability(AbilityId.SAND_SPIT);
|
.moveset([MoveId.SPLASH, MoveId.COIL]);
|
||||||
game.override.moveset([MoveId.SPLASH, MoveId.COIL]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should trigger when hit with damaging move", async () => {
|
it("should trigger when hit with damaging move", async () => {
|
||||||
@ -41,7 +40,7 @@ describe("Abilities - Sand Spit", () => {
|
|||||||
await game.toNextTurn();
|
await game.toNextTurn();
|
||||||
|
|
||||||
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SANDSTORM);
|
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.SANDSTORM);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("should trigger even when fainting", async () => {
|
it("should trigger even when fainting", async () => {
|
||||||
game.override.enemyMoveset([MoveId.TACKLE]).enemyLevel(100).startingLevel(1);
|
game.override.enemyMoveset([MoveId.TACKLE]).enemyLevel(100).startingLevel(1);
|
||||||
@ -62,5 +61,5 @@ describe("Abilities - Sand Spit", () => {
|
|||||||
await game.toNextTurn();
|
await game.toNextTurn();
|
||||||
|
|
||||||
expect(game.scene.arena.weather?.weatherType).not.toBe(WeatherType.SANDSTORM);
|
expect(game.scene.arena.weather?.weatherType).not.toBe(WeatherType.SANDSTORM);
|
||||||
}, 20000);
|
});
|
||||||
});
|
});
|
||||||
|
@ -31,8 +31,7 @@ describe("Abilities - SCHOOLING", () => {
|
|||||||
test("check if fainted pokemon switches to base form on arena reset", async () => {
|
test("check if fainted pokemon switches to base form on arena reset", async () => {
|
||||||
const soloForm = 0,
|
const soloForm = 0,
|
||||||
schoolForm = 1;
|
schoolForm = 1;
|
||||||
game.override.startingWave(4);
|
game.override.startingWave(4).starterForms({
|
||||||
game.override.starterForms({
|
|
||||||
[SpeciesId.WISHIWASHI]: schoolForm,
|
[SpeciesId.WISHIWASHI]: schoolForm,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@ describe("Abilities - Screen Cleaner", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override.battleStyle("single").ability(AbilityId.SCREEN_CLEANER).enemySpecies(SpeciesId.SHUCKLE);
|
||||||
game.override.ability(AbilityId.SCREEN_CLEANER);
|
|
||||||
game.override.enemySpecies(SpeciesId.SHUCKLE);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("removes Aurora Veil", async () => {
|
it("removes Aurora Veil", async () => {
|
||||||
|
@ -22,15 +22,14 @@ describe("Abilities - Seed Sower", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.disableCrits();
|
.battleStyle("single")
|
||||||
|
.disableCrits()
|
||||||
game.override.enemySpecies(SpeciesId.MAGIKARP);
|
.enemySpecies(SpeciesId.MAGIKARP)
|
||||||
game.override.enemyAbility(AbilityId.BALL_FETCH);
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
|
.starterSpecies(SpeciesId.ARBOLIVA)
|
||||||
game.override.starterSpecies(SpeciesId.ARBOLIVA);
|
.ability(AbilityId.SEED_SOWER)
|
||||||
game.override.ability(AbilityId.SEED_SOWER);
|
.moveset([MoveId.SPLASH]);
|
||||||
game.override.moveset([MoveId.SPLASH]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should trigger when hit with damaging move", async () => {
|
it("should trigger when hit with damaging move", async () => {
|
||||||
|
@ -69,7 +69,7 @@ describe("Abilities - Sheer Force", () => {
|
|||||||
await game.phaseInterceptor.to("BerryPhase", false);
|
await game.phaseInterceptor.to("BerryPhase", false);
|
||||||
|
|
||||||
expect(bindMove.calculateBattlePower).toHaveLastReturnedWith(bindMove.power);
|
expect(bindMove.calculateBattlePower).toHaveLastReturnedWith(bindMove.power);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("Sheer Force does not boost the base damage of moves with no secondary effect", async () => {
|
it("Sheer Force does not boost the base damage of moves with no secondary effect", async () => {
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
game.override.moveset([MoveId.TACKLE]);
|
||||||
|
@ -26,12 +26,13 @@ describe("Abilities - Shield Dust", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.enemySpecies(SpeciesId.ONIX);
|
.battleStyle("single")
|
||||||
game.override.enemyAbility(AbilityId.SHIELD_DUST);
|
.enemySpecies(SpeciesId.ONIX)
|
||||||
game.override.startingLevel(100);
|
.enemyAbility(AbilityId.SHIELD_DUST)
|
||||||
game.override.moveset(MoveId.AIR_SLASH);
|
.startingLevel(100)
|
||||||
game.override.enemyMoveset(MoveId.TACKLE);
|
.moveset(MoveId.AIR_SLASH)
|
||||||
|
.enemyMoveset(MoveId.TACKLE);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Shield Dust", async () => {
|
it("Shield Dust", async () => {
|
||||||
|
@ -26,17 +26,17 @@ describe("Abilities - SHIELDS DOWN", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
const moveToUse = MoveId.SPLASH;
|
const moveToUse = MoveId.SPLASH;
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.ability(AbilityId.SHIELDS_DOWN);
|
.battleStyle("single")
|
||||||
game.override.moveset([moveToUse]);
|
.ability(AbilityId.SHIELDS_DOWN)
|
||||||
game.override.enemyMoveset([MoveId.TACKLE]);
|
.moveset([moveToUse])
|
||||||
|
.enemyMoveset([MoveId.TACKLE]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("check if fainted pokemon switched to base form on arena reset", async () => {
|
test("check if fainted pokemon switched to base form on arena reset", async () => {
|
||||||
const meteorForm = 0,
|
const meteorForm = 0,
|
||||||
coreForm = 7;
|
coreForm = 7;
|
||||||
game.override.startingWave(4);
|
game.override.startingWave(4).starterForms({
|
||||||
game.override.starterForms({
|
|
||||||
[SpeciesId.MINIOR]: coreForm,
|
[SpeciesId.MINIOR]: coreForm,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -70,8 +70,7 @@ describe("Abilities - SHIELDS DOWN", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("should still ignore non-volatile status moves used by a pokemon with mold breaker", async () => {
|
test("should still ignore non-volatile status moves used by a pokemon with mold breaker", async () => {
|
||||||
game.override.enemyAbility(AbilityId.MOLD_BREAKER);
|
game.override.enemyAbility(AbilityId.MOLD_BREAKER).enemyMoveset([MoveId.SPORE]);
|
||||||
game.override.enemyMoveset([MoveId.SPORE]);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MINIOR]);
|
await game.classicMode.startBattle([SpeciesId.MINIOR]);
|
||||||
|
|
||||||
@ -94,8 +93,7 @@ describe("Abilities - SHIELDS DOWN", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("should ignore status moves even through mold breaker", async () => {
|
test("should ignore status moves even through mold breaker", async () => {
|
||||||
game.override.enemyMoveset([MoveId.SPORE]);
|
game.override.enemyMoveset([MoveId.SPORE]).enemyAbility(AbilityId.MOLD_BREAKER);
|
||||||
game.override.enemyAbility(AbilityId.MOLD_BREAKER);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MINIOR]);
|
await game.classicMode.startBattle([SpeciesId.MINIOR]);
|
||||||
|
|
||||||
@ -108,8 +106,9 @@ describe("Abilities - SHIELDS DOWN", () => {
|
|||||||
|
|
||||||
// toxic spikes currently does not poison flying types when gravity is in effect
|
// toxic spikes currently does not poison flying types when gravity is in effect
|
||||||
test.todo("should become poisoned by toxic spikes when grounded", async () => {
|
test.todo("should become poisoned by toxic spikes when grounded", async () => {
|
||||||
game.override.enemyMoveset([MoveId.GRAVITY, MoveId.TOXIC_SPIKES, MoveId.SPLASH]);
|
game.override
|
||||||
game.override.moveset([MoveId.GRAVITY, MoveId.SPLASH]);
|
.enemyMoveset([MoveId.GRAVITY, MoveId.TOXIC_SPIKES, MoveId.SPLASH])
|
||||||
|
.moveset([MoveId.GRAVITY, MoveId.SPLASH]);
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MINIOR]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MINIOR]);
|
||||||
|
|
||||||
@ -155,9 +154,7 @@ describe("Abilities - SHIELDS DOWN", () => {
|
|||||||
|
|
||||||
// the `NoTransformAbilityAbAttr` attribute is not checked anywhere, so this test cannot pass.
|
// the `NoTransformAbilityAbAttr` attribute is not checked anywhere, so this test cannot pass.
|
||||||
test.todo("ditto should not be immune to status after transforming", async () => {
|
test.todo("ditto should not be immune to status after transforming", async () => {
|
||||||
game.override.enemySpecies(SpeciesId.DITTO);
|
game.override.enemySpecies(SpeciesId.DITTO).enemyAbility(AbilityId.IMPOSTER).moveset([MoveId.SPLASH, MoveId.SPORE]);
|
||||||
game.override.enemyAbility(AbilityId.IMPOSTER);
|
|
||||||
game.override.moveset([MoveId.SPLASH, MoveId.SPORE]);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.MINIOR]);
|
await game.classicMode.startBattle([SpeciesId.MINIOR]);
|
||||||
|
|
||||||
@ -169,11 +166,12 @@ describe("Abilities - SHIELDS DOWN", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("should not prevent minior from receiving the fainted status effect in trainer battles", async () => {
|
test("should not prevent minior from receiving the fainted status effect in trainer battles", async () => {
|
||||||
game.override.enemyMoveset([MoveId.TACKLE]);
|
game.override
|
||||||
game.override.moveset([MoveId.THUNDERBOLT]);
|
.enemyMoveset([MoveId.TACKLE])
|
||||||
game.override.startingLevel(100);
|
.moveset([MoveId.THUNDERBOLT])
|
||||||
game.override.startingWave(5);
|
.startingLevel(100)
|
||||||
game.override.enemySpecies(SpeciesId.MINIOR);
|
.startingWave(5)
|
||||||
|
.enemySpecies(SpeciesId.MINIOR);
|
||||||
await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
|
await game.classicMode.startBattle([SpeciesId.REGIELEKI]);
|
||||||
const minior = game.scene.getEnemyPokemon()!;
|
const minior = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
|
@ -36,5 +36,5 @@ describe("Abilities - Simple", () => {
|
|||||||
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
const enemyPokemon = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-2);
|
expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-2);
|
||||||
}, 20000);
|
});
|
||||||
});
|
});
|
||||||
|
@ -53,7 +53,7 @@ describe("Abilities - Stall", () => {
|
|||||||
// The opponent Pokemon (with Stall) goes last despite having higher speed than the player Pokemon.
|
// The opponent Pokemon (with Stall) goes last despite having higher speed than the player Pokemon.
|
||||||
expect(speedOrder).toEqual([enemyIndex, playerIndex]);
|
expect(speedOrder).toEqual([enemyIndex, playerIndex]);
|
||||||
expect(commandOrder).toEqual([playerIndex, enemyIndex]);
|
expect(commandOrder).toEqual([playerIndex, enemyIndex]);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("Pokemon with Stall will go first if a move that is in a higher priority bracket than the opponent's move is used", async () => {
|
it("Pokemon with Stall will go first if a move that is in a higher priority bracket than the opponent's move is used", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.SHUCKLE]);
|
await game.classicMode.startBattle([SpeciesId.SHUCKLE]);
|
||||||
@ -71,7 +71,7 @@ describe("Abilities - Stall", () => {
|
|||||||
// The player Pokemon goes second because its move is in a lower priority bracket.
|
// The player Pokemon goes second because its move is in a lower priority bracket.
|
||||||
expect(speedOrder).toEqual([enemyIndex, playerIndex]);
|
expect(speedOrder).toEqual([enemyIndex, playerIndex]);
|
||||||
expect(commandOrder).toEqual([enemyIndex, playerIndex]);
|
expect(commandOrder).toEqual([enemyIndex, playerIndex]);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("If both Pokemon have stall and use the same move, speed is used to determine who goes first.", async () => {
|
it("If both Pokemon have stall and use the same move, speed is used to determine who goes first.", async () => {
|
||||||
game.override.ability(AbilityId.STALL);
|
game.override.ability(AbilityId.STALL);
|
||||||
@ -91,5 +91,5 @@ describe("Abilities - Stall", () => {
|
|||||||
// The player Pokemon (with Stall) goes second because its speed is lower.
|
// The player Pokemon (with Stall) goes second because its speed is lower.
|
||||||
expect(speedOrder).toEqual([enemyIndex, playerIndex]);
|
expect(speedOrder).toEqual([enemyIndex, playerIndex]);
|
||||||
expect(commandOrder).toEqual([enemyIndex, playerIndex]);
|
expect(commandOrder).toEqual([enemyIndex, playerIndex]);
|
||||||
}, 20000);
|
});
|
||||||
});
|
});
|
||||||
|
@ -28,11 +28,12 @@ describe("Abilities - Steely Spirit", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ironHeadPower = allMoves[moveToCheck].power;
|
ironHeadPower = allMoves[moveToCheck].power;
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("double");
|
game.override
|
||||||
game.override.enemySpecies(SpeciesId.SHUCKLE);
|
.battleStyle("double")
|
||||||
game.override.enemyAbility(AbilityId.BALL_FETCH);
|
.enemySpecies(SpeciesId.SHUCKLE)
|
||||||
game.override.moveset([MoveId.IRON_HEAD, MoveId.SPLASH]);
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
.moveset([MoveId.IRON_HEAD, MoveId.SPLASH])
|
||||||
|
.enemyMoveset(MoveId.SPLASH);
|
||||||
vi.spyOn(allMoves[moveToCheck], "calculateBattlePower");
|
vi.spyOn(allMoves[moveToCheck], "calculateBattlePower");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -24,15 +24,14 @@ describe("Abilities - Sturdy", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
|
.battleStyle("single")
|
||||||
game.override.starterSpecies(SpeciesId.LUCARIO);
|
.starterSpecies(SpeciesId.LUCARIO)
|
||||||
game.override.startingLevel(100);
|
.startingLevel(100)
|
||||||
game.override.moveset([MoveId.CLOSE_COMBAT, MoveId.FISSURE]);
|
.moveset([MoveId.CLOSE_COMBAT, MoveId.FISSURE])
|
||||||
|
.enemySpecies(SpeciesId.ARON)
|
||||||
game.override.enemySpecies(SpeciesId.ARON);
|
.enemyLevel(5)
|
||||||
game.override.enemyLevel(5);
|
.enemyAbility(AbilityId.STURDY);
|
||||||
game.override.enemyAbility(AbilityId.STURDY);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Sturdy activates when user is at full HP", async () => {
|
test("Sturdy activates when user is at full HP", async () => {
|
||||||
|
@ -30,13 +30,13 @@ describe("Abilities - Super Luck", () => {
|
|||||||
.enemyMoveset(MoveId.SPLASH);
|
.enemyMoveset(MoveId.SPLASH);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should increase the crit stage of a user by 1", async () => {
|
it("should increase the user's crit stage by 1", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
const enemy = game.scene.getEnemyPokemon()!;
|
const enemy = game.scene.getEnemyPokemon()!;
|
||||||
const fn = vi.spyOn(enemy, "getCritStage");
|
const critSpy = vi.spyOn(enemy, "getCritStage"); // crit stage is called on enemy
|
||||||
|
|
||||||
game.move.select(MoveId.TACKLE);
|
game.move.select(MoveId.TACKLE);
|
||||||
await game.phaseInterceptor.to("BerryPhase");
|
await game.phaseInterceptor.to("BerryPhase");
|
||||||
expect(fn).toHaveReturnedWith(1);
|
expect(critSpy).toHaveReturnedWith(1);
|
||||||
fn.mockRestore();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -69,10 +69,7 @@ describe("Abilities - Sweet Veil", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("prevents the user and its allies already drowsy due to Yawn from falling asleep.", async () => {
|
it("prevents the user and its allies already drowsy due to Yawn from falling asleep.", async () => {
|
||||||
game.override.enemySpecies(SpeciesId.PIKACHU);
|
game.override.enemySpecies(SpeciesId.PIKACHU).enemyLevel(5).startingLevel(5).enemyMoveset(MoveId.SPLASH);
|
||||||
game.override.enemyLevel(5);
|
|
||||||
game.override.startingLevel(5);
|
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.SHUCKLE, SpeciesId.SHUCKLE, SpeciesId.SWIRLIX]);
|
await game.classicMode.startBattle([SpeciesId.SHUCKLE, SpeciesId.SHUCKLE, SpeciesId.SWIRLIX]);
|
||||||
|
|
||||||
|
@ -93,8 +93,6 @@ describe("Abilities - Tera Shell", () => {
|
|||||||
await game.phaseInterceptor.to("BerryPhase", false);
|
await game.phaseInterceptor.to("BerryPhase", false);
|
||||||
expect(spy).toHaveLastReturnedWith(1);
|
expect(spy).toHaveLastReturnedWith(1);
|
||||||
expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp() - 40);
|
expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp() - 40);
|
||||||
|
|
||||||
spy.mockRestore();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should change the effectiveness of all strikes of a multi-strike move", async () => {
|
it("should change the effectiveness of all strikes of a multi-strike move", async () => {
|
||||||
@ -114,6 +112,5 @@ describe("Abilities - Tera Shell", () => {
|
|||||||
expect(spy).toHaveLastReturnedWith(0.5);
|
expect(spy).toHaveLastReturnedWith(0.5);
|
||||||
}
|
}
|
||||||
expect(spy).toHaveReturnedTimes(2);
|
expect(spy).toHaveReturnedTimes(2);
|
||||||
spy.mockRestore();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -51,8 +51,7 @@ describe("Abilities - Unseen Fist", () => {
|
|||||||
await testUnseenFistHitResult(game, MoveId.BULLDOZE, MoveId.WIDE_GUARD, false));
|
await testUnseenFistHitResult(game, MoveId.BULLDOZE, MoveId.WIDE_GUARD, false));
|
||||||
|
|
||||||
it("should cause a contact move to ignore Protect, but not Substitute", async () => {
|
it("should cause a contact move to ignore Protect, but not Substitute", async () => {
|
||||||
game.override.enemyLevel(1);
|
game.override.enemyLevel(1).moveset([MoveId.TACKLE]);
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle();
|
||||||
|
|
||||||
|
@ -3,11 +3,11 @@ import { TurnEndPhase } from "#app/phases/turn-end-phase";
|
|||||||
import { AbilityId } from "#enums/ability-id";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
|
||||||
import GameManager from "#test/testUtils/gameManager";
|
import GameManager from "#test/testUtils/gameManager";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
import { BattlerIndex } from "#enums/battler-index";
|
import { BattlerIndex } from "#enums/battler-index";
|
||||||
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
|
||||||
// See also: TypeImmunityAbAttr
|
// See also: TypeImmunityAbAttr
|
||||||
describe("Abilities - Volt Absorb", () => {
|
describe("Abilities - Volt Absorb", () => {
|
||||||
@ -26,19 +26,19 @@ describe("Abilities - Volt Absorb", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override.battleStyle("single").disableCrits();
|
||||||
game.override.disableCrits();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not activate when CHARGE is used", async () => {
|
it("does not activate when CHARGE is used", async () => {
|
||||||
const moveToUse = MoveId.CHARGE;
|
const moveToUse = MoveId.CHARGE;
|
||||||
const ability = AbilityId.VOLT_ABSORB;
|
const ability = AbilityId.VOLT_ABSORB;
|
||||||
|
|
||||||
game.override.moveset([moveToUse]);
|
game.override
|
||||||
game.override.ability(ability);
|
.moveset([moveToUse])
|
||||||
game.override.enemyMoveset([MoveId.SPLASH, MoveId.NONE, MoveId.NONE, MoveId.NONE]);
|
.ability(ability)
|
||||||
game.override.enemySpecies(SpeciesId.DUSKULL);
|
.enemyMoveset([MoveId.SPLASH])
|
||||||
game.override.enemyAbility(AbilityId.BALL_FETCH);
|
.enemySpecies(SpeciesId.DUSKULL)
|
||||||
|
.enemyAbility(AbilityId.BALL_FETCH);
|
||||||
|
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle();
|
||||||
|
|
||||||
@ -54,10 +54,11 @@ describe("Abilities - Volt Absorb", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should activate regardless of accuracy checks", async () => {
|
it("should activate regardless of accuracy checks", async () => {
|
||||||
game.override.moveset(MoveId.THUNDERBOLT);
|
game.override
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
.moveset(MoveId.THUNDERBOLT)
|
||||||
game.override.enemySpecies(SpeciesId.MAGIKARP);
|
.enemyMoveset(MoveId.SPLASH)
|
||||||
game.override.enemyAbility(AbilityId.VOLT_ABSORB);
|
.enemySpecies(SpeciesId.MAGIKARP)
|
||||||
|
.enemyAbility(AbilityId.VOLT_ABSORB);
|
||||||
|
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle();
|
||||||
|
|
||||||
@ -74,10 +75,11 @@ describe("Abilities - Volt Absorb", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("regardless of accuracy should not trigger on pokemon in semi invulnerable state", async () => {
|
it("regardless of accuracy should not trigger on pokemon in semi invulnerable state", async () => {
|
||||||
game.override.moveset(MoveId.THUNDERBOLT);
|
game.override
|
||||||
game.override.enemyMoveset(MoveId.DIVE);
|
.moveset(MoveId.THUNDERBOLT)
|
||||||
game.override.enemySpecies(SpeciesId.MAGIKARP);
|
.enemyMoveset(MoveId.DIVE)
|
||||||
game.override.enemyAbility(AbilityId.VOLT_ABSORB);
|
.enemySpecies(SpeciesId.MAGIKARP)
|
||||||
|
.enemyAbility(AbilityId.VOLT_ABSORB);
|
||||||
|
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle();
|
||||||
|
|
||||||
|
@ -23,14 +23,15 @@ describe("Abilities - Wind Power", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.enemySpecies(SpeciesId.SHIFTRY);
|
.battleStyle("single")
|
||||||
game.override.enemyAbility(AbilityId.WIND_POWER);
|
.enemySpecies(SpeciesId.SHIFTRY)
|
||||||
game.override.moveset([MoveId.TAILWIND, MoveId.SPLASH, MoveId.PETAL_BLIZZARD, MoveId.SANDSTORM]);
|
.enemyAbility(AbilityId.WIND_POWER)
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
.moveset([MoveId.TAILWIND, MoveId.SPLASH, MoveId.PETAL_BLIZZARD, MoveId.SANDSTORM])
|
||||||
|
.enemyMoveset(MoveId.SPLASH);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("it becomes charged when hit by wind moves", async () => {
|
it("becomes charged when hit by wind moves", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||||
const shiftry = game.scene.getEnemyPokemon()!;
|
const shiftry = game.scene.getEnemyPokemon()!;
|
||||||
|
|
||||||
@ -42,9 +43,8 @@ describe("Abilities - Wind Power", () => {
|
|||||||
expect(shiftry.getTag(BattlerTagType.CHARGED)).toBeDefined();
|
expect(shiftry.getTag(BattlerTagType.CHARGED)).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("it becomes charged when Tailwind takes effect on its side", async () => {
|
it("becomes charged when Tailwind takes effect on its side", async () => {
|
||||||
game.override.ability(AbilityId.WIND_POWER);
|
game.override.ability(AbilityId.WIND_POWER).enemySpecies(SpeciesId.MAGIKARP);
|
||||||
game.override.enemySpecies(SpeciesId.MAGIKARP);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.SHIFTRY]);
|
await game.classicMode.startBattle([SpeciesId.SHIFTRY]);
|
||||||
const shiftry = game.scene.getPlayerPokemon()!;
|
const shiftry = game.scene.getPlayerPokemon()!;
|
||||||
@ -58,8 +58,7 @@ describe("Abilities - Wind Power", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("does not become charged when Tailwind takes effect on opposing side", async () => {
|
it("does not become charged when Tailwind takes effect on opposing side", async () => {
|
||||||
game.override.enemySpecies(SpeciesId.MAGIKARP);
|
game.override.enemySpecies(SpeciesId.MAGIKARP).ability(AbilityId.WIND_POWER);
|
||||||
game.override.ability(AbilityId.WIND_POWER);
|
|
||||||
|
|
||||||
await game.classicMode.startBattle([SpeciesId.SHIFTRY]);
|
await game.classicMode.startBattle([SpeciesId.SHIFTRY]);
|
||||||
const magikarp = game.scene.getEnemyPokemon()!;
|
const magikarp = game.scene.getEnemyPokemon()!;
|
||||||
|
@ -23,12 +23,13 @@ describe("Abilities - Wonder Skin", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.moveset([MoveId.TACKLE, MoveId.CHARM]);
|
.battleStyle("single")
|
||||||
game.override.ability(AbilityId.BALL_FETCH);
|
.moveset([MoveId.TACKLE, MoveId.CHARM])
|
||||||
game.override.enemySpecies(SpeciesId.SHUCKLE);
|
.ability(AbilityId.BALL_FETCH)
|
||||||
game.override.enemyAbility(AbilityId.WONDER_SKIN);
|
.enemySpecies(SpeciesId.SHUCKLE)
|
||||||
game.override.enemyMoveset(MoveId.SPLASH);
|
.enemyAbility(AbilityId.WONDER_SKIN)
|
||||||
|
.enemyMoveset(MoveId.SPLASH);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("lowers accuracy of status moves to 50%", async () => {
|
it("lowers accuracy of status moves to 50%", async () => {
|
||||||
|
@ -85,8 +85,7 @@ describe("Abilities - ZEN MODE", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should switch to base form on arena reset", async () => {
|
it("should switch to base form on arena reset", async () => {
|
||||||
game.override.startingWave(4);
|
game.override.startingWave(4).starterForms({
|
||||||
game.override.starterForms({
|
|
||||||
[SpeciesId.DARMANITAN]: zenForm,
|
[SpeciesId.DARMANITAN]: zenForm,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -34,8 +34,7 @@ describe("Abilities - ZERO TO HERO", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should swap to base form on arena reset", async () => {
|
it("should swap to base form on arena reset", async () => {
|
||||||
game.override.startingWave(4);
|
game.override.startingWave(4).starterForms({
|
||||||
game.override.starterForms({
|
|
||||||
[SpeciesId.PALAFIN]: heroForm,
|
[SpeciesId.PALAFIN]: heroForm,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -130,12 +130,6 @@ describe("RibbonAchv", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.moveset([]);
|
|
||||||
game.override.startingLevel(0);
|
|
||||||
game.override.starterSpecies(0);
|
|
||||||
game.override.enemyMoveset([]);
|
|
||||||
game.override.enemySpecies(0);
|
|
||||||
game.override.startingWave(0);
|
|
||||||
scene = game.scene;
|
scene = game.scene;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -24,12 +24,14 @@ describe("Weather - Fog", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.weather(WeatherType.FOG).battleStyle("single");
|
game.override
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
.weather(WeatherType.FOG)
|
||||||
game.override.ability(AbilityId.BALL_FETCH);
|
.battleStyle("single")
|
||||||
game.override.enemyAbility(AbilityId.BALL_FETCH);
|
.moveset([MoveId.TACKLE])
|
||||||
game.override.enemySpecies(SpeciesId.MAGIKARP);
|
.ability(AbilityId.BALL_FETCH)
|
||||||
game.override.enemyMoveset([MoveId.SPLASH]);
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
|
.enemySpecies(SpeciesId.MAGIKARP)
|
||||||
|
.enemyMoveset([MoveId.SPLASH]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("move accuracy is multiplied by 90%", async () => {
|
it("move accuracy is multiplied by 90%", async () => {
|
||||||
|
@ -24,11 +24,12 @@ describe("Weather - Strong Winds", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.startingLevel(10);
|
.battleStyle("single")
|
||||||
game.override.enemySpecies(SpeciesId.TAILLOW);
|
.startingLevel(10)
|
||||||
game.override.enemyAbility(AbilityId.DELTA_STREAM);
|
.enemySpecies(SpeciesId.TAILLOW)
|
||||||
game.override.moveset([MoveId.THUNDERBOLT, MoveId.ICE_BEAM, MoveId.ROCK_SLIDE]);
|
.enemyAbility(AbilityId.DELTA_STREAM)
|
||||||
|
.moveset([MoveId.THUNDERBOLT, MoveId.ICE_BEAM, MoveId.ROCK_SLIDE]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("electric type move is not very effective on Rayquaza", async () => {
|
it("electric type move is not very effective on Rayquaza", async () => {
|
||||||
|
@ -24,11 +24,12 @@ describe("Battle order", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.enemySpecies(SpeciesId.MEWTWO);
|
.battleStyle("single")
|
||||||
game.override.enemyAbility(AbilityId.INSOMNIA);
|
.enemySpecies(SpeciesId.MEWTWO)
|
||||||
game.override.ability(AbilityId.INSOMNIA);
|
.enemyAbility(AbilityId.INSOMNIA)
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
.ability(AbilityId.INSOMNIA)
|
||||||
|
.moveset([MoveId.TACKLE]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("opponent faster than player 50 vs 150", async () => {
|
it("opponent faster than player 50 vs 150", async () => {
|
||||||
@ -48,7 +49,7 @@ describe("Battle order", () => {
|
|||||||
const order = phase.getCommandOrder();
|
const order = phase.getCommandOrder();
|
||||||
expect(order[0]).toBe(enemyPokemonIndex);
|
expect(order[0]).toBe(enemyPokemonIndex);
|
||||||
expect(order[1]).toBe(playerPokemonIndex);
|
expect(order[1]).toBe(playerPokemonIndex);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("Player faster than opponent 150 vs 50", async () => {
|
it("Player faster than opponent 150 vs 50", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR]);
|
||||||
@ -67,7 +68,7 @@ describe("Battle order", () => {
|
|||||||
const order = phase.getCommandOrder();
|
const order = phase.getCommandOrder();
|
||||||
expect(order[0]).toBe(playerPokemonIndex);
|
expect(order[0]).toBe(playerPokemonIndex);
|
||||||
expect(order[1]).toBe(enemyPokemonIndex);
|
expect(order[1]).toBe(enemyPokemonIndex);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("double - both opponents faster than player 50/50 vs 150/150", async () => {
|
it("double - both opponents faster than player 50/50 vs 150/150", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double");
|
||||||
@ -91,7 +92,7 @@ describe("Battle order", () => {
|
|||||||
expect(order.slice(0, 2).includes(enemyIndices[1])).toBe(true);
|
expect(order.slice(0, 2).includes(enemyIndices[1])).toBe(true);
|
||||||
expect(order.slice(2, 4).includes(playerIndices[0])).toBe(true);
|
expect(order.slice(2, 4).includes(playerIndices[0])).toBe(true);
|
||||||
expect(order.slice(2, 4).includes(playerIndices[1])).toBe(true);
|
expect(order.slice(2, 4).includes(playerIndices[1])).toBe(true);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("double - speed tie except 1 - 100/100 vs 100/150", async () => {
|
it("double - speed tie except 1 - 100/100 vs 100/150", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double");
|
||||||
@ -111,11 +112,10 @@ describe("Battle order", () => {
|
|||||||
|
|
||||||
const phase = game.scene.phaseManager.getCurrentPhase() as TurnStartPhase;
|
const phase = game.scene.phaseManager.getCurrentPhase() as TurnStartPhase;
|
||||||
const order = phase.getCommandOrder();
|
const order = phase.getCommandOrder();
|
||||||
|
// enemy 2 should be first, followed by some other assortment of the other 3 pokemon
|
||||||
expect(order[0]).toBe(enemyIndices[1]);
|
expect(order[0]).toBe(enemyIndices[1]);
|
||||||
expect(order.slice(1, 4).includes(enemyIndices[0])).toBe(true);
|
expect(order.slice(1, 4)).toEqual(expect.arrayContaining([enemyIndices[0], ...playerIndices]));
|
||||||
expect(order.slice(1, 4).includes(playerIndices[0])).toBe(true);
|
});
|
||||||
expect(order.slice(1, 4).includes(playerIndices[1])).toBe(true);
|
|
||||||
}, 20000);
|
|
||||||
|
|
||||||
it("double - speed tie 100/150 vs 100/150", async () => {
|
it("double - speed tie 100/150 vs 100/150", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double");
|
||||||
@ -136,9 +136,8 @@ describe("Battle order", () => {
|
|||||||
|
|
||||||
const phase = game.scene.phaseManager.getCurrentPhase() as TurnStartPhase;
|
const phase = game.scene.phaseManager.getCurrentPhase() as TurnStartPhase;
|
||||||
const order = phase.getCommandOrder();
|
const order = phase.getCommandOrder();
|
||||||
expect(order.slice(0, 2).includes(playerIndices[1])).toBe(true);
|
// P2/E2 should be randomly first/second, then P1/E1 randomly 3rd/4th
|
||||||
expect(order.slice(0, 2).includes(enemyIndices[1])).toBe(true);
|
expect(order.slice(0, 2)).toStrictEqual(expect.arrayContaining([playerIndices[1], enemyIndices[1]]));
|
||||||
expect(order.slice(2, 4).includes(playerIndices[0])).toBe(true);
|
expect(order.slice(2, 4)).toStrictEqual(expect.arrayContaining([playerIndices[0], enemyIndices[0]]));
|
||||||
expect(order.slice(2, 4).includes(enemyIndices[0])).toBe(true);
|
});
|
||||||
}, 20000);
|
|
||||||
});
|
});
|
||||||
|
@ -10,13 +10,11 @@ import { EnemyCommandPhase } from "#app/phases/enemy-command-phase";
|
|||||||
import { LoginPhase } from "#app/phases/login-phase";
|
import { LoginPhase } from "#app/phases/login-phase";
|
||||||
import { NextEncounterPhase } from "#app/phases/next-encounter-phase";
|
import { NextEncounterPhase } from "#app/phases/next-encounter-phase";
|
||||||
import { SelectGenderPhase } from "#app/phases/select-gender-phase";
|
import { SelectGenderPhase } from "#app/phases/select-gender-phase";
|
||||||
import { SelectModifierPhase } from "#app/phases/select-modifier-phase";
|
|
||||||
import { SelectStarterPhase } from "#app/phases/select-starter-phase";
|
import { SelectStarterPhase } from "#app/phases/select-starter-phase";
|
||||||
import { SummonPhase } from "#app/phases/summon-phase";
|
import { SummonPhase } from "#app/phases/summon-phase";
|
||||||
import { SwitchPhase } from "#app/phases/switch-phase";
|
import { SwitchPhase } from "#app/phases/switch-phase";
|
||||||
import { TitlePhase } from "#app/phases/title-phase";
|
import { TitlePhase } from "#app/phases/title-phase";
|
||||||
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
import { TurnInitPhase } from "#app/phases/turn-init-phase";
|
||||||
import { VictoryPhase } from "#app/phases/victory-phase";
|
|
||||||
import GameManager from "#test/testUtils/gameManager";
|
import GameManager from "#test/testUtils/gameManager";
|
||||||
import { generateStarter } from "#test/testUtils/gameManagerUtils";
|
import { generateStarter } from "#test/testUtils/gameManagerUtils";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
@ -62,7 +60,7 @@ describe("Test Battle Phase", () => {
|
|||||||
|
|
||||||
expect(game.scene.ui?.getMode()).toBe(UiMode.TITLE);
|
expect(game.scene.ui?.getMode()).toBe(UiMode.TITLE);
|
||||||
expect(game.scene.gameData.gender).toBe(PlayerGender.MALE);
|
expect(game.scene.gameData.gender).toBe(PlayerGender.MALE);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("test phase interceptor with prompt with preparation for a future prompt", async () => {
|
it("test phase interceptor with prompt with preparation for a future prompt", async () => {
|
||||||
await game.phaseInterceptor.run(LoginPhase);
|
await game.phaseInterceptor.run(LoginPhase);
|
||||||
@ -83,40 +81,34 @@ describe("Test Battle Phase", () => {
|
|||||||
|
|
||||||
expect(game.scene.ui?.getMode()).toBe(UiMode.TITLE);
|
expect(game.scene.ui?.getMode()).toBe(UiMode.TITLE);
|
||||||
expect(game.scene.gameData.gender).toBe(PlayerGender.MALE);
|
expect(game.scene.gameData.gender).toBe(PlayerGender.MALE);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("newGame one-liner", async () => {
|
it("newGame one-liner", async () => {
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle();
|
||||||
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
||||||
expect(game.scene.phaseManager.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name);
|
expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase");
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("do attack wave 3 - single battle - regular - OHKO", async () => {
|
it("do attack wave 3 - single battle - regular - OHKO", async () => {
|
||||||
game.override.starterSpecies(SpeciesId.MEWTWO);
|
game.override.enemySpecies(SpeciesId.RATTATA).startingLevel(2000).battleStyle("single").startingWave(3);
|
||||||
game.override.enemySpecies(SpeciesId.RATTATA);
|
await game.classicMode.startBattle([SpeciesId.MEWTWO]);
|
||||||
game.override.startingLevel(2000);
|
game.move.use(MoveId.TACKLE);
|
||||||
game.override.startingWave(3).battleStyle("single");
|
await game.phaseInterceptor.to("SelectModifierPhase");
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
});
|
||||||
game.override.enemyAbility(AbilityId.HYDRATION);
|
|
||||||
game.override.enemyMoveset([MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE]);
|
|
||||||
await game.classicMode.startBattle();
|
|
||||||
game.move.select(MoveId.TACKLE);
|
|
||||||
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(SelectModifierPhase, false);
|
|
||||||
}, 20000);
|
|
||||||
|
|
||||||
it("do attack wave 3 - single battle - regular - NO OHKO with opponent using non damage attack", async () => {
|
it("do attack wave 3 - single battle - regular - NO OHKO with opponent using non damage attack", async () => {
|
||||||
game.override.starterSpecies(SpeciesId.MEWTWO);
|
game.override
|
||||||
game.override.enemySpecies(SpeciesId.RATTATA);
|
.enemySpecies(SpeciesId.RATTATA)
|
||||||
game.override.startingLevel(5);
|
.startingLevel(5)
|
||||||
game.override.startingWave(3);
|
.startingWave(3)
|
||||||
game.override.moveset([MoveId.TACKLE]);
|
.moveset([MoveId.TACKLE])
|
||||||
game.override.enemyAbility(AbilityId.HYDRATION);
|
.enemyAbility(AbilityId.HYDRATION)
|
||||||
game.override.enemyMoveset([MoveId.TAIL_WHIP, MoveId.TAIL_WHIP, MoveId.TAIL_WHIP, MoveId.TAIL_WHIP]);
|
.enemyMoveset([MoveId.TAIL_WHIP, MoveId.TAIL_WHIP, MoveId.TAIL_WHIP, MoveId.TAIL_WHIP])
|
||||||
game.override.battleStyle("single");
|
.battleStyle("single");
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle([SpeciesId.MEWTWO]);
|
||||||
game.move.select(MoveId.TACKLE);
|
game.move.select(MoveId.TACKLE);
|
||||||
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase, false);
|
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase, false);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("load 100% data file", async () => {
|
it("load 100% data file", async () => {
|
||||||
await game.importData("./test/testUtils/saves/everything.prsv");
|
await game.importData("./test/testUtils/saves/everything.prsv");
|
||||||
@ -125,14 +117,16 @@ describe("Test Battle Phase", () => {
|
|||||||
return species.caughtAttr !== 0n;
|
return species.caughtAttr !== 0n;
|
||||||
}).length;
|
}).length;
|
||||||
expect(caughtCount).toBe(Object.keys(allSpecies).length);
|
expect(caughtCount).toBe(Object.keys(allSpecies).length);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("start battle with selected team", async () => {
|
it("start battle with selected team", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.CHARIZARD, SpeciesId.CHANSEY, SpeciesId.MEW]);
|
await game.classicMode.startBattle([SpeciesId.CHARIZARD, SpeciesId.CHANSEY, SpeciesId.MEW]);
|
||||||
expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.CHARIZARD);
|
expect(game.scene.getPlayerParty().map(p => p.species.speciesId)).toEqual([
|
||||||
expect(game.scene.getPlayerParty()[1].species.speciesId).toBe(SpeciesId.CHANSEY);
|
SpeciesId.CHARIZARD,
|
||||||
expect(game.scene.getPlayerParty()[2].species.speciesId).toBe(SpeciesId.MEW);
|
SpeciesId.CHANSEY,
|
||||||
}, 20000);
|
SpeciesId.MEW,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it("test remove random battle seed int", async () => {
|
it("test remove random battle seed int", async () => {
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
@ -146,12 +140,12 @@ describe("Test Battle Phase", () => {
|
|||||||
await game.phaseInterceptor.run(LoginPhase).catch(e => {
|
await game.phaseInterceptor.run(LoginPhase).catch(e => {
|
||||||
expect(e).toBe("Wrong phase: this is SelectGenderPhase and not LoginPhase");
|
expect(e).toBe("Wrong phase: this is SelectGenderPhase and not LoginPhase");
|
||||||
});
|
});
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("wrong phase but skip", async () => {
|
it("wrong phase but skip", async () => {
|
||||||
await game.phaseInterceptor.run(LoginPhase);
|
await game.phaseInterceptor.run(LoginPhase);
|
||||||
await game.phaseInterceptor.run(LoginPhase, () => game.isCurrentPhase(SelectGenderPhase));
|
await game.phaseInterceptor.run(LoginPhase, () => game.isCurrentPhase(SelectGenderPhase));
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("good run", async () => {
|
it("good run", async () => {
|
||||||
await game.phaseInterceptor.run(LoginPhase);
|
await game.phaseInterceptor.run(LoginPhase);
|
||||||
@ -166,7 +160,7 @@ describe("Test Battle Phase", () => {
|
|||||||
);
|
);
|
||||||
await game.phaseInterceptor.run(SelectGenderPhase, () => game.isCurrentPhase(TitlePhase));
|
await game.phaseInterceptor.run(SelectGenderPhase, () => game.isCurrentPhase(TitlePhase));
|
||||||
await game.phaseInterceptor.run(TitlePhase);
|
await game.phaseInterceptor.run(TitlePhase);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("good run from select gender to title", async () => {
|
it("good run from select gender to title", async () => {
|
||||||
await game.phaseInterceptor.run(LoginPhase);
|
await game.phaseInterceptor.run(LoginPhase);
|
||||||
@ -180,7 +174,7 @@ describe("Test Battle Phase", () => {
|
|||||||
() => game.isCurrentPhase(TitlePhase),
|
() => game.isCurrentPhase(TitlePhase),
|
||||||
);
|
);
|
||||||
await game.phaseInterceptor.runFrom(SelectGenderPhase).to(TitlePhase);
|
await game.phaseInterceptor.runFrom(SelectGenderPhase).to(TitlePhase);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("good run to SummonPhase phase", async () => {
|
it("good run to SummonPhase phase", async () => {
|
||||||
await game.phaseInterceptor.run(LoginPhase);
|
await game.phaseInterceptor.run(LoginPhase);
|
||||||
@ -201,7 +195,7 @@ describe("Test Battle Phase", () => {
|
|||||||
selectStarterPhase.initBattle(starters);
|
selectStarterPhase.initBattle(starters);
|
||||||
});
|
});
|
||||||
await game.phaseInterceptor.runFrom(SelectGenderPhase).to(SummonPhase);
|
await game.phaseInterceptor.runFrom(SelectGenderPhase).to(SummonPhase);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("2vs1", async () => {
|
it("2vs1", async () => {
|
||||||
game.override.battleStyle("single");
|
game.override.battleStyle("single");
|
||||||
@ -247,41 +241,42 @@ describe("Test Battle Phase", () => {
|
|||||||
|
|
||||||
it("kill opponent pokemon", async () => {
|
it("kill opponent pokemon", async () => {
|
||||||
const moveToUse = MoveId.SPLASH;
|
const moveToUse = MoveId.SPLASH;
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.starterSpecies(SpeciesId.MEWTWO);
|
.battleStyle("single")
|
||||||
game.override.enemySpecies(SpeciesId.RATTATA);
|
.starterSpecies(SpeciesId.MEWTWO)
|
||||||
game.override.enemyAbility(AbilityId.HYDRATION);
|
.enemySpecies(SpeciesId.RATTATA)
|
||||||
game.override.ability(AbilityId.ZEN_MODE);
|
.enemyAbility(AbilityId.HYDRATION)
|
||||||
game.override.startingLevel(2000);
|
.ability(AbilityId.ZEN_MODE)
|
||||||
game.override.startingWave(3);
|
.startingLevel(2000)
|
||||||
game.override.moveset([moveToUse]);
|
.startingWave(3)
|
||||||
game.override.enemyMoveset([MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE]);
|
.moveset([moveToUse])
|
||||||
|
.enemyMoveset([MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE]);
|
||||||
await game.classicMode.startBattle([SpeciesId.DARMANITAN, SpeciesId.CHARIZARD]);
|
await game.classicMode.startBattle([SpeciesId.DARMANITAN, SpeciesId.CHARIZARD]);
|
||||||
|
|
||||||
game.move.select(moveToUse);
|
game.move.select(moveToUse);
|
||||||
await game.phaseInterceptor.to(DamageAnimPhase, false);
|
await game.phaseInterceptor.to(DamageAnimPhase, false);
|
||||||
await game.killPokemon(game.scene.currentBattle.enemyParty[0]);
|
await game.killPokemon(game.scene.currentBattle.enemyParty[0]);
|
||||||
expect(game.scene.currentBattle.enemyParty[0].isFainted()).toBe(true);
|
expect(game.scene.currentBattle.enemyParty[0].isFainted()).toBe(true);
|
||||||
await game.phaseInterceptor.to(VictoryPhase, false);
|
await game.phaseInterceptor.to("VictoryPhase");
|
||||||
}, 200000);
|
});
|
||||||
|
|
||||||
it("to next turn", async () => {
|
it("to next turn", async () => {
|
||||||
const moveToUse = MoveId.SPLASH;
|
const moveToUse = MoveId.SPLASH;
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
game.override.starterSpecies(SpeciesId.MEWTWO);
|
.battleStyle("single")
|
||||||
game.override.enemySpecies(SpeciesId.RATTATA);
|
.enemySpecies(SpeciesId.RATTATA)
|
||||||
game.override.enemyAbility(AbilityId.HYDRATION);
|
.enemyAbility(AbilityId.HYDRATION)
|
||||||
game.override.ability(AbilityId.ZEN_MODE);
|
.ability(AbilityId.ZEN_MODE)
|
||||||
game.override.startingLevel(2000);
|
.startingLevel(2000)
|
||||||
game.override.startingWave(3);
|
.startingWave(3)
|
||||||
game.override.moveset([moveToUse]);
|
.moveset([moveToUse])
|
||||||
game.override.enemyMoveset([MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE]);
|
.enemyMoveset([MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE]);
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle([SpeciesId.MEWTWO]);
|
||||||
const turn = game.scene.currentBattle.turn;
|
const turn = game.scene.currentBattle.turn;
|
||||||
game.move.select(moveToUse);
|
game.move.select(moveToUse);
|
||||||
await game.toNextTurn();
|
await game.toNextTurn();
|
||||||
expect(game.scene.currentBattle.turn).toBeGreaterThan(turn);
|
expect(game.scene.currentBattle.turn).toBeGreaterThan(turn);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("does not set new weather if staying in same biome", async () => {
|
it("does not set new weather if staying in same biome", async () => {
|
||||||
const moveToUse = MoveId.SPLASH;
|
const moveToUse = MoveId.SPLASH;
|
||||||
@ -294,8 +289,8 @@ describe("Test Battle Phase", () => {
|
|||||||
.startingLevel(2000)
|
.startingLevel(2000)
|
||||||
.startingWave(3)
|
.startingWave(3)
|
||||||
.startingBiome(BiomeId.LAKE)
|
.startingBiome(BiomeId.LAKE)
|
||||||
.moveset([moveToUse]);
|
.moveset([moveToUse])
|
||||||
game.override.enemyMoveset([MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE]);
|
.enemyMoveset([MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE, MoveId.TACKLE]);
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle();
|
||||||
const waveIndex = game.scene.currentBattle.waveIndex;
|
const waveIndex = game.scene.currentBattle.waveIndex;
|
||||||
game.move.select(moveToUse);
|
game.move.select(moveToUse);
|
||||||
@ -305,7 +300,7 @@ describe("Test Battle Phase", () => {
|
|||||||
await game.toNextWave();
|
await game.toNextWave();
|
||||||
expect(game.scene.arena.trySetWeather).not.toHaveBeenCalled();
|
expect(game.scene.arena.trySetWeather).not.toHaveBeenCalled();
|
||||||
expect(game.scene.currentBattle.waveIndex).toBeGreaterThan(waveIndex);
|
expect(game.scene.currentBattle.waveIndex).toBeGreaterThan(waveIndex);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("does not force switch if active pokemon faints at same time as enemy mon and is revived in post-battle", async () => {
|
it("does not force switch if active pokemon faints at same time as enemy mon and is revived in post-battle", async () => {
|
||||||
const moveToUse = MoveId.TAKE_DOWN;
|
const moveToUse = MoveId.TAKE_DOWN;
|
||||||
@ -336,5 +331,5 @@ describe("Test Battle Phase", () => {
|
|||||||
() => game.isCurrentPhase(NextEncounterPhase),
|
() => game.isCurrentPhase(NextEncounterPhase),
|
||||||
);
|
);
|
||||||
await game.phaseInterceptor.to(SwitchPhase);
|
await game.phaseInterceptor.to(SwitchPhase);
|
||||||
}, 20000);
|
});
|
||||||
});
|
});
|
||||||
|
@ -56,7 +56,7 @@ describe("Double Battles", () => {
|
|||||||
|
|
||||||
await game.phaseInterceptor.to(TurnInitPhase);
|
await game.phaseInterceptor.to(TurnInitPhase);
|
||||||
expect(game.scene.getPlayerField().filter(p => !p.isFainted())).toHaveLength(2);
|
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 () => {
|
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 rngSweepProgress = 0; // Will simulate RNG rolls by slowly increasing from 0 to 1
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { CommandPhase } from "#app/phases/command-phase";
|
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { AbilityId } from "#enums/ability-id";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
@ -32,66 +31,67 @@ describe("Test Battle Phase", () => {
|
|||||||
.enemyMoveset(MoveId.TACKLE);
|
.enemyMoveset(MoveId.TACKLE);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: Make these into `it.each`es
|
||||||
it("startBattle 2vs1 boss", async () => {
|
it("startBattle 2vs1 boss", async () => {
|
||||||
game.override.battleStyle("single").startingWave(10);
|
game.override.battleStyle("single").startingWave(10);
|
||||||
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
||||||
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
||||||
expect(game.scene.phaseManager.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name);
|
expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase");
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("startBattle 2vs2 boss", async () => {
|
it("startBattle 2vs2 boss", async () => {
|
||||||
game.override.battleStyle("double").startingWave(10);
|
game.override.battleStyle("double").startingWave(10);
|
||||||
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
||||||
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
||||||
expect(game.scene.phaseManager.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name);
|
expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase");
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("startBattle 2vs2 trainer", async () => {
|
it("startBattle 2vs2 trainer", async () => {
|
||||||
game.override.battleStyle("double").startingWave(5);
|
game.override.battleStyle("double").startingWave(5);
|
||||||
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
||||||
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
||||||
expect(game.scene.phaseManager.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name);
|
expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase");
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("startBattle 2vs1 trainer", async () => {
|
it("startBattle 2vs1 trainer", async () => {
|
||||||
game.override.battleStyle("single").startingWave(5);
|
game.override.battleStyle("single").startingWave(5);
|
||||||
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
||||||
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
||||||
expect(game.scene.phaseManager.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name);
|
expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase");
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("startBattle 2vs1 rival", async () => {
|
it("startBattle 2vs1 rival", async () => {
|
||||||
game.override.battleStyle("single").startingWave(8);
|
game.override.battleStyle("single").startingWave(8);
|
||||||
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
||||||
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
||||||
expect(game.scene.phaseManager.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name);
|
expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase");
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("startBattle 2vs2 rival", async () => {
|
it("startBattle 2vs2 rival", async () => {
|
||||||
game.override.battleStyle("double").startingWave(8);
|
game.override.battleStyle("double").startingWave(8);
|
||||||
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
||||||
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
||||||
expect(game.scene.phaseManager.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name);
|
expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase");
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("startBattle 1vs1 trainer", async () => {
|
it("startBattle 1vs1 trainer", async () => {
|
||||||
game.override.battleStyle("single").startingWave(5);
|
game.override.battleStyle("single").startingWave(5);
|
||||||
await game.classicMode.startBattle([SpeciesId.BLASTOISE]);
|
await game.classicMode.startBattle([SpeciesId.BLASTOISE]);
|
||||||
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
||||||
expect(game.scene.phaseManager.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name);
|
expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase");
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("startBattle 2vs2 trainer", async () => {
|
it("startBattle 2vs2 trainer", async () => {
|
||||||
game.override.battleStyle("double").startingWave(5);
|
game.override.battleStyle("double").startingWave(5);
|
||||||
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]);
|
||||||
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
||||||
expect(game.scene.phaseManager.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name);
|
expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase");
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("startBattle 4vs2 trainer", async () => {
|
it("startBattle 4vs2 trainer", async () => {
|
||||||
game.override.battleStyle("double").startingWave(5);
|
game.override.battleStyle("double").startingWave(5);
|
||||||
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD, SpeciesId.DARKRAI, SpeciesId.GABITE]);
|
await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD, SpeciesId.DARKRAI, SpeciesId.GABITE]);
|
||||||
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND);
|
||||||
expect(game.scene.phaseManager.getCurrentPhase()!.constructor.name).toBe(CommandPhase.name);
|
expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase");
|
||||||
}, 20000);
|
});
|
||||||
});
|
});
|
||||||
|
@ -13,7 +13,7 @@ import { SpeciesId } from "#enums/species-id";
|
|||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
import GameManager from "#test/testUtils/gameManager";
|
import GameManager from "#test/testUtils/gameManager";
|
||||||
import { mockI18next } from "#test/testUtils/testUtils";
|
import { mockI18next } from "#test/testUtils/testUtils";
|
||||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
const pokemonName = "PKM";
|
const pokemonName = "PKM";
|
||||||
const sourceText = "SOURCE";
|
const sourceText = "SOURCE";
|
||||||
@ -294,10 +294,6 @@ describe("Status Effect Messages", () => {
|
|||||||
expect(text).toBe("statusEffect:burn.overlap");
|
expect(text).toBe("statusEffect:burn.overlap");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
vi.resetAllMocks();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Status Effects", () => {
|
describe("Status Effects", () => {
|
||||||
|
@ -25,7 +25,6 @@ describe("Egg Generation Tests", () => {
|
|||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
game.phaseInterceptor.restoreOg();
|
game.phaseInterceptor.restoreOg();
|
||||||
vi.restoreAllMocks();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
@ -21,7 +21,6 @@ describe("Manaphy Eggs", () => {
|
|||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
game.phaseInterceptor.restoreOg();
|
game.phaseInterceptor.restoreOg();
|
||||||
vi.restoreAllMocks();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
@ -94,7 +94,7 @@ describe("Escape chance calculations", () => {
|
|||||||
phase.attemptRunAway(playerPokemon, enemyField, escapePercentage);
|
phase.attemptRunAway(playerPokemon, enemyField, escapePercentage);
|
||||||
expect(escapePercentage.value).toBe(escapeChances[i].expectedEscapeChance);
|
expect(escapePercentage.value).toBe(escapeChances[i].expectedEscapeChance);
|
||||||
}
|
}
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("double non-boss opponent", async () => {
|
it("double non-boss opponent", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double");
|
||||||
@ -180,7 +180,7 @@ describe("Escape chance calculations", () => {
|
|||||||
escapeChances[i].pokemonSpeedRatio * totalEnemySpeed,
|
escapeChances[i].pokemonSpeedRatio * totalEnemySpeed,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("single boss opponent", async () => {
|
it("single boss opponent", async () => {
|
||||||
game.override.startingWave(10);
|
game.override.startingWave(10);
|
||||||
@ -259,11 +259,10 @@ describe("Escape chance calculations", () => {
|
|||||||
phase.attemptRunAway(playerPokemon, enemyField, escapePercentage);
|
phase.attemptRunAway(playerPokemon, enemyField, escapePercentage);
|
||||||
expect(escapePercentage.value).toBe(escapeChances[i].expectedEscapeChance);
|
expect(escapePercentage.value).toBe(escapeChances[i].expectedEscapeChance);
|
||||||
}
|
}
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("double boss opponent", async () => {
|
it("double boss opponent", async () => {
|
||||||
game.override.battleStyle("double");
|
game.override.battleStyle("double").startingWave(10);
|
||||||
game.override.startingWave(10);
|
|
||||||
await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.ABOMASNOW]);
|
await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.ABOMASNOW]);
|
||||||
|
|
||||||
const playerPokemon = game.scene.getPlayerField();
|
const playerPokemon = game.scene.getPlayerField();
|
||||||
@ -358,5 +357,5 @@ describe("Escape chance calculations", () => {
|
|||||||
escapeChances[i].pokemonSpeedRatio * totalEnemySpeed,
|
escapeChances[i].pokemonSpeedRatio * totalEnemySpeed,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, 20000);
|
});
|
||||||
});
|
});
|
||||||
|
@ -28,12 +28,11 @@ describe("Evolution", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
|
|
||||||
game.override.battleStyle("single");
|
game.override
|
||||||
|
.battleStyle("single")
|
||||||
game.override.enemySpecies(SpeciesId.MAGIKARP);
|
.enemySpecies(SpeciesId.MAGIKARP)
|
||||||
game.override.enemyAbility(AbilityId.BALL_FETCH);
|
.enemyAbility(AbilityId.BALL_FETCH)
|
||||||
|
.startingLevel(60);
|
||||||
game.override.startingLevel(60);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should keep hidden ability after evolving", async () => {
|
it("should keep hidden ability after evolving", async () => {
|
||||||
|
@ -88,9 +88,7 @@ describe("Spec - Pokemon", () => {
|
|||||||
let scene: BattleScene;
|
let scene: BattleScene;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
game.override.enemySpecies(SpeciesId.ZUBAT);
|
game.override.enemySpecies(SpeciesId.ZUBAT).starterSpecies(SpeciesId.ABRA).enableStarterFusion();
|
||||||
game.override.starterSpecies(SpeciesId.ABRA);
|
|
||||||
game.override.enableStarterFusion();
|
|
||||||
scene = game.scene;
|
scene = game.scene;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -146,8 +144,7 @@ describe("Spec - Pokemon", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Fusing mons with one and two types", async () => {
|
it("Fusing mons with one and two types", async () => {
|
||||||
game.override.starterSpecies(SpeciesId.CHARMANDER);
|
game.override.starterSpecies(SpeciesId.CHARMANDER).starterFusionSpecies(SpeciesId.HOUNDOUR);
|
||||||
game.override.starterFusionSpecies(SpeciesId.HOUNDOUR);
|
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle();
|
||||||
const pokemon = scene.getPlayerParty()[0];
|
const pokemon = scene.getPlayerParty()[0];
|
||||||
|
|
||||||
@ -157,8 +154,7 @@ describe("Spec - Pokemon", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Fusing mons with two and one types", async () => {
|
it("Fusing mons with two and one types", async () => {
|
||||||
game.override.starterSpecies(SpeciesId.NUMEL);
|
game.override.starterSpecies(SpeciesId.NUMEL).starterFusionSpecies(SpeciesId.CHARMANDER);
|
||||||
game.override.starterFusionSpecies(SpeciesId.CHARMANDER);
|
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle();
|
||||||
const pokemon = scene.getPlayerParty()[0];
|
const pokemon = scene.getPlayerParty()[0];
|
||||||
|
|
||||||
@ -168,8 +164,7 @@ describe("Spec - Pokemon", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Fusing two mons with two types", async () => {
|
it("Fusing two mons with two types", async () => {
|
||||||
game.override.starterSpecies(SpeciesId.NATU);
|
game.override.starterSpecies(SpeciesId.NATU).starterFusionSpecies(SpeciesId.HOUNDOUR);
|
||||||
game.override.starterFusionSpecies(SpeciesId.HOUNDOUR);
|
|
||||||
await game.classicMode.startBattle();
|
await game.classicMode.startBattle();
|
||||||
const pokemon = scene.getPlayerParty()[0];
|
const pokemon = scene.getPlayerParty()[0];
|
||||||
|
|
||||||
|
@ -15,8 +15,6 @@ describe("game-mode", () => {
|
|||||||
});
|
});
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
game.phaseInterceptor.restoreOg();
|
game.phaseInterceptor.restoreOg();
|
||||||
vi.clearAllMocks();
|
|
||||||
vi.resetAllMocks();
|
|
||||||
});
|
});
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
|
@ -37,7 +37,7 @@ describe("Items - Dire Hit", () => {
|
|||||||
.moveset([MoveId.POUND])
|
.moveset([MoveId.POUND])
|
||||||
.startingHeldItems([{ name: "DIRE_HIT" }])
|
.startingHeldItems([{ name: "DIRE_HIT" }])
|
||||||
.battleStyle("single");
|
.battleStyle("single");
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("should raise CRIT stage by 1", async () => {
|
it("should raise CRIT stage by 1", async () => {
|
||||||
await game.classicMode.startBattle([SpeciesId.GASTLY]);
|
await game.classicMode.startBattle([SpeciesId.GASTLY]);
|
||||||
@ -51,7 +51,7 @@ describe("Items - Dire Hit", () => {
|
|||||||
await game.phaseInterceptor.to(TurnEndPhase);
|
await game.phaseInterceptor.to(TurnEndPhase);
|
||||||
|
|
||||||
expect(enemyPokemon.getCritStage).toHaveReturnedWith(1);
|
expect(enemyPokemon.getCritStage).toHaveReturnedWith(1);
|
||||||
}, 20000);
|
});
|
||||||
|
|
||||||
it("should renew how many battles are left of existing DIRE_HIT when picking up new DIRE_HIT", async () => {
|
it("should renew how many battles are left of existing DIRE_HIT when picking up new DIRE_HIT", async () => {
|
||||||
game.override.itemRewards([{ name: "DIRE_HIT" }]);
|
game.override.itemRewards([{ name: "DIRE_HIT" }]);
|
||||||
@ -93,5 +93,5 @@ describe("Items - Dire Hit", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect(count).toBe(1);
|
expect(count).toBe(1);
|
||||||
}, 20000);
|
});
|
||||||
});
|
});
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user