mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-06 23:49:26 +02:00
Merge branch 'beta' into evilleaderchanges
This commit is contained in:
commit
d179894018
5
.github/workflows/linting.yml
vendored
5
.github/workflows/linting.yml
vendored
@ -41,4 +41,7 @@ jobs:
|
||||
run: pnpm biome-ci
|
||||
|
||||
- name: Check dependencies with depcruise
|
||||
run: pnpm depcruise
|
||||
run: pnpm depcruise
|
||||
|
||||
- name: Lint with ls-lint
|
||||
run: pnpm ls-lint
|
2
.github/workflows/test-shard-template.yml
vendored
2
.github/workflows/test-shard-template.yml
vendored
@ -44,4 +44,4 @@ jobs:
|
||||
run: pnpm i
|
||||
|
||||
- name: Run tests
|
||||
run: pnpm exec vitest --project ${{ inputs.project }} --no-isolate --shard=${{ inputs.shard }}/${{ inputs.totalShards }} ${{ !runner.debug && '--silent' || '' }}
|
||||
run: pnpm test:silent --shard=${{ inputs.shard }}/${{ inputs.totalShards }}
|
||||
|
27
.ls-lint.yml
Normal file
27
.ls-lint.yml
Normal file
@ -0,0 +1,27 @@
|
||||
# Base settings to use
|
||||
# Note that the `_cfg` key isn't part of ls-lint's configuration, it's just a YAML anchor for reuse.
|
||||
_cfg: &cfg
|
||||
.ps1: kebab-case
|
||||
.ts: kebab-case
|
||||
.js: kebab-case
|
||||
.*.ts: kebab-case
|
||||
.*.js: kebab-case
|
||||
.dir: kebab-case
|
||||
.py: snake_case # python files should always use snake_case
|
||||
|
||||
ls:
|
||||
<<: *cfg
|
||||
src:
|
||||
<<: *cfg
|
||||
.dir: kebab-case | regex:@types
|
||||
.js: exists:0
|
||||
src/system/version-migration/versions:
|
||||
.ts: snake_case
|
||||
<<: *cfg
|
||||
|
||||
ignore:
|
||||
- node_modules
|
||||
- .vscode
|
||||
- .github
|
||||
- .git
|
||||
- public
|
@ -104,7 +104,7 @@ Most non-trivial changes (*especially bug fixes*) should come along with new tes
|
||||
- Test edge cases. A good strategy is to think of edge cases beforehand and create tests for them using `it.todo`. Once the edge case has been handled, you can remove the `todo` marker.
|
||||
|
||||
## 😈 Development Save File
|
||||
> Some issues may require you to have unlocks on your save file which go beyond normal overrides. For this reason, the repository contains a [save file](../test/testUtils/saves/everything.psrv) with _everything_ unlocked (even ones not legitimately obtainable, like unimplemented variant shinies).
|
||||
> Some issues may require you to have unlocks on your save file which go beyond normal overrides. For this reason, the repository contains a [save file](../test/test-utils/saves/everything.psrv) with _everything_ unlocked (even ones not legitimately obtainable, like unimplemented variant shinies).
|
||||
|
||||
1. Start the game up locally and navigate to `Menu -> Manage Data -> Import Data`
|
||||
2. Select [everything.prsv](test/testUtils/saves/everything.prsv) (`test/testUtils/saves/everything.prsv`) and confirm.
|
||||
2. Select [everything.prsv](test/test-utils/saves/everything.prsv) (`test/test-utils/saves/everything.prsv`) and confirm.
|
||||
|
2
global.d.ts
vendored
2
global.d.ts
vendored
@ -8,7 +8,7 @@ declare global {
|
||||
* Can technically be undefined/null but for ease of use we are going to assume it is always defined.
|
||||
* Used to load i18n files exclusively.
|
||||
*
|
||||
* To set up your own server in a test see `game_data.test.ts`
|
||||
* To set up your own server in a test see `game-data.test.ts`
|
||||
*/
|
||||
var server: SetupServerApi;
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
pre-commit:
|
||||
skip:
|
||||
- merge
|
||||
- rebase
|
||||
commands:
|
||||
biome-lint:
|
||||
run: pnpm exec biome check --write --reporter=summary --staged --no-errors-on-unmatched
|
||||
stage_fixed: true
|
||||
skip:
|
||||
- merge
|
||||
- rebase
|
||||
ls-lint:
|
||||
run: pnpm exec ls-lint
|
||||
|
||||
post-merge:
|
||||
commands:
|
||||
|
@ -12,7 +12,7 @@
|
||||
"test": "vitest run --no-isolate",
|
||||
"test:cov": "vitest run --coverage --no-isolate",
|
||||
"test:watch": "vitest watch --coverage --no-isolate",
|
||||
"test:silent": "vitest run --silent --no-isolate",
|
||||
"test:silent": "vitest run --silent='passed-only' --no-isolate",
|
||||
"test:create": "node scripts/create-test/create-test.js",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"eslint": "eslint --fix .",
|
||||
@ -28,6 +28,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.0.0",
|
||||
"@ls-lint/ls-lint": "2.3.1",
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"@types/node": "^22.16.3",
|
||||
"@vitest/coverage-istanbul": "^3.2.4",
|
||||
|
@ -45,6 +45,9 @@ importers:
|
||||
'@biomejs/biome':
|
||||
specifier: 2.0.0
|
||||
version: 2.0.0
|
||||
'@ls-lint/ls-lint':
|
||||
specifier: 2.3.1
|
||||
version: 2.3.1
|
||||
'@types/jsdom':
|
||||
specifier: ^21.1.7
|
||||
version: 21.1.7
|
||||
@ -565,6 +568,12 @@ packages:
|
||||
'@jridgewell/trace-mapping@0.3.29':
|
||||
resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==}
|
||||
|
||||
'@ls-lint/ls-lint@2.3.1':
|
||||
resolution: {integrity: sha512-vPe6IDByQnQRTxcAYjTxrmga/tSIui50VBFTB5KIJWY3OOFmxE2VtymjeSEfQfiMbhZV/ZPAqYy2lt8pZFQ0Rw==}
|
||||
cpu: [x64, arm64, s390x, ppc64le]
|
||||
os: [darwin, linux, win32]
|
||||
hasBin: true
|
||||
|
||||
'@material/material-color-utilities@0.2.7':
|
||||
resolution: {integrity: sha512-0FCeqG6WvK4/Cc06F/xXMd/pv4FeisI0c1tUpBbfhA2n9Y8eZEv4Karjbmf2ZqQCPUWMrGp8A571tCjizxoTiQ==}
|
||||
|
||||
@ -2452,6 +2461,8 @@ snapshots:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.4
|
||||
|
||||
'@ls-lint/ls-lint@2.3.1': {}
|
||||
|
||||
'@material/material-color-utilities@0.2.7': {}
|
||||
|
||||
'@mswjs/interceptors@0.39.2':
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { GameManager } from "#test/testUtils/gameManager";
|
||||
import { GameManager } from "#test/test-utils/game-manager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
||||
|
@ -2,13 +2,13 @@ import re
|
||||
|
||||
filenames = [['src/enums/moves.ts', 'move'], ['src/enums/abilities.ts', 'ability'], ['src/enums/species.ts', 'Pokémon']]
|
||||
|
||||
commentBlockStart = re.compile('\/\*[^\*].*') # Regex for the start of a comment block
|
||||
commentBlockEnd = re.compile('.*,\*\/') # Regex for the end of a comment block
|
||||
commentBlockStart = re.compile(r'\/\*[^\*].*') # Regex for the start of a comment block
|
||||
commentBlockEnd = re.compile(r'.*,\*\/') # Regex for the end of a comment block
|
||||
|
||||
commentExp = re.compile('(?:\/\*\*.*\*\/)') # Regex for a url comment that already existed in the file
|
||||
commentExp = re.compile(r'(?:\/\*\*.*\*\/)') # Regex for a url comment that already existed in the file
|
||||
enumExp = re.compile('.*,') # Regex for a regular enum line
|
||||
|
||||
numberExp = re.compile(' +\= +\d+,')
|
||||
numberExp = re.compile(r' +\= +\d+,')
|
||||
|
||||
replaceList = ['ALOLA', 'ETERNAL', 'GALAR', 'HISUI', 'PALDEA', 'BLOODMOON']
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { UserInfo } from "#types/UserInfo";
|
||||
import type { UserInfo } from "#types/user-info";
|
||||
|
||||
export interface AccountInfoResponse extends UserInfo {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
export class UpdateSessionSavedataRequest {
|
||||
export interface UpdateSessionSavedataRequest {
|
||||
slot: number;
|
||||
trainerId: number;
|
||||
secretId: number;
|
@ -4,7 +4,7 @@ export interface GetSystemSavedataRequest {
|
||||
clientSessionId: string;
|
||||
}
|
||||
|
||||
export class UpdateSystemSavedataRequest {
|
||||
export interface UpdateSystemSavedataRequest {
|
||||
clientSessionId: string;
|
||||
trainerId?: number;
|
||||
secretId?: number;
|
@ -1,6 +1,6 @@
|
||||
import { pokerogueApi } from "#api/pokerogue-api";
|
||||
import { bypassLogin } from "#app/global-vars/bypass-login";
|
||||
import type { UserInfo } from "#types/UserInfo";
|
||||
import type { UserInfo } from "#types/user-info";
|
||||
import { randomString } from "#utils/common";
|
||||
|
||||
export let loggedInUser: UserInfo | null = null;
|
||||
|
@ -699,16 +699,16 @@ export class BattleScene extends SceneBase {
|
||||
if (expSpriteKeys.size > 0) {
|
||||
return;
|
||||
}
|
||||
this.cachedFetch("./exp-sprites.json")
|
||||
.then(res => res.json())
|
||||
.then(keys => {
|
||||
if (Array.isArray(keys)) {
|
||||
for (const key of keys) {
|
||||
expSpriteKeys.add(key);
|
||||
}
|
||||
}
|
||||
Promise.resolve();
|
||||
});
|
||||
const res = await this.cachedFetch("./exp-sprites.json");
|
||||
const keys = await res.json();
|
||||
if (!Array.isArray(keys)) {
|
||||
throw new Error("EXP Sprites were not array when fetched!");
|
||||
}
|
||||
|
||||
// TODO: Optimize this
|
||||
for (const k of keys) {
|
||||
expSpriteKeys.add(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1669,6 +1669,11 @@ export class BattleScene extends SceneBase {
|
||||
case SpeciesId.MAUSHOLD:
|
||||
case SpeciesId.DUDUNSPARCE:
|
||||
return !randSeedInt(4) ? 1 : 0;
|
||||
case SpeciesId.SINISTEA:
|
||||
case SpeciesId.POLTEAGEIST:
|
||||
case SpeciesId.POLTCHAGEIST:
|
||||
case SpeciesId.SINISTCHA:
|
||||
return !randSeedInt(16) ? 1 : 0;
|
||||
case SpeciesId.PIKACHU:
|
||||
if (this.currentBattle?.battleType === BattleType.TRAINER && this.currentBattle?.waveIndex < 30) {
|
||||
return 0; // Ban Cosplay and Partner Pika from Trainers before wave 30
|
||||
|
@ -28,12 +28,12 @@ import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import type { BerryType } from "#enums/berry-type";
|
||||
import { Command } from "#enums/command";
|
||||
import { HitResult } from "#enums/hit-result";
|
||||
import { MoveCategory } from "#enums/MoveCategory";
|
||||
import { MoveFlags } from "#enums/MoveFlags";
|
||||
import { MoveTarget } from "#enums/MoveTarget";
|
||||
import { CommonAnim } from "#enums/move-anims-common";
|
||||
import { MoveCategory } from "#enums/move-category";
|
||||
import { MoveFlags } from "#enums/move-flags";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { MoveResult } from "#enums/move-result";
|
||||
import { MoveTarget } from "#enums/move-target";
|
||||
import { MoveUseMode } from "#enums/move-use-mode";
|
||||
import { PokemonAnimType } from "#enums/pokemon-anim-type";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
|
@ -9,10 +9,10 @@ import { ArenaTagType } from "#enums/arena-tag-type";
|
||||
import type { BattlerIndex } from "#enums/battler-index";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { HitResult } from "#enums/hit-result";
|
||||
import { MoveCategory } from "#enums/MoveCategory";
|
||||
import { MoveTarget } from "#enums/MoveTarget";
|
||||
import { CommonAnim } from "#enums/move-anims-common";
|
||||
import { MoveCategory } from "#enums/move-category";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { MoveTarget } from "#enums/move-target";
|
||||
import { MoveUseMode } from "#enums/move-use-mode";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import { Stat } from "#enums/stat";
|
||||
|
@ -86,7 +86,7 @@ export enum BiomePoolTier {
|
||||
|
||||
export const uncatchableSpecies: SpeciesId[] = [];
|
||||
|
||||
export interface SpeciesTree {
|
||||
interface SpeciesTree {
|
||||
[key: number]: SpeciesId[]
|
||||
}
|
||||
|
||||
@ -94,11 +94,11 @@ export interface PokemonPools {
|
||||
[key: number]: (SpeciesId | SpeciesTree)[]
|
||||
}
|
||||
|
||||
export interface BiomeTierPokemonPools {
|
||||
interface BiomeTierPokemonPools {
|
||||
[key: number]: PokemonPools
|
||||
}
|
||||
|
||||
export interface BiomePokemonPools {
|
||||
interface BiomePokemonPools {
|
||||
[key: number]: BiomeTierPokemonPools
|
||||
}
|
||||
|
||||
@ -2022,7 +2022,6 @@ export const biomeTrainerPools: BiomeTrainerPools = {
|
||||
}
|
||||
};
|
||||
|
||||
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: init methods are expected to have many lines.
|
||||
export function initBiomes() {
|
||||
const pokemonBiomes = [
|
||||
[ SpeciesId.BULBASAUR, PokemonType.GRASS, PokemonType.POISON, [
|
||||
|
@ -3,8 +3,8 @@ import { allMoves } from "#data/data-lists";
|
||||
import type { BattlerIndex } from "#enums/battler-index";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { EncounterAnim } from "#enums/encounter-anims";
|
||||
import { MoveFlags } from "#enums/MoveFlags";
|
||||
import { AnimBlendType, AnimFocus, AnimFrameTarget, ChargeAnim, CommonAnim } from "#enums/move-anims-common";
|
||||
import { MoveFlags } from "#enums/move-flags";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { animationFileName, coerceArray, getFrameMs, isNullOrUndefined, type nil } from "#utils/common";
|
||||
|
@ -11,9 +11,9 @@ import { AbilityId } from "#enums/ability-id";
|
||||
import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { HitResult } from "#enums/hit-result";
|
||||
import { MoveCategory } from "#enums/MoveCategory";
|
||||
import { MoveFlags } from "#enums/MoveFlags";
|
||||
import { ChargeAnim, CommonAnim } from "#enums/move-anims-common";
|
||||
import { MoveCategory } from "#enums/move-category";
|
||||
import { MoveFlags } from "#enums/move-flags";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { MoveResult } from "#enums/move-result";
|
||||
import { MoveUseMode } from "#enums/move-use-mode";
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { allMoves } from "#data/data-lists";
|
||||
import type { BattlerIndex } from "#enums/battler-index";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { MoveTarget } from "#enums/MoveTarget";
|
||||
import type { MoveId } from "#enums/move-id";
|
||||
import { MoveTarget } from "#enums/move-target";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import { applyMoveAttrs } from "#moves/apply-attrs";
|
||||
@ -27,6 +27,28 @@ export function isFieldTargeted(move: Move): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether a move is a spread move.
|
||||
*
|
||||
* @param move - The {@linkcode Move} to check
|
||||
* @returns Whether {@linkcode move} is spread-targeted.
|
||||
* @remarks
|
||||
* Examples include:
|
||||
* - Moves targeting all adjacent Pokemon (like Surf)
|
||||
* - Moves targeting all adjacent enemies (like Air Cutter)
|
||||
*/
|
||||
|
||||
export function isSpreadMove(move: Move): boolean {
|
||||
switch (move.moveTarget) {
|
||||
case MoveTarget.ALL_ENEMIES:
|
||||
case MoveTarget.ALL_NEAR_ENEMIES:
|
||||
case MoveTarget.ALL_OTHERS:
|
||||
case MoveTarget.ALL_NEAR_OTHERS:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getMoveTargets(user: Pokemon, move: MoveId, replaceTarget?: MoveTarget): MoveTargetSet {
|
||||
const variableTarget = new NumberHolder(0);
|
||||
user.getOpponents(false).forEach(p => applyMoveAttrs("VariableTargetAttr", user, p, allMoves[move], variableTarget));
|
||||
|
@ -48,11 +48,11 @@ import { ChargeAnim } from "#enums/move-anims-common";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { MoveResult } from "#enums/move-result";
|
||||
import { isVirtual, MoveUseMode } from "#enums/move-use-mode";
|
||||
import { MoveCategory } from "#enums/MoveCategory";
|
||||
import { MoveEffectTrigger } from "#enums/MoveEffectTrigger";
|
||||
import { MoveFlags } from "#enums/MoveFlags";
|
||||
import { MoveTarget } from "#enums/MoveTarget";
|
||||
import { MultiHitType } from "#enums/MultiHitType";
|
||||
import { MoveCategory } from "#enums/move-category";
|
||||
import { MoveEffectTrigger } from "#enums/move-effect-trigger";
|
||||
import { MoveFlags } from "#enums/move-flags";
|
||||
import { MoveTarget } from "#enums/move-target";
|
||||
import { MultiHitType } from "#enums/multi-hit-type";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import {
|
||||
@ -808,16 +808,14 @@ export abstract class Move implements Localizable {
|
||||
}
|
||||
|
||||
const power = new NumberHolder(this.power);
|
||||
|
||||
applyMoveAttrs("VariablePowerAttr", source, target, this, power);
|
||||
|
||||
const typeChangeMovePowerMultiplier = new NumberHolder(1);
|
||||
const typeChangeHolder = new NumberHolder(this.type);
|
||||
|
||||
applyAbAttrs("MoveTypeChangeAbAttr", {pokemon: source, opponent: target, move: this, simulated: true, moveType: typeChangeHolder, power: typeChangeMovePowerMultiplier});
|
||||
|
||||
const sourceTeraType = source.getTeraType();
|
||||
if (source.isTerastallized && sourceTeraType === this.type && power.value < 60 && this.priority <= 0 && !this.hasAttr("MultiHitAttr") && !globalScene.findModifier(m => m instanceof PokemonMultiHitModifier && m.pokemonId === source.id)) {
|
||||
power.value = 60;
|
||||
}
|
||||
|
||||
const abAttrParams: PreAttackModifyPowerAbAttrParams = {
|
||||
pokemon: source,
|
||||
opponent: target,
|
||||
@ -832,6 +830,13 @@ export abstract class Move implements Localizable {
|
||||
applyAbAttrs("AllyMoveCategoryPowerBoostAbAttr", {...abAttrParams, pokemon: ally});
|
||||
}
|
||||
|
||||
// Non-priority, single-hit moves of the user's Tera Type are always a bare minimum of 60 power
|
||||
|
||||
const sourceTeraType = source.getTeraType();
|
||||
if (source.isTerastallized && sourceTeraType === this.type && power.value < 60 && this.priority <= 0 && !this.hasAttr("MultiHitAttr") && !globalScene.findModifier(m => m instanceof PokemonMultiHitModifier && m.pokemonId === source.id)) {
|
||||
power.value = 60;
|
||||
}
|
||||
|
||||
const fieldAuras = new Set(
|
||||
globalScene.getField(true)
|
||||
.map((p) => p.getAbilityAttrs("FieldMoveTypePowerBoostAbAttr").filter(attr => {
|
||||
@ -855,7 +860,6 @@ export abstract class Move implements Localizable {
|
||||
power.value *= typeBoost.boostValue;
|
||||
}
|
||||
|
||||
applyMoveAttrs("VariablePowerAttr", source, target, this, power);
|
||||
|
||||
if (!this.hasAttr("TypelessAttr")) {
|
||||
globalScene.arena.applyTags(WeakenMoveTypeTag, simulated, typeChangeHolder.value, power);
|
||||
|
@ -8,9 +8,9 @@ import { BattlerIndex } from "#enums/battler-index";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
import { EncounterAnim } from "#enums/encounter-anims";
|
||||
import { MoveCategory } from "#enums/MoveCategory";
|
||||
import { ModifierPoolType } from "#enums/modifier-pool-type";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { MoveCategory } from "#enums/move-category";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { MoveUseMode } from "#enums/move-use-mode";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { modifierTypes } from "#data/data-lists";
|
||||
import { MoveCategory } from "#enums/MoveCategory";
|
||||
import { MoveCategory } from "#enums/move-category";
|
||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
} from "#data/form-change-triggers";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { FormChangeItem } from "#enums/form-change-item";
|
||||
import { MoveCategory } from "#enums/MoveCategory";
|
||||
import { MoveCategory } from "#enums/move-category";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
|
@ -2851,11 +2851,11 @@ export function initSpecies() {
|
||||
new PokemonSpecies(SpeciesId.GRAPPLOCT, 8, false, false, false, "Jujitsu Pokémon", PokemonType.FIGHTING, null, 1.6, 39, AbilityId.LIMBER, AbilityId.NONE, AbilityId.TECHNICIAN, 480, 80, 118, 90, 70, 80, 42, 45, 50, 168, GrowthRate.MEDIUM_SLOW, 50, false),
|
||||
new PokemonSpecies(SpeciesId.SINISTEA, 8, false, false, false, "Black Tea Pokémon", PokemonType.GHOST, null, 0.1, 0.2, AbilityId.WEAK_ARMOR, AbilityId.NONE, AbilityId.CURSED_BODY, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, GrowthRate.MEDIUM_FAST, null, false, false,
|
||||
new PokemonForm("Phony Form", "phony", PokemonType.GHOST, null, 0.1, 0.2, AbilityId.WEAK_ARMOR, AbilityId.NONE, AbilityId.CURSED_BODY, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, "", true),
|
||||
new PokemonForm("Antique Form", "antique", PokemonType.GHOST, null, 0.1, 0.2, AbilityId.WEAK_ARMOR, AbilityId.NONE, AbilityId.CURSED_BODY, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, "", true, true),
|
||||
new PokemonForm("Antique Form", "antique", PokemonType.GHOST, null, 0.1, 0.2, AbilityId.WEAK_ARMOR, AbilityId.NONE, AbilityId.CURSED_BODY, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, "", true),
|
||||
),
|
||||
new PokemonSpecies(SpeciesId.POLTEAGEIST, 8, false, false, false, "Black Tea Pokémon", PokemonType.GHOST, null, 0.2, 0.4, AbilityId.WEAK_ARMOR, AbilityId.NONE, AbilityId.CURSED_BODY, 508, 60, 65, 65, 134, 114, 70, 60, 50, 178, GrowthRate.MEDIUM_FAST, null, false, false,
|
||||
new PokemonForm("Phony Form", "phony", PokemonType.GHOST, null, 0.2, 0.4, AbilityId.WEAK_ARMOR, AbilityId.NONE, AbilityId.CURSED_BODY, 508, 60, 65, 65, 134, 114, 70, 60, 50, 178, false, "", true),
|
||||
new PokemonForm("Antique Form", "antique", PokemonType.GHOST, null, 0.2, 0.4, AbilityId.WEAK_ARMOR, AbilityId.NONE, AbilityId.CURSED_BODY, 508, 60, 65, 65, 134, 114, 70, 60, 50, 178, false, "", true, true),
|
||||
new PokemonForm("Antique Form", "antique", PokemonType.GHOST, null, 0.2, 0.4, AbilityId.WEAK_ARMOR, AbilityId.NONE, AbilityId.CURSED_BODY, 508, 60, 65, 65, 134, 114, 70, 60, 50, 178, false, "", true),
|
||||
),
|
||||
new PokemonSpecies(SpeciesId.HATENNA, 8, false, false, false, "Calm Pokémon", PokemonType.PSYCHIC, null, 0.4, 3.4, AbilityId.HEALER, AbilityId.ANTICIPATION, AbilityId.MAGIC_BOUNCE, 265, 42, 30, 45, 56, 53, 39, 235, 50, 53, GrowthRate.SLOW, 0, false),
|
||||
new PokemonSpecies(SpeciesId.HATTREM, 8, false, false, false, "Serene Pokémon", PokemonType.PSYCHIC, null, 0.6, 4.8, AbilityId.HEALER, AbilityId.ANTICIPATION, AbilityId.MAGIC_BOUNCE, 370, 57, 40, 65, 86, 73, 49, 120, 50, 130, GrowthRate.SLOW, 0, false),
|
||||
@ -3109,11 +3109,11 @@ export function initSpecies() {
|
||||
new PokemonSpecies(SpeciesId.DIPPLIN, 9, false, false, false, "Candy Apple Pokémon", PokemonType.GRASS, PokemonType.DRAGON, 0.4, 4.4, AbilityId.SUPERSWEET_SYRUP, AbilityId.GLUTTONY, AbilityId.STICKY_HOLD, 485, 80, 80, 110, 95, 80, 40, 45, 50, 170, GrowthRate.ERRATIC, 50, false),
|
||||
new PokemonSpecies(SpeciesId.POLTCHAGEIST, 9, false, false, false, "Matcha Pokémon", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, AbilityId.HOSPITALITY, AbilityId.NONE, AbilityId.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, GrowthRate.SLOW, null, false, false,
|
||||
new PokemonForm("Counterfeit Form", "counterfeit", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, AbilityId.HOSPITALITY, AbilityId.NONE, AbilityId.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, null, true),
|
||||
new PokemonForm("Artisan Form", "artisan", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, AbilityId.HOSPITALITY, AbilityId.NONE, AbilityId.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, null, false, true),
|
||||
new PokemonForm("Artisan Form", "artisan", PokemonType.GRASS, PokemonType.GHOST, 0.1, 1.1, AbilityId.HOSPITALITY, AbilityId.NONE, AbilityId.HEATPROOF, 308, 40, 45, 45, 74, 54, 50, 120, 50, 62, false, "counterfeit", true),
|
||||
),
|
||||
new PokemonSpecies(SpeciesId.SINISTCHA, 9, false, false, false, "Matcha Pokémon", PokemonType.GRASS, PokemonType.GHOST, 0.2, 2.2, AbilityId.HOSPITALITY, AbilityId.NONE, AbilityId.HEATPROOF, 508, 71, 60, 106, 121, 80, 70, 60, 50, 178, GrowthRate.SLOW, null, false, false,
|
||||
new PokemonForm("Unremarkable Form", "unremarkable", PokemonType.GRASS, PokemonType.GHOST, 0.2, 2.2, AbilityId.HOSPITALITY, AbilityId.NONE, AbilityId.HEATPROOF, 508, 71, 60, 106, 121, 80, 70, 60, 50, 178),
|
||||
new PokemonForm("Masterpiece Form", "masterpiece", PokemonType.GRASS, PokemonType.GHOST, 0.2, 2.2, AbilityId.HOSPITALITY, AbilityId.NONE, AbilityId.HEATPROOF, 508, 71, 60, 106, 121, 80, 70, 60, 50, 178, false, null, false, true),
|
||||
new PokemonForm("Unremarkable Form", "unremarkable", PokemonType.GRASS, PokemonType.GHOST, 0.2, 2.2, AbilityId.HOSPITALITY, AbilityId.NONE, AbilityId.HEATPROOF, 508, 71, 60, 106, 121, 80, 70, 60, 50, 178, false, null, true),
|
||||
new PokemonForm("Masterpiece Form", "masterpiece", PokemonType.GRASS, PokemonType.GHOST, 0.2, 2.2, AbilityId.HOSPITALITY, AbilityId.NONE, AbilityId.HEATPROOF, 508, 71, 60, 106, 121, 80, 70, 60, 50, 178, false, "unremarkable", true),
|
||||
),
|
||||
new PokemonSpecies(SpeciesId.OKIDOGI, 9, true, false, false, "Retainer Pokémon", PokemonType.POISON, PokemonType.FIGHTING, 1.8, 92.2, AbilityId.TOXIC_CHAIN, AbilityId.NONE, AbilityId.GUARD_DOG, 555, 88, 128, 115, 58, 86, 80, 3, 0, 276, GrowthRate.SLOW, 100, false),
|
||||
new PokemonSpecies(SpeciesId.MUNKIDORI, 9, true, false, false, "Retainer Pokémon", PokemonType.POISON, PokemonType.PSYCHIC, 1, 12.2, AbilityId.TOXIC_CHAIN, AbilityId.NONE, AbilityId.FRISK, 555, 88, 75, 66, 130, 90, 106, 3, 0, 276, GrowthRate.SLOW, 100, false),
|
||||
|
@ -3,6 +3,7 @@ import type { BattlerIndex } from "#enums/battler-index";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
import type { Move } from "#moves/move";
|
||||
import { isFieldTargeted, isSpreadMove } from "#moves/move-utils";
|
||||
import i18next from "i18next";
|
||||
|
||||
export enum TerrainType {
|
||||
@ -60,13 +61,19 @@ export class Terrain {
|
||||
isMoveTerrainCancelled(user: Pokemon, targets: BattlerIndex[], move: Move): boolean {
|
||||
switch (this.terrainType) {
|
||||
case TerrainType.PSYCHIC:
|
||||
if (!move.hasAttr("ProtectAttr")) {
|
||||
// Cancels move if the move has positive priority and targets a Pokemon grounded on the Psychic Terrain
|
||||
return (
|
||||
move.getPriority(user) > 0 &&
|
||||
user.getOpponents(true).some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded())
|
||||
);
|
||||
}
|
||||
// Cf https://bulbapedia.bulbagarden.net/wiki/Psychic_Terrain_(move)#Generation_VII
|
||||
// Psychic terrain will only cancel a move if it:
|
||||
return (
|
||||
// ... is neither spread nor field-targeted,
|
||||
!isFieldTargeted(move) &&
|
||||
!isSpreadMove(move) &&
|
||||
// .. has positive final priority,
|
||||
move.getPriority(user) > 0 &&
|
||||
// ...and is targeting at least 1 grounded opponent
|
||||
user
|
||||
.getOpponents(true)
|
||||
.some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded())
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -82,11 +82,11 @@ import { DexAttr } from "#enums/dex-attr";
|
||||
import { FieldPosition } from "#enums/field-position";
|
||||
import { HitResult } from "#enums/hit-result";
|
||||
import { LearnMoveSituation } from "#enums/learn-move-situation";
|
||||
import { MoveCategory } from "#enums/MoveCategory";
|
||||
import { MoveFlags } from "#enums/MoveFlags";
|
||||
import { MoveTarget } from "#enums/MoveTarget";
|
||||
import { ModifierTier } from "#enums/modifier-tier";
|
||||
import { MoveCategory } from "#enums/move-category";
|
||||
import { MoveFlags } from "#enums/move-flags";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { MoveTarget } from "#enums/move-target";
|
||||
import { isIgnorePP, isVirtual, MoveUseMode } from "#enums/move-use-mode";
|
||||
import { Nature } from "#enums/nature";
|
||||
import { PokeballType } from "#enums/pokeball";
|
||||
|
35
src/init/init.ts
Normal file
35
src/init/init.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { initAbilities } from "#abilities/ability";
|
||||
import { initBiomes } from "#balance/biomes";
|
||||
import { initEggMoves } from "#balance/egg-moves";
|
||||
import { initPokemonPrevolutions, initPokemonStarters } from "#balance/pokemon-evolutions";
|
||||
import { initChallenges } from "#data/challenge";
|
||||
import { initTrainerTypeDialogue } from "#data/dialogue";
|
||||
import { initPokemonForms } from "#data/pokemon-forms";
|
||||
import { initSpecies } from "#data/pokemon-species";
|
||||
import { initModifierPools } from "#modifiers/init-modifier-pools";
|
||||
import { initModifierTypes } from "#modifiers/modifier-type";
|
||||
import { initMoves } from "#moves/move";
|
||||
import { initMysteryEncounters } from "#mystery-encounters/mystery-encounters";
|
||||
import { initAchievements } from "#system/achv";
|
||||
import { initVouchers } from "#system/voucher";
|
||||
import { initStatsKeys } from "#ui/game-stats-ui-handler";
|
||||
|
||||
/** Initialize the game. */
|
||||
export function initializeGame() {
|
||||
initModifierTypes();
|
||||
initModifierPools();
|
||||
initAchievements();
|
||||
initVouchers();
|
||||
initStatsKeys();
|
||||
initPokemonPrevolutions();
|
||||
initPokemonStarters();
|
||||
initBiomes();
|
||||
initEggMoves();
|
||||
initPokemonForms();
|
||||
initTrainerTypeDialogue();
|
||||
initSpecies();
|
||||
initMoves();
|
||||
initAbilities();
|
||||
initChallenges();
|
||||
initMysteryEncounters();
|
||||
}
|
@ -3,13 +3,13 @@ import { TouchControl } from "#app/touch-controls";
|
||||
import { Button } from "#enums/buttons";
|
||||
import { Device } from "#enums/devices";
|
||||
import { UiMode } from "#enums/ui-mode";
|
||||
import cfg_keyboard_qwerty from "#inputs/cfg_keyboard_qwerty";
|
||||
import { assign, getButtonWithKeycode, getIconForLatestInput, swap } from "#inputs/configHandler";
|
||||
import pad_dualshock from "#inputs/pad_dualshock";
|
||||
import pad_generic from "#inputs/pad_generic";
|
||||
import pad_procon from "#inputs/pad_procon";
|
||||
import pad_unlicensedSNES from "#inputs/pad_unlicensedSNES";
|
||||
import pad_xbox360 from "#inputs/pad_xbox360";
|
||||
import cfg_keyboard_qwerty from "#inputs/cfg-keyboard-qwerty";
|
||||
import { assign, getButtonWithKeycode, getIconForLatestInput, swap } from "#inputs/config-handler";
|
||||
import pad_dualshock from "#inputs/pad-dualshock";
|
||||
import pad_generic from "#inputs/pad-generic";
|
||||
import pad_procon from "#inputs/pad-procon";
|
||||
import pad_unlicensedSNES from "#inputs/pad-unlicensed-snes";
|
||||
import pad_xbox360 from "#inputs/pad-xbox360";
|
||||
import type { SettingGamepad } from "#system/settings-gamepad";
|
||||
import type { SettingKeyboard } from "#system/settings-keyboard";
|
||||
import { MoveTouchControlsHandler } from "#ui/move-touch-controls-handler";
|
||||
|
@ -1,29 +1,16 @@
|
||||
import { initAbilities } from "#abilities/ability";
|
||||
import { timedEventManager } from "#app/global-event-manager";
|
||||
import { initializeGame } from "#app/init/init";
|
||||
import { SceneBase } from "#app/scene-base";
|
||||
import { isMobile } from "#app/touch-controls";
|
||||
import { initBiomes } from "#balance/biomes";
|
||||
import { initEggMoves } from "#balance/egg-moves";
|
||||
import { initPokemonPrevolutions, initPokemonStarters } from "#balance/pokemon-evolutions";
|
||||
import { initChallenges } from "#data/challenge";
|
||||
import { initTrainerTypeDialogue } from "#data/dialogue";
|
||||
import { initPokemonForms } from "#data/pokemon-forms";
|
||||
import { initSpecies } from "#data/pokemon-species";
|
||||
import { BiomeId } from "#enums/biome-id";
|
||||
import { GachaType } from "#enums/gacha-types";
|
||||
import { getBiomeHasProps } from "#field/arena";
|
||||
import { initModifierPools } from "#modifiers/init-modifier-pools";
|
||||
import { initModifierTypes } from "#modifiers/modifier-type";
|
||||
import { initMoves } from "#moves/move";
|
||||
import { initMysteryEncounters } from "#mystery-encounters/mystery-encounters";
|
||||
import { CacheBustedLoaderPlugin } from "#plugins/cache-busted-loader-plugin";
|
||||
import { initAchievements } from "#system/achv";
|
||||
import { initVouchers } from "#system/voucher";
|
||||
import { initStatsKeys } from "#ui/game-stats-ui-handler";
|
||||
import { getWindowVariantSuffix, WindowVariant } from "#ui/ui-theme";
|
||||
import { hasAllLocalizedSprites, localPing } from "#utils/common";
|
||||
import { getEnumValues } from "#utils/enums";
|
||||
import i18next from "i18next";
|
||||
import type { GameObjects } from "phaser";
|
||||
|
||||
export class LoadingScene extends SceneBase {
|
||||
public static readonly KEY = "loading";
|
||||
@ -366,30 +353,12 @@ export class LoadingScene extends SceneBase {
|
||||
|
||||
this.loadLoadingScreen();
|
||||
|
||||
initModifierTypes();
|
||||
initModifierPools();
|
||||
|
||||
initAchievements();
|
||||
initVouchers();
|
||||
initStatsKeys();
|
||||
initPokemonPrevolutions();
|
||||
initPokemonStarters();
|
||||
initBiomes();
|
||||
initEggMoves();
|
||||
initPokemonForms();
|
||||
initTrainerTypeDialogue();
|
||||
initSpecies();
|
||||
initMoves();
|
||||
initAbilities();
|
||||
initChallenges();
|
||||
initMysteryEncounters();
|
||||
initializeGame();
|
||||
}
|
||||
|
||||
loadLoadingScreen() {
|
||||
const mobile = isMobile();
|
||||
|
||||
const loadingGraphics: any[] = [];
|
||||
|
||||
const bg = this.add.image(0, 0, "");
|
||||
bg.setOrigin(0, 0);
|
||||
bg.setScale(6);
|
||||
@ -460,6 +429,7 @@ export class LoadingScene extends SceneBase {
|
||||
});
|
||||
disclaimerDescriptionText.setOrigin(0.5, 0.5);
|
||||
|
||||
const loadingGraphics: (GameObjects.Image | GameObjects.Graphics | GameObjects.Text)[] = [];
|
||||
loadingGraphics.push(
|
||||
bg,
|
||||
graphics,
|
||||
|
@ -279,6 +279,7 @@ export class AttemptCapturePhase extends PokemonPhase {
|
||||
globalScene.updateModifiers(true);
|
||||
removePokemon();
|
||||
if (newPokemon) {
|
||||
newPokemon.leaveField(true, true, false);
|
||||
newPokemon.loadAssets().then(end);
|
||||
} else {
|
||||
end();
|
||||
|
@ -13,12 +13,12 @@ import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { HitCheckResult } from "#enums/hit-check-result";
|
||||
import { HitResult } from "#enums/hit-result";
|
||||
import { MoveCategory } from "#enums/MoveCategory";
|
||||
import { MoveEffectTrigger } from "#enums/MoveEffectTrigger";
|
||||
import { MoveFlags } from "#enums/MoveFlags";
|
||||
import { MoveTarget } from "#enums/MoveTarget";
|
||||
import { MoveCategory } from "#enums/move-category";
|
||||
import { MoveEffectTrigger } from "#enums/move-effect-trigger";
|
||||
import { MoveFlags } from "#enums/move-flags";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { MoveResult } from "#enums/move-result";
|
||||
import { MoveTarget } from "#enums/move-target";
|
||||
import { isReflected, isVirtual, MoveUseMode } from "#enums/move-use-mode";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import type { Pokemon } from "#field/pokemon";
|
||||
|
@ -13,8 +13,8 @@ import { ArenaTagType } from "#enums/arena-tag-type";
|
||||
import { BattlerIndex } from "#enums/battler-index";
|
||||
import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { MoveFlags } from "#enums/MoveFlags";
|
||||
import { CommonAnim } from "#enums/move-anims-common";
|
||||
import { MoveFlags } from "#enums/move-flags";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { MoveResult } from "#enums/move-result";
|
||||
import { isIgnorePP, isIgnoreStatus, isReflected, isVirtual, MoveUseMode } from "#enums/move-use-mode";
|
||||
|
@ -2,8 +2,8 @@ import { globalScene } from "#app/global-scene";
|
||||
import { getTerrainColor, TerrainType } from "#data/terrain";
|
||||
import { getCurrentTime } from "#utils/common";
|
||||
import Phaser from "phaser";
|
||||
import fieldSpriteFragShader from "./glsl/fieldSpriteFragShader.frag?raw";
|
||||
import spriteVertShader from "./glsl/spriteShader.vert?raw";
|
||||
import fieldSpriteFragShader from "./glsl/field-sprite-frag-shader.frag?raw";
|
||||
import spriteVertShader from "./glsl/sprite-shader.vert?raw";
|
||||
|
||||
export class FieldSpritePipeline extends Phaser.Renderer.WebGL.Pipelines.MultiPipeline {
|
||||
constructor(game: Phaser.Game, config?: Phaser.Types.Renderer.WebGL.WebGLPipelineConfig) {
|
||||
|
@ -5,8 +5,8 @@ import { Pokemon } from "#field/pokemon";
|
||||
import { Trainer } from "#field/trainer";
|
||||
import { variantColorCache } from "#sprites/variant";
|
||||
import { rgbHexToRgba } from "#utils/common";
|
||||
import spriteFragShader from "./glsl/spriteFragShader.frag?raw";
|
||||
import spriteVertShader from "./glsl/spriteShader.vert?raw";
|
||||
import spriteFragShader from "./glsl/sprite-frag-shader.frag?raw";
|
||||
import spriteVertShader from "./glsl/sprite-shader.vert?raw";
|
||||
|
||||
export class SpritePipeline extends FieldSpritePipeline {
|
||||
private _tone: number[];
|
||||
|
@ -5,7 +5,7 @@ import type {
|
||||
AccountLoginRequest,
|
||||
AccountLoginResponse,
|
||||
AccountRegisterRequest,
|
||||
} from "#types/PokerogueAccountApi";
|
||||
} from "#types/api/pokerogue-account-api";
|
||||
import { removeCookie, setCookie } from "#utils/cookies";
|
||||
|
||||
/**
|
||||
|
@ -6,7 +6,7 @@ import type {
|
||||
SearchAccountResponse,
|
||||
UnlinkAccountFromDiscordIdRequest,
|
||||
UnlinkAccountFromGoogledIdRequest,
|
||||
} from "#types/PokerogueAdminApi";
|
||||
} from "#types/api/pokerogue-admin-api";
|
||||
|
||||
export class PokerogueAdminApi extends ApiBase {
|
||||
public readonly ERR_USERNAME_NOT_FOUND: string = "Username not found!";
|
||||
|
@ -3,7 +3,7 @@ import { PokerogueAccountApi } from "#api/pokerogue-account-api";
|
||||
import { PokerogueAdminApi } from "#api/pokerogue-admin-api";
|
||||
import { PokerogueDailyApi } from "#api/pokerogue-daily-api";
|
||||
import { PokerogueSavedataApi } from "#api/pokerogue-savedata-api";
|
||||
import type { TitleStatsResponse } from "#types/PokerogueApi";
|
||||
import type { TitleStatsResponse } from "#types/api/pokerogue-api-types";
|
||||
|
||||
/**
|
||||
* A wrapper for PokéRogue API requests.
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ApiBase } from "#api/api-base";
|
||||
import type { GetDailyRankingsPageCountRequest, GetDailyRankingsRequest } from "#types/PokerogueDailyApi";
|
||||
import type { GetDailyRankingsPageCountRequest, GetDailyRankingsRequest } from "#types/api/pokerogue-daily-api";
|
||||
import type { RankingEntry } from "#ui/daily-run-scoreboard";
|
||||
|
||||
/**
|
||||
|
@ -2,7 +2,7 @@ import { ApiBase } from "#api/api-base";
|
||||
import { PokerogueSessionSavedataApi } from "#api/pokerogue-session-savedata-api";
|
||||
import { PokerogueSystemSavedataApi } from "#api/pokerogue-system-savedata-api";
|
||||
import { MAX_INT_ATTR_VALUE } from "#app/constants";
|
||||
import type { UpdateAllSavedataRequest } from "#types/PokerogueSavedataApi";
|
||||
import type { UpdateAllSavedataRequest } from "#types/api/pokerogue-save-data-api";
|
||||
|
||||
/**
|
||||
* A wrapper for PokéRogue savedata API requests.
|
||||
|
@ -7,7 +7,7 @@ import type {
|
||||
GetSessionSavedataRequest,
|
||||
NewClearSessionSavedataRequest,
|
||||
UpdateSessionSavedataRequest,
|
||||
} from "#types/PokerogueSessionSavedataApi";
|
||||
} from "#types/api/pokerogue-session-save-data-api";
|
||||
|
||||
/**
|
||||
* A wrapper for PokéRogue session savedata API requests.
|
||||
|
@ -4,7 +4,7 @@ import type {
|
||||
UpdateSystemSavedataRequest,
|
||||
VerifySystemSavedataRequest,
|
||||
VerifySystemSavedataResponse,
|
||||
} from "#types/PokerogueSystemSavedataApi";
|
||||
} from "#types/api/pokerogue-system-save-data-api";
|
||||
|
||||
/**
|
||||
* A wrapper for PokéRogue system savedata API requests.
|
||||
|
@ -57,7 +57,7 @@ import {
|
||||
applySessionVersionMigration,
|
||||
applySettingsVersionMigration,
|
||||
applySystemVersionMigration,
|
||||
} from "#system/version_converter";
|
||||
} from "#system/version-migration/version-converter";
|
||||
import { VoucherType, vouchers } from "#system/voucher";
|
||||
import { trainerConfigs } from "#trainers/trainer-config";
|
||||
import type { DexData, DexEntry } from "#types/dex-data";
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
import { version } from "#package.json";
|
||||
import type { SessionSaveData, SystemSaveData } from "#system/game-data";
|
||||
import type { SessionSaveMigrator } from "#types/SessionSaveMigrator";
|
||||
import type { SettingsSaveMigrator } from "#types/SettingsSaveMigrator";
|
||||
import type { SystemSaveMigrator } from "#types/SystemSaveMigrator";
|
||||
import type { SessionSaveMigrator } from "#types/session-save-migrator";
|
||||
import type { SettingsSaveMigrator } from "#types/settings-save-migrator";
|
||||
import type { SystemSaveMigrator } from "#types/system-save-migrator";
|
||||
import { compareVersions } from "compare-versions";
|
||||
|
||||
/*
|
||||
@ -49,11 +49,11 @@ export const settingsMigrators: readonly SettingsSaveMigrator[] = [settingsMigra
|
||||
// Add migrator imports below:
|
||||
// Example: import * as vA_B_C from "#system/vA_B_C";
|
||||
|
||||
import * as v1_0_4 from "#system/v1_0_4";
|
||||
import * as v1_7_0 from "#system/v1_7_0";
|
||||
import * as v1_8_3 from "#system/v1_8_3";
|
||||
import * as v1_9_0 from "#system/v1_9_0";
|
||||
import * as v1_10_0 from "#system/v1_10_0";
|
||||
import * as v1_0_4 from "#system/version-migration/versions/v1_0_4";
|
||||
import * as v1_7_0 from "#system/version-migration/versions/v1_7_0";
|
||||
import * as v1_8_3 from "#system/version-migration/versions/v1_8_3";
|
||||
import * as v1_9_0 from "#system/version-migration/versions/v1_9_0";
|
||||
import * as v1_10_0 from "#system/version-migration/versions/v1_10_0";
|
||||
|
||||
/** Current game version */
|
||||
const LATEST_VERSION = version;
|
@ -5,9 +5,9 @@ import { AbilityAttr } from "#enums/ability-attr";
|
||||
import { DexAttr } from "#enums/dex-attr";
|
||||
import type { SessionSaveData, SystemSaveData } from "#system/game-data";
|
||||
import { SettingKeys } from "#system/settings";
|
||||
import type { SessionSaveMigrator } from "#types/SessionSaveMigrator";
|
||||
import type { SettingsSaveMigrator } from "#types/SettingsSaveMigrator";
|
||||
import type { SystemSaveMigrator } from "#types/SystemSaveMigrator";
|
||||
import type { SessionSaveMigrator } from "#types/session-save-migrator";
|
||||
import type { SettingsSaveMigrator } from "#types/settings-save-migrator";
|
||||
import type { SystemSaveMigrator } from "#types/system-save-migrator";
|
||||
import { isNullOrUndefined } from "#utils/common";
|
||||
|
||||
/**
|
@ -3,7 +3,7 @@ import type { MoveId } from "#enums/move-id";
|
||||
import type { MoveResult } from "#enums/move-result";
|
||||
import { MoveUseMode } from "#enums/move-use-mode";
|
||||
import type { SessionSaveData } from "#system/game-data";
|
||||
import type { SessionSaveMigrator } from "#types/SessionSaveMigrator";
|
||||
import type { SessionSaveMigrator } from "#types/session-save-migrator";
|
||||
import type { TurnMove } from "#types/turn-move";
|
||||
|
||||
/** Prior signature of `TurnMove`; used to ensure parity */
|
@ -2,8 +2,8 @@ import { globalScene } from "#app/global-scene";
|
||||
import { getPokemonSpeciesForm } from "#data/pokemon-species";
|
||||
import { DexAttr } from "#enums/dex-attr";
|
||||
import type { SessionSaveData, SystemSaveData } from "#system/game-data";
|
||||
import type { SessionSaveMigrator } from "#types/SessionSaveMigrator";
|
||||
import type { SystemSaveMigrator } from "#types/SystemSaveMigrator";
|
||||
import type { SessionSaveMigrator } from "#types/session-save-migrator";
|
||||
import type { SystemSaveMigrator } from "#types/system-save-migrator";
|
||||
import { isNullOrUndefined } from "#utils/common";
|
||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { DexAttr } from "#enums/dex-attr";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import type { SystemSaveData } from "#system/game-data";
|
||||
import type { SystemSaveMigrator } from "#types/SystemSaveMigrator";
|
||||
import type { SystemSaveMigrator } from "#types/system-save-migrator";
|
||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||
|
||||
/**
|
@ -2,7 +2,7 @@ import { MoveId } from "#enums/move-id";
|
||||
import { PokemonMove } from "#moves/pokemon-move";
|
||||
import type { SessionSaveData } from "#system/game-data";
|
||||
import type { PokemonData } from "#system/pokemon-data";
|
||||
import type { SessionSaveMigrator } from "#types/SessionSaveMigrator";
|
||||
import type { SessionSaveMigrator } from "#types/session-save-migrator";
|
||||
|
||||
/**
|
||||
* Migrate all lingering rage fist data inside `CustomPokemonData`,
|
@ -86,14 +86,14 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
|
||||
private flyoutTextHeaderPlayer: Phaser.GameObjects.Text;
|
||||
/** The {@linkcode Phaser.GameObjects.Text} header used to indicate the enemy's effects */
|
||||
private flyoutTextHeaderEnemy: Phaser.GameObjects.Text;
|
||||
/** The {@linkcode Phaser.GameObjects.Text} header used to indicate neutral effects */
|
||||
/** The {@linkcode Phaser.GameObjects.Text} header used to indicate field effects */
|
||||
private flyoutTextHeaderField: Phaser.GameObjects.Text;
|
||||
|
||||
/** The {@linkcode Phaser.GameObjects.Text} used to indicate the player's effects */
|
||||
private flyoutTextPlayer: Phaser.GameObjects.Text;
|
||||
/** The {@linkcode Phaser.GameObjects.Text} used to indicate the enemy's effects */
|
||||
private flyoutTextEnemy: Phaser.GameObjects.Text;
|
||||
/** The {@linkcode Phaser.GameObjects.Text} used to indicate neutral effects */
|
||||
/** The {@linkcode Phaser.GameObjects.Text} used to indicate field effects */
|
||||
private flyoutTextField: Phaser.GameObjects.Text;
|
||||
|
||||
/** Container for all field effects observed by this object */
|
||||
@ -163,7 +163,7 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
|
||||
this.flyoutTextHeaderField = addTextObject(
|
||||
this.flyoutWidth / 2,
|
||||
5,
|
||||
i18next.t("arenaFlyout:neutral"),
|
||||
i18next.t("arenaFlyout:field"),
|
||||
TextStyle.SUMMARY_GREEN,
|
||||
);
|
||||
this.flyoutTextHeaderField.setFontSize(54);
|
||||
|
@ -4,7 +4,7 @@ import { getTypeDamageMultiplierColor } from "#data/type";
|
||||
import { BattleType } from "#enums/battle-type";
|
||||
import { Button } from "#enums/buttons";
|
||||
import { Command } from "#enums/command";
|
||||
import { MoveCategory } from "#enums/MoveCategory";
|
||||
import { MoveCategory } from "#enums/move-category";
|
||||
import { MoveUseMode } from "#enums/move-use-mode";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import { UiMode } from "#enums/ui-mode";
|
||||
|
@ -2,7 +2,6 @@ import { globalScene } from "#app/global-scene";
|
||||
import { speciesStarterCosts } from "#balance/starters";
|
||||
import { Button } from "#enums/buttons";
|
||||
import { DexAttr } from "#enums/dex-attr";
|
||||
import type { UiMode } from "#enums/ui-mode";
|
||||
import { UiTheme } from "#enums/ui-theme";
|
||||
import type { GameData } from "#system/game-data";
|
||||
import { addTextObject, TextStyle } from "#ui/text";
|
||||
@ -217,152 +216,207 @@ export class GameStatsUiHandler extends UiHandler {
|
||||
private gameStatsContainer: Phaser.GameObjects.Container;
|
||||
private statsContainer: Phaser.GameObjects.Container;
|
||||
|
||||
private statLabels: Phaser.GameObjects.Text[];
|
||||
private statValues: Phaser.GameObjects.Text[];
|
||||
/** The number of rows enabled per page. */
|
||||
private static readonly ROWS_PER_PAGE = 9;
|
||||
|
||||
private statLabels: Phaser.GameObjects.Text[] = [];
|
||||
private statValues: Phaser.GameObjects.Text[] = [];
|
||||
|
||||
private arrowUp: Phaser.GameObjects.Sprite;
|
||||
private arrowDown: Phaser.GameObjects.Sprite;
|
||||
|
||||
constructor(mode: UiMode | null = null) {
|
||||
super(mode);
|
||||
|
||||
this.statLabels = [];
|
||||
this.statValues = [];
|
||||
/** Whether the UI is single column mode */
|
||||
private get singleCol(): boolean {
|
||||
const resolvedLang = i18next.resolvedLanguage ?? "en";
|
||||
// NOTE TO TRANSLATION TEAM: Add more languages that want to display
|
||||
// in a single-column inside of the `[]` (e.g. `["ru", "fr"]`)
|
||||
return ["fr", "es-ES", "es-MX", "it", "ja", "pt-BR", "ru"].includes(resolvedLang);
|
||||
}
|
||||
/** The number of columns used by this menu in the resolved language */
|
||||
private get columnCount(): 1 | 2 {
|
||||
return this.singleCol ? 1 : 2;
|
||||
}
|
||||
|
||||
// #region Columnar-specific properties
|
||||
|
||||
/** The with of each column in the stats view */
|
||||
private get colWidth(): number {
|
||||
return (globalScene.scaledCanvas.width - 2) / this.columnCount;
|
||||
}
|
||||
|
||||
/** THe width of a column's background window */
|
||||
private get colBgWidth(): number {
|
||||
return this.colWidth - 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the `x` position of the stat label based on its index.
|
||||
*
|
||||
* @remarks
|
||||
* Should be used for stat labels (e.g. stat name, not its value). For stat value, use {@linkcode calcTextX}.
|
||||
* @param index - The index of the stat label
|
||||
* @returns The `x` position for the stat label
|
||||
*/
|
||||
private calcLabelX(index: number): number {
|
||||
if (this.singleCol || !(index & 1)) {
|
||||
return 8;
|
||||
}
|
||||
return 8 + (index & 1 ? this.colBgWidth : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the `y` position of the stat label/text based on its index.
|
||||
* @param index - The index of the stat label
|
||||
* @returns The `y` position for the stat label
|
||||
*/
|
||||
private calcEntryY(index: number): number {
|
||||
if (!this.singleCol) {
|
||||
// Floor division by 2 as we want 1 to go to 0
|
||||
index >>= 1;
|
||||
}
|
||||
return 28 + index * 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the `x` position of the stat value based on its index.
|
||||
* @param index - The index of the stat value
|
||||
* @returns The calculated `x` position
|
||||
*/
|
||||
private calcTextX(index: number): number {
|
||||
if (this.singleCol || !(index & 1)) {
|
||||
return this.colBgWidth - 8;
|
||||
}
|
||||
return this.colBgWidth * 2 - 8;
|
||||
}
|
||||
|
||||
/** The number of stats on screen at one time (varies with column count) */
|
||||
private get statsPerPage(): number {
|
||||
return GameStatsUiHandler.ROWS_PER_PAGE * this.columnCount;
|
||||
}
|
||||
|
||||
// #endregion Columnar-specific properties
|
||||
|
||||
setup() {
|
||||
const ui = this.getUi();
|
||||
|
||||
this.gameStatsContainer = globalScene.add.container(1, -(globalScene.game.canvas.height / 6) + 1);
|
||||
/** The scaled width of the global canvas */
|
||||
const sWidth = globalScene.scaledCanvas.width;
|
||||
/** The scaled height of the global canvas */
|
||||
const sHeight = globalScene.scaledCanvas.height;
|
||||
|
||||
const gameStatsContainer = globalScene.add.container(1, -sHeight + 1);
|
||||
this.gameStatsContainer = gameStatsContainer;
|
||||
|
||||
this.gameStatsContainer.setInteractive(
|
||||
new Phaser.Geom.Rectangle(0, 0, globalScene.game.canvas.width / 6, globalScene.game.canvas.height / 6),
|
||||
new Phaser.Geom.Rectangle(0, 0, sWidth, sHeight),
|
||||
Phaser.Geom.Rectangle.Contains,
|
||||
);
|
||||
|
||||
const headerBg = addWindow(0, 0, globalScene.game.canvas.width / 6 - 2, 24);
|
||||
headerBg.setOrigin(0, 0);
|
||||
const headerBg = addWindow(0, 0, sWidth - 2, 24).setOrigin(0);
|
||||
|
||||
const headerText = addTextObject(0, 0, i18next.t("gameStatsUiHandler:stats"), TextStyle.HEADER_LABEL);
|
||||
headerText.setOrigin(0, 0);
|
||||
headerText.setPositionRelative(headerBg, 8, 4);
|
||||
const headerText = addTextObject(0, 0, i18next.t("gameStatsUiHandler:stats"), TextStyle.HEADER_LABEL)
|
||||
.setOrigin(0)
|
||||
.setPositionRelative(headerBg, 8, 4);
|
||||
|
||||
const statsBgWidth = (globalScene.game.canvas.width / 6 - 2) / 2;
|
||||
const [statsBgLeft, statsBgRight] = new Array(2).fill(null).map((_, i) => {
|
||||
const width = statsBgWidth + 2;
|
||||
const height = Math.floor(globalScene.game.canvas.height / 6 - headerBg.height - 2);
|
||||
const statsBg = addWindow(
|
||||
(statsBgWidth - 2) * i,
|
||||
headerBg.height,
|
||||
width,
|
||||
height,
|
||||
false,
|
||||
false,
|
||||
i > 0 ? -3 : 0,
|
||||
1,
|
||||
);
|
||||
statsBg.setOrigin(0, 0);
|
||||
return statsBg;
|
||||
});
|
||||
this.gameStatsContainer.add([headerBg, headerText]);
|
||||
|
||||
this.statsContainer = globalScene.add.container(0, 0);
|
||||
const colWidth = this.colWidth;
|
||||
|
||||
for (let i = 0; i < 18; i++) {
|
||||
const statLabel = addTextObject(
|
||||
8 + (i % 2 === 1 ? statsBgWidth : 0),
|
||||
28 + Math.floor(i / 2) * 16,
|
||||
"",
|
||||
TextStyle.STATS_LABEL,
|
||||
);
|
||||
statLabel.setOrigin(0, 0);
|
||||
this.statsContainer.add(statLabel);
|
||||
this.statLabels.push(statLabel);
|
||||
|
||||
const statValue = addTextObject(statsBgWidth * ((i % 2) + 1) - 8, statLabel.y, "", TextStyle.STATS_VALUE);
|
||||
statValue.setOrigin(1, 0);
|
||||
this.statsContainer.add(statValue);
|
||||
this.statValues.push(statValue);
|
||||
{
|
||||
const columnCount = this.columnCount;
|
||||
const headerHeight = headerBg.height;
|
||||
const statsBgHeight = Math.floor(globalScene.scaledCanvas.height - headerBg.height - 2);
|
||||
const maskOffsetX = columnCount === 1 ? 0 : -3;
|
||||
for (let i = 0; i < columnCount; i++) {
|
||||
gameStatsContainer.add(
|
||||
addWindow(i * this.colBgWidth, headerHeight, colWidth, statsBgHeight, false, false, maskOffsetX, 1, undefined) // formatting
|
||||
.setOrigin(0),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.gameStatsContainer.add(headerBg);
|
||||
this.gameStatsContainer.add(headerText);
|
||||
this.gameStatsContainer.add(statsBgLeft);
|
||||
this.gameStatsContainer.add(statsBgRight);
|
||||
const length = this.statsPerPage;
|
||||
this.statLabels = Array.from({ length }, (_, i) =>
|
||||
addTextObject(this.calcLabelX(i), this.calcEntryY(i), "", TextStyle.STATS_LABEL).setOrigin(0),
|
||||
);
|
||||
|
||||
this.statValues = Array.from({ length }, (_, i) =>
|
||||
addTextObject(this.calcTextX(i), this.calcEntryY(i), "", TextStyle.STATS_VALUE).setOrigin(1, 0),
|
||||
);
|
||||
this.statsContainer = globalScene.add.container(0, 0, [...this.statLabels, ...this.statValues]);
|
||||
|
||||
this.gameStatsContainer.add(this.statsContainer);
|
||||
|
||||
// arrows to show that we can scroll through the stats
|
||||
const isLegacyTheme = globalScene.uiTheme === UiTheme.LEGACY;
|
||||
this.arrowDown = globalScene.add.sprite(
|
||||
statsBgWidth,
|
||||
globalScene.game.canvas.height / 6 - (isLegacyTheme ? 9 : 5),
|
||||
"prompt",
|
||||
);
|
||||
this.gameStatsContainer.add(this.arrowDown);
|
||||
this.arrowUp = globalScene.add.sprite(statsBgWidth, headerBg.height + (isLegacyTheme ? 7 : 3), "prompt");
|
||||
this.arrowUp.flipY = true;
|
||||
this.gameStatsContainer.add(this.arrowUp);
|
||||
const arrowX = this.singleCol ? colWidth / 2 : colWidth;
|
||||
this.arrowDown = globalScene.add.sprite(arrowX, sHeight - (isLegacyTheme ? 9 : 5), "prompt");
|
||||
|
||||
this.arrowUp = globalScene.add
|
||||
.sprite(arrowX, headerBg.height + (isLegacyTheme ? 7 : 3), "prompt") //
|
||||
.setFlipY(true);
|
||||
|
||||
this.gameStatsContainer.add([this.arrowDown, this.arrowUp]);
|
||||
|
||||
ui.add(this.gameStatsContainer);
|
||||
|
||||
this.setCursor(0);
|
||||
|
||||
this.gameStatsContainer.setVisible(false);
|
||||
}
|
||||
|
||||
show(args: any[]): boolean {
|
||||
super.show(args);
|
||||
this.gameStatsContainer.setActive(true).setVisible(true);
|
||||
|
||||
this.setCursor(0);
|
||||
|
||||
this.updateStats();
|
||||
|
||||
this.arrowUp.play("prompt");
|
||||
this.arrowDown.play("prompt");
|
||||
this.arrowUp.setActive(true).play("prompt").setVisible(false);
|
||||
this.arrowDown.setActive(true).play("prompt");
|
||||
/* `setCursor` handles updating stats if the position is different from before.
|
||||
When opening this UI, we want to update stats regardless of the prior position. */
|
||||
if (!this.setCursor(0)) {
|
||||
this.updateStats();
|
||||
}
|
||||
if (globalScene.uiTheme === UiTheme.LEGACY) {
|
||||
this.arrowUp.setTint(0x484848);
|
||||
this.arrowDown.setTint(0x484848);
|
||||
}
|
||||
|
||||
this.updateArrows();
|
||||
|
||||
this.gameStatsContainer.setVisible(true);
|
||||
|
||||
this.getUi().moveTo(this.gameStatsContainer, this.getUi().length - 1);
|
||||
|
||||
this.getUi().hideTooltip();
|
||||
this.getUi()
|
||||
.moveTo(this.gameStatsContainer, this.getUi().length - 1)
|
||||
.hideTooltip();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
updateStats(): void {
|
||||
const statKeys = Object.keys(displayStats).slice(this.cursor * 2, this.cursor * 2 + 18);
|
||||
/**
|
||||
* Update the stat labels and values to reflect the current cursor position.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Invokes each stat's {@linkcode DisplayStat.sourceFunc | sourceFunc} to obtain its value.
|
||||
* Stat labels are shown as `???` if the stat is marked as hidden and its value is zero.
|
||||
*/
|
||||
private updateStats(): void {
|
||||
const perPage = this.statsPerPage;
|
||||
const columns = this.columnCount;
|
||||
const statKeys = Object.keys(displayStats).slice(this.cursor * columns, this.cursor * columns + perPage);
|
||||
statKeys.forEach((key, s) => {
|
||||
const stat = displayStats[key] as DisplayStat;
|
||||
const value = stat.sourceFunc!(globalScene.gameData); // TODO: is this bang correct?
|
||||
const value = stat.sourceFunc?.(globalScene.gameData) ?? "-";
|
||||
const valAsInt = Number.parseInt(value);
|
||||
this.statLabels[s].setText(
|
||||
!stat.hidden || Number.isNaN(Number.parseInt(value)) || Number.parseInt(value)
|
||||
? i18next.t(`gameStatsUiHandler:${stat.label_key}`)
|
||||
: "???",
|
||||
!stat.hidden || Number.isNaN(value) || valAsInt ? i18next.t(`gameStatsUiHandler:${stat.label_key}`) : "???",
|
||||
);
|
||||
this.statValues[s].setText(value);
|
||||
});
|
||||
if (statKeys.length < 18) {
|
||||
for (let s = statKeys.length; s < 18; s++) {
|
||||
this.statLabels[s].setText("");
|
||||
this.statValues[s].setText("");
|
||||
}
|
||||
for (let s = statKeys.length; s < perPage; s++) {
|
||||
this.statLabels[s].setText("");
|
||||
this.statValues[s].setText("");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show arrows at the top / bottom of the page if it's possible to scroll in that direction
|
||||
*/
|
||||
updateArrows(): void {
|
||||
const showUpArrow = this.cursor > 0;
|
||||
this.arrowUp.setVisible(showUpArrow);
|
||||
|
||||
const showDownArrow = this.cursor < Math.ceil((Object.keys(displayStats).length - 18) / 2);
|
||||
this.arrowDown.setVisible(showDownArrow);
|
||||
/** The maximum cursor position */
|
||||
private get maxCursorPos(): number {
|
||||
return Math.ceil((Object.keys(displayStats).length - this.statsPerPage) / this.columnCount);
|
||||
}
|
||||
|
||||
processInput(button: Button): boolean {
|
||||
@ -370,45 +424,59 @@ export class GameStatsUiHandler extends UiHandler {
|
||||
|
||||
let success = false;
|
||||
|
||||
if (button === Button.CANCEL) {
|
||||
success = true;
|
||||
globalScene.ui.revertMode();
|
||||
} else {
|
||||
switch (button) {
|
||||
case Button.UP:
|
||||
if (this.cursor) {
|
||||
success = this.setCursor(this.cursor - 1);
|
||||
}
|
||||
break;
|
||||
case Button.DOWN:
|
||||
if (this.cursor < Math.ceil((Object.keys(displayStats).length - 18) / 2)) {
|
||||
success = this.setCursor(this.cursor + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/** The direction to move the cursor (up/down) */
|
||||
let dir: 1 | -1 = 1;
|
||||
switch (button) {
|
||||
case Button.CANCEL:
|
||||
success = true;
|
||||
globalScene.ui.revertMode();
|
||||
break;
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: intentional
|
||||
case Button.UP:
|
||||
dir = -1;
|
||||
case Button.DOWN:
|
||||
success = this.setCursor(this.cursor + dir);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
ui.playSelect();
|
||||
return true;
|
||||
}
|
||||
|
||||
return success;
|
||||
return false;
|
||||
}
|
||||
|
||||
setCursor(cursor: number): boolean {
|
||||
const ret = super.setCursor(cursor);
|
||||
|
||||
if (ret) {
|
||||
this.updateStats();
|
||||
this.updateArrows();
|
||||
/**
|
||||
* Set the cursor to the specified position, if able and update the stats display.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* If `newCursor` is not between `0` and {@linkcode maxCursorPos}, or if it is the same as {@linkcode newCursor}
|
||||
* then no updates happen and `false` is returned.
|
||||
*
|
||||
* Otherwise, updates the up/down arrow visibility and calls {@linkcode updateStats}
|
||||
*
|
||||
* @param newCursor - The position to set the cursor to.
|
||||
* @returns Whether the cursor successfully moved to a new position
|
||||
*/
|
||||
override setCursor(newCursor: number): boolean {
|
||||
if (newCursor < 0 || newCursor > this.maxCursorPos || this.cursor === newCursor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
this.cursor = newCursor;
|
||||
|
||||
this.updateStats();
|
||||
// NOTE: Do not toggle the arrows' "active" property here, as this would cause their animations to desync
|
||||
this.arrowUp.setVisible(this.cursor > 0);
|
||||
this.arrowDown.setVisible(this.cursor < this.maxCursorPos);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
clear() {
|
||||
super.clear();
|
||||
this.gameStatsContainer.setVisible(false);
|
||||
this.gameStatsContainer.setVisible(false).setActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,12 +273,23 @@ export class ModifierSelectUiHandler extends AwaitableUiHandler {
|
||||
// causing errors if reroll is selected
|
||||
this.awaitingActionInput = false;
|
||||
|
||||
// TODO: Replace with `Promise.withResolvers` when possible.
|
||||
let tweenResolve: () => void;
|
||||
const tweenPromise = new Promise<void>(resolve => (tweenResolve = resolve));
|
||||
const { promise: tweenPromise, resolve: tweenResolve } = Promise.withResolvers<void>();
|
||||
let i = 0;
|
||||
|
||||
// TODO: Rework this bespoke logic for animating the modifier options.
|
||||
// #region: animation
|
||||
/** Holds promises that resolve once each reward's *upgrade animation* has finished playing */
|
||||
const rewardAnimPromises: Promise<void>[] = [];
|
||||
/** Holds promises that resolves once *all* animations for a reward have finished playing */
|
||||
const rewardAnimAllSettledPromises: Promise<void>[] = [];
|
||||
|
||||
/*
|
||||
* A counter here is used instead of a loop to "stagger" the apperance of each reward,
|
||||
* using `sine.easeIn` to speed up the appearance of the rewards as each animation progresses.
|
||||
*
|
||||
* The `onComplete` callback for this tween is set to resolve once the upgrade animations
|
||||
* for each reward has finished playing, allowing for the next set of animations to
|
||||
* start to appear.
|
||||
*/
|
||||
globalScene.tweens.addCounter({
|
||||
ease: "Sine.easeIn",
|
||||
duration: 1250,
|
||||
@ -288,30 +299,35 @@ export class ModifierSelectUiHandler extends AwaitableUiHandler {
|
||||
const index = Math.floor(value * typeOptions.length);
|
||||
if (index > i && index <= typeOptions.length) {
|
||||
const option = this.options[i];
|
||||
option?.show(
|
||||
Math.floor((1 - value) * 1250) * 0.325 + 2000 * maxUpgradeCount,
|
||||
-(maxUpgradeCount - typeOptions[i].upgradeCount),
|
||||
);
|
||||
if (option) {
|
||||
rewardAnimPromises.push(
|
||||
option.show(
|
||||
Math.floor((1 - value) * 1250) * 0.325 + 2000 * maxUpgradeCount,
|
||||
-(maxUpgradeCount - typeOptions[i].upgradeCount),
|
||||
rewardAnimAllSettledPromises,
|
||||
),
|
||||
);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
},
|
||||
onComplete: () => {
|
||||
tweenResolve();
|
||||
Promise.allSettled(rewardAnimPromises).then(() => tweenResolve());
|
||||
},
|
||||
});
|
||||
|
||||
let shopResolve: () => void;
|
||||
const shopPromise = new Promise<void>(resolve => (shopResolve = resolve));
|
||||
tweenPromise.then(() => {
|
||||
globalScene.time.delayedCall(1000, () => {
|
||||
for (const shopOption of this.shopOptionsRows.flat()) {
|
||||
shopOption.show(0, 0);
|
||||
}
|
||||
shopResolve();
|
||||
});
|
||||
/** Holds promises that resolve once each shop item has finished animating */
|
||||
const shopAnimPromises: Promise<void>[] = [];
|
||||
globalScene.time.delayedCall(1000 + maxUpgradeCount * 2000, () => {
|
||||
for (const shopOption of this.shopOptionsRows.flat()) {
|
||||
// It is safe to skip awaiting the `show` method here,
|
||||
// as the promise it returns is also part of the promise appended to `shopAnimPromises`,
|
||||
// which is awaited later on.
|
||||
shopOption.show(0, 0, shopAnimPromises, false);
|
||||
}
|
||||
});
|
||||
|
||||
shopPromise.then(() => {
|
||||
tweenPromise.then(() => {
|
||||
globalScene.time.delayedCall(500, () => {
|
||||
if (partyHasHeldItem) {
|
||||
this.transferButtonContainer.setAlpha(0);
|
||||
@ -344,31 +360,39 @@ export class ModifierSelectUiHandler extends AwaitableUiHandler {
|
||||
duration: 250,
|
||||
});
|
||||
|
||||
const updateCursorTarget = () => {
|
||||
if (globalScene.shopCursorTarget === ShopCursorTarget.CHECK_TEAM) {
|
||||
this.setRowCursor(0);
|
||||
this.setCursor(2);
|
||||
} else if (globalScene.shopCursorTarget === ShopCursorTarget.SHOP && globalScene.gameMode.hasNoShop) {
|
||||
this.setRowCursor(ShopCursorTarget.REWARDS);
|
||||
this.setCursor(0);
|
||||
} else {
|
||||
this.setRowCursor(globalScene.shopCursorTarget);
|
||||
this.setCursor(0);
|
||||
}
|
||||
};
|
||||
// Ensure that the reward animations have completed before allowing input to proceed.
|
||||
// Required to ensure that the user cannot interact with the UI before the animations
|
||||
// have completed, (which, among other things, would allow the GameObjects to be destroyed
|
||||
// before the animations have completed, causing errors).
|
||||
Promise.allSettled([...shopAnimPromises, ...rewardAnimAllSettledPromises]).then(() => {
|
||||
const updateCursorTarget = () => {
|
||||
if (globalScene.shopCursorTarget === ShopCursorTarget.CHECK_TEAM) {
|
||||
this.setRowCursor(0);
|
||||
this.setCursor(2);
|
||||
} else if (globalScene.shopCursorTarget === ShopCursorTarget.SHOP && globalScene.gameMode.hasNoShop) {
|
||||
this.setRowCursor(ShopCursorTarget.REWARDS);
|
||||
this.setCursor(0);
|
||||
} else {
|
||||
this.setRowCursor(globalScene.shopCursorTarget);
|
||||
this.setCursor(0);
|
||||
}
|
||||
};
|
||||
|
||||
updateCursorTarget();
|
||||
updateCursorTarget();
|
||||
|
||||
handleTutorial(Tutorial.Select_Item).then(res => {
|
||||
if (res) {
|
||||
updateCursorTarget();
|
||||
}
|
||||
this.awaitingActionInput = true;
|
||||
this.onActionInput = args[2];
|
||||
handleTutorial(Tutorial.Select_Item).then(res => {
|
||||
if (res) {
|
||||
updateCursorTarget();
|
||||
}
|
||||
this.awaitingActionInput = true;
|
||||
this.onActionInput = args[2];
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// #endregion: animation
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -820,14 +844,45 @@ class ModifierOption extends Phaser.GameObjects.Container {
|
||||
}
|
||||
}
|
||||
|
||||
show(remainingDuration: number, upgradeCountOffset: number) {
|
||||
if (!this.modifierTypeOption.cost) {
|
||||
/**
|
||||
* Start the tweens responsible for animating the option's appearance
|
||||
*
|
||||
* @privateremarks
|
||||
* This method is unusual. It "returns" (one via the actual return, one by via appending to the `promiseHolder`
|
||||
* parameter) two promises. The promise returned by the method resolves once the option's appearance animations have
|
||||
* completed, and is meant to allow callers to synchronize with the completion of the option's appearance animations.
|
||||
* The promise appended to `promiseHolder` resolves once *all* animations started by this method have completed,
|
||||
* and should be used by callers to ensure that all animations have completed before proceeding.
|
||||
*
|
||||
* @param remainingDuration - The duration in milliseconds that the animation can play for
|
||||
* @param upgradeCountOffset - The offset to apply to the upgrade count for options whose rarity is being upgraded
|
||||
* @param promiseHolder - A promise that resolves once all tweens started by this method have completed will be pushed to this array.
|
||||
* @param isReward - Whether the option being shown is a reward, meaning it should show pokeball and upgrade animations.
|
||||
* @returns A promise that resolves once the *option's apperance animations* have completed. This promise will resolve _before_ all
|
||||
* promises that are initiated in this method complete. Instead, the `promiseHolder` array will contain a new promise
|
||||
* that will resolve once all animations have completed.
|
||||
*
|
||||
*/
|
||||
async show(
|
||||
remainingDuration: number,
|
||||
upgradeCountOffset: number,
|
||||
promiseHolder: Promise<void>[],
|
||||
isReward = true,
|
||||
): Promise<void> {
|
||||
/** Promises for the pokeball and upgrade animations */
|
||||
const animPromises: Promise<void>[] = [];
|
||||
if (isReward) {
|
||||
const { promise: bouncePromise, resolve: resolveBounce } = Promise.withResolvers<void>();
|
||||
globalScene.tweens.add({
|
||||
targets: this.pb,
|
||||
y: 0,
|
||||
duration: 1250,
|
||||
ease: "Bounce.Out",
|
||||
onComplete: () => {
|
||||
resolveBounce();
|
||||
},
|
||||
});
|
||||
animPromises.push(bouncePromise);
|
||||
|
||||
let lastValue = 1;
|
||||
let bounceCount = 0;
|
||||
@ -857,7 +912,9 @@ class ModifierOption extends Phaser.GameObjects.Container {
|
||||
|
||||
// TODO: Figure out proper delay between chains and then convert this into a single tween chain
|
||||
// rather than starting multiple tween chains.
|
||||
|
||||
for (let u = 0; u < this.modifierTypeOption.upgradeCount; u++) {
|
||||
const { resolve, promise } = Promise.withResolvers<void>();
|
||||
globalScene.tweens.chain({
|
||||
tweens: [
|
||||
{
|
||||
@ -883,65 +940,99 @@ class ModifierOption extends Phaser.GameObjects.Container {
|
||||
ease: "Sine.easeOut",
|
||||
onComplete: () => {
|
||||
this.pbTint.setVisible(false);
|
||||
resolve();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
animPromises.push(promise);
|
||||
}
|
||||
}
|
||||
|
||||
const finalPromises: Promise<void>[] = [];
|
||||
globalScene.time.delayedCall(remainingDuration + 2000, () => {
|
||||
if (!globalScene) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.modifierTypeOption.cost) {
|
||||
if (isReward) {
|
||||
this.pb.setTexture("pb", `${this.getPbAtlasKey(0)}_open`);
|
||||
globalScene.playSound("se/pb_rel");
|
||||
|
||||
const { resolve: pbResolve, promise: pbPromise } = Promise.withResolvers<void>();
|
||||
|
||||
globalScene.tweens.add({
|
||||
targets: this.pb,
|
||||
duration: 500,
|
||||
delay: 250,
|
||||
ease: "Sine.easeIn",
|
||||
alpha: 0,
|
||||
onComplete: () => this.pb.destroy(),
|
||||
onComplete: () => {
|
||||
Promise.allSettled(animPromises).then(() => this.pb.destroy());
|
||||
pbResolve();
|
||||
},
|
||||
});
|
||||
finalPromises.push(pbPromise);
|
||||
}
|
||||
|
||||
/** Delay for the rest of the tweens to ensure they show after the pokeball animation begins to appear */
|
||||
const delay = isReward ? 250 : 0;
|
||||
|
||||
const { resolve: itemResolve, promise: itemPromise } = Promise.withResolvers<void>();
|
||||
globalScene.tweens.add({
|
||||
targets: this.itemContainer,
|
||||
delay,
|
||||
duration: 500,
|
||||
ease: "Elastic.Out",
|
||||
scale: 2,
|
||||
alpha: 1,
|
||||
onComplete: () => {
|
||||
itemResolve();
|
||||
},
|
||||
});
|
||||
if (!this.modifierTypeOption.cost) {
|
||||
finalPromises.push(itemPromise);
|
||||
|
||||
if (isReward) {
|
||||
const { resolve: itemTintResolve, promise: itemTintPromise } = Promise.withResolvers<void>();
|
||||
globalScene.tweens.add({
|
||||
targets: this.itemTint,
|
||||
alpha: 0,
|
||||
delay,
|
||||
duration: 500,
|
||||
ease: "Sine.easeIn",
|
||||
onComplete: () => this.itemTint.destroy(),
|
||||
onComplete: () => {
|
||||
this.itemTint.destroy();
|
||||
itemTintResolve();
|
||||
},
|
||||
});
|
||||
finalPromises.push(itemTintPromise);
|
||||
}
|
||||
|
||||
const { resolve: itemTextResolve, promise: itemTextPromise } = Promise.withResolvers<void>();
|
||||
globalScene.tweens.add({
|
||||
targets: this.itemText,
|
||||
delay,
|
||||
duration: 500,
|
||||
alpha: 1,
|
||||
y: 25,
|
||||
ease: "Cubic.easeInOut",
|
||||
onComplete: () => itemTextResolve(),
|
||||
});
|
||||
finalPromises.push(itemTextPromise);
|
||||
|
||||
if (this.itemCostText) {
|
||||
const { resolve: itemCostResolve, promise: itemCostPromise } = Promise.withResolvers<void>();
|
||||
globalScene.tweens.add({
|
||||
targets: this.itemCostText,
|
||||
delay,
|
||||
duration: 500,
|
||||
alpha: 1,
|
||||
y: 35,
|
||||
ease: "Cubic.easeInOut",
|
||||
onComplete: () => itemCostResolve(),
|
||||
});
|
||||
finalPromises.push(itemCostPromise);
|
||||
}
|
||||
});
|
||||
// The `.then` suppresses the return type for the Promise.allSettled so that it returns void.
|
||||
promiseHolder.push(Promise.allSettled([...animPromises, ...finalPromises]).then());
|
||||
|
||||
await Promise.allSettled(animPromises);
|
||||
}
|
||||
|
||||
getPbAtlasKey(tierOffset = 0) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { InfoToggle } from "#app/battle-scene";
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { MoveCategory } from "#enums/MoveCategory";
|
||||
import { MoveCategory } from "#enums/move-category";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
import type { Move } from "#moves/move";
|
||||
import { addTextObject, TextStyle } from "#ui/text";
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { Button } from "#enums/buttons";
|
||||
import type { UiMode } from "#enums/ui-mode";
|
||||
import { NavigationManager } from "#ui/navigationMenu";
|
||||
import { NavigationManager } from "#ui/navigation-menu";
|
||||
import { addTextObject, TextStyle } from "#ui/text";
|
||||
import { UiHandler } from "#ui/ui-handler";
|
||||
import { addWindow } from "#ui/ui-theme";
|
||||
|
@ -3,8 +3,8 @@ import type { InterfaceConfig } from "#app/inputs-controller";
|
||||
import { Button } from "#enums/buttons";
|
||||
import type { Device } from "#enums/devices";
|
||||
import type { UiMode } from "#enums/ui-mode";
|
||||
import { getIconWithSettingName } from "#inputs/configHandler";
|
||||
import { NavigationManager, NavigationMenu } from "#ui/navigationMenu";
|
||||
import { getIconWithSettingName } from "#inputs/config-handler";
|
||||
import { NavigationManager, NavigationMenu } from "#ui/navigation-menu";
|
||||
import { ScrollBar } from "#ui/scroll-bar";
|
||||
import { addTextObject, TextStyle } from "#ui/text";
|
||||
import { UiHandler } from "#ui/ui-handler";
|
||||
|
@ -5,7 +5,7 @@ import type { SettingType } from "#system/settings";
|
||||
import { Setting, SettingKeys } from "#system/settings";
|
||||
import type { InputsIcons } from "#ui/abstract-control-settings-ui-handler";
|
||||
import { MessageUiHandler } from "#ui/message-ui-handler";
|
||||
import { NavigationManager, NavigationMenu } from "#ui/navigationMenu";
|
||||
import { NavigationManager, NavigationMenu } from "#ui/navigation-menu";
|
||||
import { ScrollBar } from "#ui/scroll-bar";
|
||||
import { addTextObject, TextStyle } from "#ui/text";
|
||||
import { addWindow } from "#ui/ui-theme";
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { Device } from "#enums/devices";
|
||||
import type { UiMode } from "#enums/ui-mode";
|
||||
import { getIconWithSettingName, getKeyWithKeycode } from "#inputs/configHandler";
|
||||
import { getIconWithSettingName, getKeyWithKeycode } from "#inputs/config-handler";
|
||||
import { AbstractBindingUiHandler } from "#ui/abstract-binding-ui-handler";
|
||||
import { addTextObject, TextStyle } from "#ui/text";
|
||||
import i18next from "i18next";
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { Device } from "#enums/devices";
|
||||
import type { UiMode } from "#enums/ui-mode";
|
||||
import { getKeyWithKeycode } from "#inputs/configHandler";
|
||||
import { getKeyWithKeycode } from "#inputs/config-handler";
|
||||
import { AbstractBindingUiHandler } from "#ui/abstract-binding-ui-handler";
|
||||
import { addTextObject, TextStyle } from "#ui/text";
|
||||
import i18next from "i18next";
|
||||
|
@ -2,9 +2,9 @@ import { globalScene } from "#app/global-scene";
|
||||
import type { InterfaceConfig } from "#app/inputs-controller";
|
||||
import { Device } from "#enums/devices";
|
||||
import type { UiMode } from "#enums/ui-mode";
|
||||
import pad_dualshock from "#inputs/pad_dualshock";
|
||||
import pad_unlicensedSNES from "#inputs/pad_unlicensedSNES";
|
||||
import pad_xbox360 from "#inputs/pad_xbox360";
|
||||
import pad_dualshock from "#inputs/pad-dualshock";
|
||||
import pad_unlicensedSNES from "#inputs/pad-unlicensed-snes";
|
||||
import pad_xbox360 from "#inputs/pad-xbox360";
|
||||
import {
|
||||
SettingGamepad,
|
||||
setSettingGamepad,
|
||||
|
@ -2,8 +2,8 @@ import { globalScene } from "#app/global-scene";
|
||||
import type { InterfaceConfig } from "#app/inputs-controller";
|
||||
import { Device } from "#enums/devices";
|
||||
import { UiMode } from "#enums/ui-mode";
|
||||
import cfg_keyboard_qwerty from "#inputs/cfg_keyboard_qwerty";
|
||||
import { deleteBind } from "#inputs/configHandler";
|
||||
import cfg_keyboard_qwerty from "#inputs/cfg-keyboard-qwerty";
|
||||
import { deleteBind } from "#inputs/config-handler";
|
||||
import {
|
||||
SettingKeyboard,
|
||||
setSettingKeyboard,
|
||||
@ -12,7 +12,7 @@ import {
|
||||
settingKeyboardOptions,
|
||||
} from "#system/settings-keyboard";
|
||||
import { AbstractControlSettingsUiHandler } from "#ui/abstract-control-settings-ui-handler";
|
||||
import { NavigationManager } from "#ui/navigationMenu";
|
||||
import { NavigationManager } from "#ui/navigation-menu";
|
||||
import { addTextObject, TextStyle } from "#ui/text";
|
||||
import { reverseValueToKeySetting, truncateString } from "#utils/common";
|
||||
import i18next from "i18next";
|
||||
|
@ -1,41 +0,0 @@
|
||||
{
|
||||
"textures": [
|
||||
{
|
||||
"image": "shiny_icons.png",
|
||||
"format": "RGBA8888",
|
||||
"size": {
|
||||
"w": 45,
|
||||
"h": 14
|
||||
},
|
||||
"scale": 1,
|
||||
"frames": [
|
||||
{
|
||||
"filename": "0",
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"sourceSize": {
|
||||
"w": 45,
|
||||
"h": 14
|
||||
},
|
||||
"spriteSourceSize": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 15,
|
||||
"h": 14
|
||||
},
|
||||
"frame": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 15,
|
||||
"h": 14
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "https://www.codeandweb.com/texturepacker",
|
||||
"version": "3.0",
|
||||
"smartupdate": "$TexturePacker:SmartUpdate:a3275c7504a9b35b288265e191b1d14c:420725f3fb73c2cac0ab3bbc0a46f2e1:3a8b8ca0f0e4be067dd46c07b78ee013$"
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ import { getNatureName, getNatureStatMultiplier } from "#data/nature";
|
||||
import { getPokeballAtlasKey } from "#data/pokeball";
|
||||
import { getTypeRgb } from "#data/type";
|
||||
import { Button } from "#enums/buttons";
|
||||
import { MoveCategory } from "#enums/MoveCategory";
|
||||
import { MoveCategory } from "#enums/move-category";
|
||||
import { Nature } from "#enums/nature";
|
||||
import { PlayerGender } from "#enums/player-gender";
|
||||
import { PokemonType } from "#enums/pokemon-type";
|
||||
|
@ -29,7 +29,7 @@ import { MenuUiHandler } from "#ui/menu-ui-handler";
|
||||
import { MessageUiHandler } from "#ui/message-ui-handler";
|
||||
import { ModifierSelectUiHandler } from "#ui/modifier-select-ui-handler";
|
||||
import { MysteryEncounterUiHandler } from "#ui/mystery-encounter-ui-handler";
|
||||
import { NavigationManager } from "#ui/navigationMenu";
|
||||
import { NavigationManager } from "#ui/navigation-menu";
|
||||
import { OptionSelectUiHandler } from "#ui/option-select-ui-handler";
|
||||
import { PartyUiHandler } from "#ui/party-ui-handler";
|
||||
import { PokedexPageUiHandler } from "#ui/pokedex-page-ui-handler";
|
||||
|
@ -3,7 +3,7 @@ import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { WeatherType } from "#enums/weather-type";
|
||||
import { GameManager } from "#test/testUtils/gameManager";
|
||||
import { GameManager } from "#test/test-utils/game-manager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
@ -2,7 +2,7 @@ import { AbilityId } from "#enums/ability-id";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { GameManager } from "#test/testUtils/gameManager";
|
||||
import { GameManager } from "#test/test-utils/game-manager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
@ -5,7 +5,7 @@ import { UiMode } from "#enums/ui-mode";
|
||||
import { CommandPhase } from "#phases/command-phase";
|
||||
import { TurnInitPhase } from "#phases/turn-init-phase";
|
||||
import i18next from "#plugins/i18n";
|
||||
import { GameManager } from "#test/testUtils/gameManager";
|
||||
import { GameManager } from "#test/test-utils/game-manager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
@ -2,7 +2,7 @@ import { AbilityId } from "#enums/ability-id";
|
||||
import { BattlerIndex } from "#enums/battler-index";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { GameManager } from "#test/testUtils/gameManager";
|
||||
import { GameManager } from "#test/test-utils/game-manager";
|
||||
import { isBetween, toDmgValue } from "#utils/common";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
@ -3,7 +3,7 @@ import { AbilityId } from "#enums/ability-id";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { Stat } from "#enums/stat";
|
||||
import { GameManager } from "#test/testUtils/gameManager";
|
||||
import { GameManager } from "#test/test-utils/game-manager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { allAbilities } from "#data/data-lists";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { GameManager } from "#test/testUtils/gameManager";
|
||||
import { GameManager } from "#test/test-utils/game-manager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
@ -5,7 +5,7 @@ import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import type { PlayerPokemon } from "#field/pokemon";
|
||||
import { GameManager } from "#test/testUtils/gameManager";
|
||||
import { GameManager } from "#test/test-utils/game-manager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
@ -2,7 +2,7 @@ import { allMoves } from "#data/data-lists";
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { GameManager } from "#test/testUtils/gameManager";
|
||||
import { GameManager } from "#test/test-utils/game-manager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
@ -4,7 +4,7 @@ import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { MoveEffectPhase } from "#phases/move-effect-phase";
|
||||
import { TurnEndPhase } from "#phases/turn-end-phase";
|
||||
import { GameManager } from "#test/testUtils/gameManager";
|
||||
import { GameManager } from "#test/test-utils/game-manager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user