mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-06 15:39:27 +02:00
Merge branch 'beta' into workflow-dispatch
This commit is contained in:
commit
fffe9553bb
@ -11,17 +11,18 @@ _cfg: &cfg
|
|||||||
|
|
||||||
ls:
|
ls:
|
||||||
<<: *cfg
|
<<: *cfg
|
||||||
src:
|
src: &src
|
||||||
<<: *cfg
|
<<: *cfg
|
||||||
.dir: kebab-case | regex:@types
|
.dir: kebab-case | regex:@types
|
||||||
.js: exists:0
|
.js: exists:0
|
||||||
src/system/version-migration/versions:
|
src/system/version-migration/versions:
|
||||||
.ts: snake_case
|
.ts: snake_case
|
||||||
<<: *cfg
|
<<: *cfg
|
||||||
|
test: *src
|
||||||
ignore:
|
ignore:
|
||||||
- node_modules
|
- node_modules
|
||||||
- .vscode
|
- .vscode
|
||||||
- .github
|
- .github
|
||||||
- .git
|
- .git
|
||||||
- public
|
- public
|
||||||
|
- dist
|
||||||
|
@ -177,9 +177,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Overrides to prevent unused import removal inside `overrides.ts` and enums files (for TSDoc linkcodes)
|
// Overrides to prevent unused import removal inside `overrides.ts` and enums files (for TSDoc linkcodes),
|
||||||
|
// as well as in all TS files in `scripts/` (which are assumed to be boilerplate templates).
|
||||||
{
|
{
|
||||||
"includes": ["**/src/overrides.ts", "**/src/enums/**/*"],
|
"includes": ["**/src/overrides.ts", "**/src/enums/**/*", "**/scripts/**/*.ts"],
|
||||||
"linter": {
|
"linter": {
|
||||||
"rules": {
|
"rules": {
|
||||||
"correctness": {
|
"correctness": {
|
||||||
@ -189,7 +190,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"includes": ["**/src/overrides.ts"],
|
"includes": ["**/src/overrides.ts", "**/scripts/**/*.ts"],
|
||||||
"linter": {
|
"linter": {
|
||||||
"rules": {
|
"rules": {
|
||||||
"style": {
|
"style": {
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
"@types/jsdom": "^21.1.7",
|
"@types/jsdom": "^21.1.7",
|
||||||
"@types/node": "^22.16.3",
|
"@types/node": "^22.16.3",
|
||||||
"@vitest/coverage-istanbul": "^3.2.4",
|
"@vitest/coverage-istanbul": "^3.2.4",
|
||||||
|
"@vitest/expect": "^3.2.4",
|
||||||
"chalk": "^5.4.1",
|
"chalk": "^5.4.1",
|
||||||
"dependency-cruiser": "^16.10.4",
|
"dependency-cruiser": "^16.10.4",
|
||||||
"inquirer": "^12.7.0",
|
"inquirer": "^12.7.0",
|
||||||
|
@ -57,6 +57,9 @@ importers:
|
|||||||
'@vitest/coverage-istanbul':
|
'@vitest/coverage-istanbul':
|
||||||
specifier: ^3.2.4
|
specifier: ^3.2.4
|
||||||
version: 3.2.4(vitest@3.2.4(@types/node@22.16.3)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.3)(typescript@5.8.3))(yaml@2.8.0))
|
version: 3.2.4(vitest@3.2.4(@types/node@22.16.3)(jsdom@26.1.0)(msw@2.10.4(@types/node@22.16.3)(typescript@5.8.3))(yaml@2.8.0))
|
||||||
|
'@vitest/expect':
|
||||||
|
specifier: ^3.2.4
|
||||||
|
version: 3.2.4
|
||||||
chalk:
|
chalk:
|
||||||
specifier: ^5.4.1
|
specifier: ^5.4.1
|
||||||
version: 5.4.1
|
version: 5.4.1
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 362b2c4fcc20b31a7be6c2dab537055fbaeb247f
|
Subproject commit e2fbba17ea7a96068970ea98a8a84ed3e25b6f07
|
@ -44,20 +44,22 @@ function getTestFolderPath(...folders) {
|
|||||||
* @returns {Promise<{selectedOption: {label: string, dir: string}}>} the selected type
|
* @returns {Promise<{selectedOption: {label: string, dir: string}}>} the selected type
|
||||||
*/
|
*/
|
||||||
async function promptTestType() {
|
async function promptTestType() {
|
||||||
const typeAnswer = await inquirer.prompt([
|
const typeAnswer = await inquirer
|
||||||
{
|
.prompt([
|
||||||
type: "list",
|
{
|
||||||
name: "selectedOption",
|
type: "list",
|
||||||
message: "What type of test would you like to create?",
|
name: "selectedOption",
|
||||||
choices: [...choices.map(choice => ({ name: choice.label, value: choice })), "EXIT"],
|
message: "What type of test would you like to create?",
|
||||||
},
|
choices: [...choices.map(choice => ({ name: choice.label, value: choice })), { name: "EXIT", value: "N/A" }],
|
||||||
]);
|
},
|
||||||
|
])
|
||||||
|
.then(ans => ans.selectedOption);
|
||||||
|
|
||||||
if (typeAnswer.selectedOption === "EXIT") {
|
if (typeAnswer.name === "EXIT") {
|
||||||
console.log("Exiting...");
|
console.log("Exiting...");
|
||||||
return process.exit();
|
return process.exit(0);
|
||||||
}
|
}
|
||||||
if (!choices.some(choice => choice.dir === typeAnswer.selectedOption.dir)) {
|
if (!choices.some(choice => choice.dir === typeAnswer.dir)) {
|
||||||
console.error(`Please provide a valid type: (${choices.map(choice => choice.label).join(", ")})!`);
|
console.error(`Please provide a valid type: (${choices.map(choice => choice.label).join(", ")})!`);
|
||||||
return await promptTestType();
|
return await promptTestType();
|
||||||
}
|
}
|
||||||
|
@ -8,20 +8,14 @@ import type { Variant } from "#sprites/variant";
|
|||||||
* Data pertaining to a Pokemon's Illusion.
|
* Data pertaining to a Pokemon's Illusion.
|
||||||
*/
|
*/
|
||||||
export interface IllusionData {
|
export interface IllusionData {
|
||||||
basePokemon: {
|
/** The name of pokemon featured in the illusion */
|
||||||
/** The actual name of the Pokemon */
|
name: string;
|
||||||
name: string;
|
/** The nickname of the pokemon featured in the illusion */
|
||||||
/** The actual nickname of the Pokemon */
|
nickname: string;
|
||||||
nickname: string;
|
/** Whether the pokemon featured in the illusion is shiny or not */
|
||||||
/** Whether the base pokemon is shiny or not */
|
shiny: boolean;
|
||||||
shiny: boolean;
|
/** The variant of the pokemon featured in the illusion */
|
||||||
/** The shiny variant of the base pokemon */
|
variant: Variant;
|
||||||
variant: Variant;
|
|
||||||
/** Whether the fusion species of the base pokemon is shiny or not */
|
|
||||||
fusionShiny: boolean;
|
|
||||||
/** The variant of the fusion species of the base pokemon */
|
|
||||||
fusionVariant: Variant;
|
|
||||||
};
|
|
||||||
/** The species of the illusion */
|
/** The species of the illusion */
|
||||||
species: SpeciesId;
|
species: SpeciesId;
|
||||||
/** The formIndex of the illusion */
|
/** The formIndex of the illusion */
|
||||||
@ -34,6 +28,10 @@ export interface IllusionData {
|
|||||||
fusionSpecies?: PokemonSpecies;
|
fusionSpecies?: PokemonSpecies;
|
||||||
/** The fusionFormIndex of the illusion */
|
/** The fusionFormIndex of the illusion */
|
||||||
fusionFormIndex?: number;
|
fusionFormIndex?: number;
|
||||||
|
/** Whether the fusion species of the pokemon featured in the illusion is shiny or not */
|
||||||
|
fusionShiny?: boolean;
|
||||||
|
/** The variant of the fusion species of the pokemon featured in the illusion */
|
||||||
|
fusionVariant?: Variant;
|
||||||
/** The fusionGender of the illusion if it's a fusion */
|
/** The fusionGender of the illusion if it's a fusion */
|
||||||
fusionGender?: Gender;
|
fusionGender?: Gender;
|
||||||
/** The level of the illusion (not used currently) */
|
/** The level of the illusion (not used currently) */
|
||||||
|
@ -75,3 +75,14 @@ export type NonFunctionPropertiesRecursive<Class> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type AbstractConstructor<T> = abstract new (...args: any[]) => T;
|
export type AbstractConstructor<T> = abstract new (...args: any[]) => T;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type helper that iterates through the fields of the type and coerces any `null` properties to `undefined` (including in union types).
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* This is primarily useful when an object with nullable properties wants to be serialized and have its `null`
|
||||||
|
* properties coerced to `undefined`.
|
||||||
|
*/
|
||||||
|
export type CoerceNullPropertiesToUndefined<T extends object> = {
|
||||||
|
[K in keyof T]: null extends T[K] ? Exclude<T[K], null> | undefined : T[K];
|
||||||
|
};
|
||||||
|
10
src/@types/ui.ts
Normal file
10
src/@types/ui.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import type Phaser from "phaser";
|
||||||
|
import type InputText from "phaser3-rex-plugins/plugins/gameobjects/dom/inputtext/InputText";
|
||||||
|
|
||||||
|
export interface TextStyleOptions {
|
||||||
|
scale: number;
|
||||||
|
styleOptions: Phaser.Types.GameObjects.Text.TextStyle | InputText.IConfig;
|
||||||
|
shadowColor: string;
|
||||||
|
shadowXpos: number;
|
||||||
|
shadowYpos: number;
|
||||||
|
}
|
@ -67,6 +67,7 @@ import { PokemonType } from "#enums/pokemon-type";
|
|||||||
import { ShopCursorTarget } from "#enums/shop-cursor-target";
|
import { ShopCursorTarget } from "#enums/shop-cursor-target";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { TrainerSlot } from "#enums/trainer-slot";
|
import type { TrainerSlot } from "#enums/trainer-slot";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { TrainerVariant } from "#enums/trainer-variant";
|
import { TrainerVariant } from "#enums/trainer-variant";
|
||||||
@ -132,7 +133,7 @@ import { CharSprite } from "#ui/char-sprite";
|
|||||||
import { PartyExpBar } from "#ui/party-exp-bar";
|
import { PartyExpBar } from "#ui/party-exp-bar";
|
||||||
import { PokeballTray } from "#ui/pokeball-tray";
|
import { PokeballTray } from "#ui/pokeball-tray";
|
||||||
import { PokemonInfoContainer } from "#ui/pokemon-info-container";
|
import { PokemonInfoContainer } from "#ui/pokemon-info-container";
|
||||||
import { addTextObject, getTextColor, TextStyle } from "#ui/text";
|
import { addTextObject, getTextColor } from "#ui/text";
|
||||||
import { UI } from "#ui/ui";
|
import { UI } from "#ui/ui";
|
||||||
import { addUiThemeOverrides } from "#ui/ui-theme";
|
import { addUiThemeOverrides } from "#ui/ui-theme";
|
||||||
import {
|
import {
|
||||||
@ -236,6 +237,7 @@ export class BattleScene extends SceneBase {
|
|||||||
public enableTouchControls = false;
|
public enableTouchControls = false;
|
||||||
public enableVibration = false;
|
public enableVibration = false;
|
||||||
public showBgmBar = true;
|
public showBgmBar = true;
|
||||||
|
public hideUsername = false;
|
||||||
/** Determines the selected battle style. */
|
/** Determines the selected battle style. */
|
||||||
public battleStyle: BattleStyle = BattleStyle.SWITCH;
|
public battleStyle: BattleStyle = BattleStyle.SWITCH;
|
||||||
/**
|
/**
|
||||||
|
@ -15,6 +15,7 @@ import { SpeciesFormChangeAbilityTrigger, SpeciesFormChangeWeatherTrigger } from
|
|||||||
import { Gender } from "#data/gender";
|
import { Gender } from "#data/gender";
|
||||||
import { getPokeballName } from "#data/pokeball";
|
import { getPokeballName } from "#data/pokeball";
|
||||||
import { pokemonFormChanges } from "#data/pokemon-forms";
|
import { pokemonFormChanges } from "#data/pokemon-forms";
|
||||||
|
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||||
import { getNonVolatileStatusEffects, getStatusEffectDescriptor, getStatusEffectHealText } from "#data/status-effect";
|
import { getNonVolatileStatusEffects, getStatusEffectDescriptor, getStatusEffectHealText } from "#data/status-effect";
|
||||||
import { TerrainType } from "#data/terrain";
|
import { TerrainType } from "#data/terrain";
|
||||||
import type { Weather } from "#data/weather";
|
import type { Weather } from "#data/weather";
|
||||||
@ -6001,8 +6002,13 @@ export class IllusionPreSummonAbAttr extends PreSummonAbAttr {
|
|||||||
const party: Pokemon[] = (pokemon.isPlayer() ? globalScene.getPlayerParty() : globalScene.getEnemyParty()).filter(
|
const party: Pokemon[] = (pokemon.isPlayer() ? globalScene.getPlayerParty() : globalScene.getEnemyParty()).filter(
|
||||||
p => p.isAllowedInBattle(),
|
p => p.isAllowedInBattle(),
|
||||||
);
|
);
|
||||||
const lastPokemon: Pokemon = party.filter(p => p !== pokemon).at(-1) || pokemon;
|
let illusionPokemon: Pokemon | PokemonSpecies;
|
||||||
pokemon.setIllusion(lastPokemon);
|
if (pokemon.hasTrainer()) {
|
||||||
|
illusionPokemon = party.filter(p => p !== pokemon).at(-1) || pokemon;
|
||||||
|
} else {
|
||||||
|
illusionPokemon = globalScene.arena.randomSpecies(globalScene.currentBattle.waveIndex, pokemon.level);
|
||||||
|
}
|
||||||
|
pokemon.setIllusion(illusionPokemon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns Whether the illusion can be applied. */
|
/** @returns Whether the illusion can be applied. */
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { allMoves } from "#data/data-lists";
|
import { allMoves } from "#data/data-lists";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { toReadableString } from "#utils/common";
|
|
||||||
import { getEnumKeys, getEnumValues } from "#utils/enums";
|
import { getEnumKeys, getEnumValues } from "#utils/enums";
|
||||||
|
import { toTitleCase } from "#utils/strings";
|
||||||
|
|
||||||
export const speciesEggMoves = {
|
export const speciesEggMoves = {
|
||||||
[SpeciesId.BULBASAUR]: [ MoveId.SAPPY_SEED, MoveId.MALIGNANT_CHAIN, MoveId.EARTH_POWER, MoveId.MATCHA_GOTCHA ],
|
[SpeciesId.BULBASAUR]: [ MoveId.SAPPY_SEED, MoveId.MALIGNANT_CHAIN, MoveId.EARTH_POWER, MoveId.MATCHA_GOTCHA ],
|
||||||
@ -617,7 +617,7 @@ function parseEggMoves(content: string): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (eggMoves.every(m => m === MoveId.NONE)) {
|
if (eggMoves.every(m => m === MoveId.NONE)) {
|
||||||
console.warn(`Species ${toReadableString(SpeciesId[species])} could not be parsed, excluding from output...`)
|
console.warn(`Species ${toTitleCase(SpeciesId[species])} could not be parsed, excluding from output...`)
|
||||||
} else {
|
} else {
|
||||||
output += `[SpeciesId.${SpeciesId[species]}]: [ ${eggMoves.map(m => `MoveId.${MoveId[m]}`).join(", ")} ],\n`;
|
output += `[SpeciesId.${SpeciesId[species]}]: [ ${eggMoves.map(m => `MoveId.${MoveId[m]}`).join(", ")} ],\n`;
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,9 @@ import { AnimBlendType, AnimFocus, AnimFrameTarget, ChargeAnim, CommonAnim } fro
|
|||||||
import { MoveFlags } from "#enums/move-flags";
|
import { MoveFlags } from "#enums/move-flags";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
import type { Pokemon } from "#field/pokemon";
|
import type { Pokemon } from "#field/pokemon";
|
||||||
import { animationFileName, coerceArray, getFrameMs, isNullOrUndefined, type nil } from "#utils/common";
|
import { coerceArray, getFrameMs, isNullOrUndefined, type nil } from "#utils/common";
|
||||||
import { getEnumKeys, getEnumValues } from "#utils/enums";
|
import { getEnumKeys, getEnumValues } from "#utils/enums";
|
||||||
|
import { toKebabCase } from "#utils/strings";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
|
|
||||||
export class AnimConfig {
|
export class AnimConfig {
|
||||||
@ -412,7 +413,7 @@ export function initCommonAnims(): Promise<void> {
|
|||||||
const commonAnimId = commonAnimIds[ca];
|
const commonAnimId = commonAnimIds[ca];
|
||||||
commonAnimFetches.push(
|
commonAnimFetches.push(
|
||||||
globalScene
|
globalScene
|
||||||
.cachedFetch(`./battle-anims/common-${commonAnimNames[ca].toLowerCase().replace(/_/g, "-")}.json`)
|
.cachedFetch(`./battle-anims/common-${toKebabCase(commonAnimNames[ca])}.json`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(cas => commonAnims.set(commonAnimId, new AnimConfig(cas))),
|
.then(cas => commonAnims.set(commonAnimId, new AnimConfig(cas))),
|
||||||
);
|
);
|
||||||
@ -450,7 +451,7 @@ export function initMoveAnim(move: MoveId): Promise<void> {
|
|||||||
|
|
||||||
const fetchAnimAndResolve = (move: MoveId) => {
|
const fetchAnimAndResolve = (move: MoveId) => {
|
||||||
globalScene
|
globalScene
|
||||||
.cachedFetch(`./battle-anims/${animationFileName(move)}.json`)
|
.cachedFetch(`./battle-anims/${toKebabCase(MoveId[move])}.json`)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const contentType = response.headers.get("content-type");
|
const contentType = response.headers.get("content-type");
|
||||||
if (!response.ok || contentType?.indexOf("application/json") === -1) {
|
if (!response.ok || contentType?.indexOf("application/json") === -1) {
|
||||||
@ -506,7 +507,7 @@ function useDefaultAnim(move: MoveId, defaultMoveAnim: MoveId) {
|
|||||||
* @remarks use {@linkcode useDefaultAnim} to use a default animation
|
* @remarks use {@linkcode useDefaultAnim} to use a default animation
|
||||||
*/
|
*/
|
||||||
function logMissingMoveAnim(move: MoveId, ...optionalParams: any[]) {
|
function logMissingMoveAnim(move: MoveId, ...optionalParams: any[]) {
|
||||||
const moveName = animationFileName(move);
|
const moveName = toKebabCase(MoveId[move]);
|
||||||
console.warn(`Could not load animation file for move '${moveName}'`, ...optionalParams);
|
console.warn(`Could not load animation file for move '${moveName}'`, ...optionalParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,7 +525,7 @@ export async function initEncounterAnims(encounterAnim: EncounterAnim | Encounte
|
|||||||
}
|
}
|
||||||
encounterAnimFetches.push(
|
encounterAnimFetches.push(
|
||||||
globalScene
|
globalScene
|
||||||
.cachedFetch(`./battle-anims/encounter-${encounterAnimNames[anim].toLowerCase().replace(/_/g, "-")}.json`)
|
.cachedFetch(`./battle-anims/encounter-${toKebabCase(encounterAnimNames[anim])}.json`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(cas => encounterAnims.set(anim, new AnimConfig(cas))),
|
.then(cas => encounterAnims.set(anim, new AnimConfig(cas))),
|
||||||
);
|
);
|
||||||
@ -548,7 +549,7 @@ export function initMoveChargeAnim(chargeAnim: ChargeAnim): Promise<void> {
|
|||||||
} else {
|
} else {
|
||||||
chargeAnims.set(chargeAnim, null);
|
chargeAnims.set(chargeAnim, null);
|
||||||
globalScene
|
globalScene
|
||||||
.cachedFetch(`./battle-anims/${ChargeAnim[chargeAnim].toLowerCase().replace(/_/g, "-")}.json`)
|
.cachedFetch(`./battle-anims/${toKebabCase(ChargeAnim[chargeAnim])}.json`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(ca => {
|
.then(ca => {
|
||||||
if (Array.isArray(ca)) {
|
if (Array.isArray(ca)) {
|
||||||
@ -1405,7 +1406,9 @@ export async function populateAnims() {
|
|||||||
const chargeAnimIds = getEnumValues(ChargeAnim);
|
const chargeAnimIds = getEnumValues(ChargeAnim);
|
||||||
const commonNamePattern = /name: (?:Common:)?(Opp )?(.*)/;
|
const commonNamePattern = /name: (?:Common:)?(Opp )?(.*)/;
|
||||||
const moveNameToId = {};
|
const moveNameToId = {};
|
||||||
|
// Exclude MoveId.NONE;
|
||||||
for (const move of getEnumValues(MoveId).slice(1)) {
|
for (const move of getEnumValues(MoveId).slice(1)) {
|
||||||
|
// KARATE_CHOP => KARATECHOP
|
||||||
const moveName = MoveId[move].toUpperCase().replace(/_/g, "");
|
const moveName = MoveId[move].toUpperCase().replace(/_/g, "");
|
||||||
moveNameToId[moveName] = move;
|
moveNameToId[moveName] = move;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import { defaultStarterSpecies } from "#app/constants";
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { pokemonEvolutions } from "#balance/pokemon-evolutions";
|
import { pokemonEvolutions } from "#balance/pokemon-evolutions";
|
||||||
import { speciesStarterCosts } from "#balance/starters";
|
import { speciesStarterCosts } from "#balance/starters";
|
||||||
|
import { getEggTierForSpecies } from "#data/egg";
|
||||||
import { pokemonFormChanges } from "#data/pokemon-forms";
|
import { pokemonFormChanges } from "#data/pokemon-forms";
|
||||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||||
import { getPokemonSpeciesForm } from "#data/pokemon-species";
|
import { getPokemonSpeciesForm } from "#data/pokemon-species";
|
||||||
@ -11,6 +12,7 @@ import { BattleType } from "#enums/battle-type";
|
|||||||
import { ChallengeType } from "#enums/challenge-type";
|
import { ChallengeType } from "#enums/challenge-type";
|
||||||
import { Challenges } from "#enums/challenges";
|
import { Challenges } from "#enums/challenges";
|
||||||
import { TypeColor, TypeShadow } from "#enums/color";
|
import { TypeColor, TypeShadow } from "#enums/color";
|
||||||
|
import { EggTier } from "#enums/egg-type";
|
||||||
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves";
|
||||||
import { ModifierTier } from "#enums/modifier-tier";
|
import { ModifierTier } from "#enums/modifier-tier";
|
||||||
import type { MoveId } from "#enums/move-id";
|
import type { MoveId } from "#enums/move-id";
|
||||||
@ -27,6 +29,7 @@ import type { DexAttrProps, GameData } from "#system/game-data";
|
|||||||
import { BooleanHolder, type NumberHolder, randSeedItem } from "#utils/common";
|
import { BooleanHolder, type NumberHolder, randSeedItem } from "#utils/common";
|
||||||
import { deepCopy } from "#utils/data";
|
import { deepCopy } from "#utils/data";
|
||||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||||
|
import { toCamelCase, toSnakeCase } from "#utils/strings";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
/** A constant for the default max cost of the starting party before a run */
|
/** A constant for the default max cost of the starting party before a run */
|
||||||
@ -67,14 +70,11 @@ export abstract class Challenge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the localisation key for the challenge
|
* Gets the localization key for the challenge
|
||||||
* @returns {@link string} The i18n key for this challenge
|
* @returns The i18n key for this challenge as camel case.
|
||||||
*/
|
*/
|
||||||
geti18nKey(): string {
|
geti18nKey(): string {
|
||||||
return Challenges[this.id]
|
return toCamelCase(Challenges[this.id]);
|
||||||
.split("_")
|
|
||||||
.map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()))
|
|
||||||
.join("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,23 +105,22 @@ export abstract class Challenge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the textual representation of a challenge's current value.
|
* Return the textual representation of a challenge's current value.
|
||||||
* @param overrideValue {@link number} The value to check for. If undefined, gets the current value.
|
* @param overrideValue - The value to check for; default {@linkcode this.value}
|
||||||
* @returns {@link string} The localised name for the current value.
|
* @returns The localised text for the current value.
|
||||||
*/
|
*/
|
||||||
getValue(overrideValue?: number): string {
|
getValue(overrideValue: number = this.value): string {
|
||||||
const value = overrideValue ?? this.value;
|
return i18next.t(`challenges:${this.geti18nKey()}.value.${overrideValue}`);
|
||||||
return i18next.t(`challenges:${this.geti18nKey()}.value.${value}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the description of a challenge's current value.
|
* Return the description of a challenge's current value.
|
||||||
* @param overrideValue {@link number} The value to check for. If undefined, gets the current value.
|
* @param overrideValue - The value to check for; default {@linkcode this.value}
|
||||||
* @returns {@link string} The localised description for the current value.
|
* @returns The localised description for the current value.
|
||||||
*/
|
*/
|
||||||
getDescription(overrideValue?: number): string {
|
// TODO: Do we need an override value here? it's currently unused
|
||||||
const value = overrideValue ?? this.value;
|
getDescription(overrideValue: number = this.value): string {
|
||||||
return `${i18next.t([`challenges:${this.geti18nKey()}.desc.${value}`, `challenges:${this.geti18nKey()}.desc`])}`;
|
return `${i18next.t([`challenges:${this.geti18nKey()}.desc.${overrideValue}`, `challenges:${this.geti18nKey()}.desc`])}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -579,31 +578,19 @@ export class SingleGenerationChallenge extends Challenge {
|
|||||||
return this.value > 0 ? 1 : 0;
|
return this.value > 0 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
getValue(overrideValue: number = this.value): string {
|
||||||
* Returns the textual representation of a challenge's current value.
|
if (overrideValue === 0) {
|
||||||
* @param {value} overrideValue The value to check for. If undefined, gets the current value.
|
|
||||||
* @returns {string} The localised name for the current value.
|
|
||||||
*/
|
|
||||||
getValue(overrideValue?: number): string {
|
|
||||||
const value = overrideValue ?? this.value;
|
|
||||||
if (value === 0) {
|
|
||||||
return i18next.t("settings:off");
|
return i18next.t("settings:off");
|
||||||
}
|
}
|
||||||
return i18next.t(`starterSelectUiHandler:gen${value}`);
|
return i18next.t(`starterSelectUiHandler:gen${overrideValue}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
getDescription(overrideValue: number = this.value): string {
|
||||||
* Returns the description of a challenge's current value.
|
if (overrideValue === 0) {
|
||||||
* @param {value} overrideValue The value to check for. If undefined, gets the current value.
|
|
||||||
* @returns {string} The localised description for the current value.
|
|
||||||
*/
|
|
||||||
getDescription(overrideValue?: number): string {
|
|
||||||
const value = overrideValue ?? this.value;
|
|
||||||
if (value === 0) {
|
|
||||||
return i18next.t("challenges:singleGeneration.desc_default");
|
return i18next.t("challenges:singleGeneration.desc_default");
|
||||||
}
|
}
|
||||||
return i18next.t("challenges:singleGeneration.desc", {
|
return i18next.t("challenges:singleGeneration.desc", {
|
||||||
gen: i18next.t(`challenges:singleGeneration.gen_${value}`),
|
gen: i18next.t(`challenges:singleGeneration.gen_${overrideValue}`),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,29 +658,13 @@ export class SingleTypeChallenge extends Challenge {
|
|||||||
return this.value > 0 ? 1 : 0;
|
return this.value > 0 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
getValue(overrideValue: number = this.value): string {
|
||||||
* Returns the textual representation of a challenge's current value.
|
return toSnakeCase(PokemonType[overrideValue - 1]);
|
||||||
* @param {value} overrideValue The value to check for. If undefined, gets the current value.
|
|
||||||
* @returns {string} The localised name for the current value.
|
|
||||||
*/
|
|
||||||
getValue(overrideValue?: number): string {
|
|
||||||
if (overrideValue === undefined) {
|
|
||||||
overrideValue = this.value;
|
|
||||||
}
|
|
||||||
return PokemonType[this.value - 1].toLowerCase();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
getDescription(overrideValue: number = this.value): string {
|
||||||
* Returns the description of a challenge's current value.
|
const type = i18next.t(`pokemonInfo:Type.${PokemonType[overrideValue - 1]}`);
|
||||||
* @param {value} overrideValue The value to check for. If undefined, gets the current value.
|
const typeColor = `[color=${TypeColor[PokemonType[overrideValue - 1]]}][shadow=${TypeShadow[PokemonType[this.value - 1]]}]${type}[/shadow][/color]`;
|
||||||
* @returns {string} The localised description for the current value.
|
|
||||||
*/
|
|
||||||
getDescription(overrideValue?: number): string {
|
|
||||||
if (overrideValue === undefined) {
|
|
||||||
overrideValue = this.value;
|
|
||||||
}
|
|
||||||
const type = i18next.t(`pokemonInfo:Type.${PokemonType[this.value - 1]}`);
|
|
||||||
const typeColor = `[color=${TypeColor[PokemonType[this.value - 1]]}][shadow=${TypeShadow[PokemonType[this.value - 1]]}]${type}[/shadow][/color]`;
|
|
||||||
const defaultDesc = i18next.t("challenges:singleType.desc_default");
|
const defaultDesc = i18next.t("challenges:singleType.desc_default");
|
||||||
const typeDesc = i18next.t("challenges:singleType.desc", {
|
const typeDesc = i18next.t("challenges:singleType.desc", {
|
||||||
type: typeColor,
|
type: typeColor,
|
||||||
@ -714,11 +685,14 @@ export class SingleTypeChallenge extends Challenge {
|
|||||||
*/
|
*/
|
||||||
export class FreshStartChallenge extends Challenge {
|
export class FreshStartChallenge extends Challenge {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(Challenges.FRESH_START, 1);
|
super(Challenges.FRESH_START, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
applyStarterChoice(pokemon: PokemonSpecies, valid: BooleanHolder): boolean {
|
applyStarterChoice(pokemon: PokemonSpecies, valid: BooleanHolder): boolean {
|
||||||
if (!defaultStarterSpecies.includes(pokemon.speciesId)) {
|
if (
|
||||||
|
(this.value === 1 && !defaultStarterSpecies.includes(pokemon.speciesId)) ||
|
||||||
|
(this.value === 2 && getEggTierForSpecies(pokemon) >= EggTier.EPIC)
|
||||||
|
) {
|
||||||
valid.value = false;
|
valid.value = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -726,15 +700,12 @@ export class FreshStartChallenge extends Challenge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
applyStarterCost(species: SpeciesId, cost: NumberHolder): boolean {
|
applyStarterCost(species: SpeciesId, cost: NumberHolder): boolean {
|
||||||
if (defaultStarterSpecies.includes(species)) {
|
cost.value = speciesStarterCosts[species];
|
||||||
cost.value = speciesStarterCosts[species];
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
applyStarterModify(pokemon: Pokemon): boolean {
|
applyStarterModify(pokemon: Pokemon): boolean {
|
||||||
pokemon.abilityIndex = 0; // Always base ability, not hidden ability
|
pokemon.abilityIndex = pokemon.abilityIndex % 2; // Always base ability, if you set it to hidden it wraps to first ability
|
||||||
pokemon.passive = false; // Passive isn't unlocked
|
pokemon.passive = false; // Passive isn't unlocked
|
||||||
pokemon.nature = Nature.HARDY; // Neutral nature
|
pokemon.nature = Nature.HARDY; // Neutral nature
|
||||||
pokemon.moveset = pokemon.species
|
pokemon.moveset = pokemon.species
|
||||||
@ -746,7 +717,22 @@ export class FreshStartChallenge extends Challenge {
|
|||||||
pokemon.luck = 0; // No luck
|
pokemon.luck = 0; // No luck
|
||||||
pokemon.shiny = false; // Not shiny
|
pokemon.shiny = false; // Not shiny
|
||||||
pokemon.variant = 0; // Not shiny
|
pokemon.variant = 0; // Not shiny
|
||||||
pokemon.formIndex = 0; // Froakie should be base form
|
if (pokemon.species.speciesId === SpeciesId.ZYGARDE && pokemon.formIndex >= 2) {
|
||||||
|
pokemon.formIndex -= 2; // Sets 10%-PC to 10%-AB and 50%-PC to 50%-AB
|
||||||
|
} else if (
|
||||||
|
pokemon.formIndex > 0 &&
|
||||||
|
[
|
||||||
|
SpeciesId.PIKACHU,
|
||||||
|
SpeciesId.EEVEE,
|
||||||
|
SpeciesId.PICHU,
|
||||||
|
SpeciesId.ROTOM,
|
||||||
|
SpeciesId.MELOETTA,
|
||||||
|
SpeciesId.FROAKIE,
|
||||||
|
SpeciesId.ROCKRUFF,
|
||||||
|
].includes(pokemon.species.speciesId)
|
||||||
|
) {
|
||||||
|
pokemon.formIndex = 0; // These mons are set to form 0 because they're meant to be unlocks or mid-run form changes
|
||||||
|
}
|
||||||
pokemon.ivs = [15, 15, 15, 15, 15, 15]; // Default IVs of 15 for all stats (Updated to 15 from 10 in 1.2.0)
|
pokemon.ivs = [15, 15, 15, 15, 15, 15]; // Default IVs of 15 for all stats (Updated to 15 from 10 in 1.2.0)
|
||||||
pokemon.teraType = pokemon.species.type1; // Always primary tera type
|
pokemon.teraType = pokemon.species.type1; // Always primary tera type
|
||||||
return true;
|
return true;
|
||||||
@ -832,13 +818,7 @@ export class LowerStarterMaxCostChallenge extends Challenge {
|
|||||||
super(Challenges.LOWER_MAX_STARTER_COST, 9);
|
super(Challenges.LOWER_MAX_STARTER_COST, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
getValue(overrideValue: number = this.value): string {
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
getValue(overrideValue?: number): string {
|
|
||||||
if (overrideValue === undefined) {
|
|
||||||
overrideValue = this.value;
|
|
||||||
}
|
|
||||||
return (DEFAULT_PARTY_MAX_COST - overrideValue).toString();
|
return (DEFAULT_PARTY_MAX_COST - overrideValue).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -866,13 +846,7 @@ export class LowerStarterPointsChallenge extends Challenge {
|
|||||||
super(Challenges.LOWER_STARTER_POINTS, 9);
|
super(Challenges.LOWER_STARTER_POINTS, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
getValue(overrideValue: number = this.value): string {
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
getValue(overrideValue?: number): string {
|
|
||||||
if (overrideValue === undefined) {
|
|
||||||
overrideValue = this.value;
|
|
||||||
}
|
|
||||||
return (DEFAULT_PARTY_MAX_COST - overrideValue).toString();
|
return (DEFAULT_PARTY_MAX_COST - overrideValue).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { BattleSpec } from "#enums/battle-spec";
|
import { BattleSpec } from "#enums/battle-spec";
|
||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { trainerConfigs } from "#trainers/trainer-config";
|
import { trainerConfigs } from "#trainers/trainer-config";
|
||||||
|
import { capitalizeFirstLetter } from "#utils/strings";
|
||||||
|
|
||||||
export interface TrainerTypeMessages {
|
export interface TrainerTypeMessages {
|
||||||
encounter?: string | string[];
|
encounter?: string | string[];
|
||||||
@ -1755,8 +1756,7 @@ export function initTrainerTypeDialogue(): void {
|
|||||||
trainerConfigs[trainerType][`${messageType}Messages`] = messages[0][messageType];
|
trainerConfigs[trainerType][`${messageType}Messages`] = messages[0][messageType];
|
||||||
}
|
}
|
||||||
if (messages.length > 1) {
|
if (messages.length > 1) {
|
||||||
trainerConfigs[trainerType][`female${messageType.slice(0, 1).toUpperCase()}${messageType.slice(1)}Messages`] =
|
trainerConfigs[trainerType][`female${capitalizeFirstLetter(messageType)}Messages`] = messages[1][messageType];
|
||||||
messages[1][messageType];
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trainerConfigs[trainerType][`${messageType}Messages`] = messages[messageType];
|
trainerConfigs[trainerType][`${messageType}Messages`] = messages[messageType];
|
||||||
|
@ -87,8 +87,9 @@ import type { AttackMoveResult } from "#types/attack-move-result";
|
|||||||
import type { Localizable } from "#types/locales";
|
import type { Localizable } from "#types/locales";
|
||||||
import type { ChargingMove, MoveAttrMap, MoveAttrString, MoveClassMap, MoveKindString } from "#types/move-types";
|
import type { ChargingMove, MoveAttrMap, MoveAttrString, MoveClassMap, MoveKindString } from "#types/move-types";
|
||||||
import type { TurnMove } from "#types/turn-move";
|
import type { TurnMove } from "#types/turn-move";
|
||||||
import { BooleanHolder, type Constructor, isNullOrUndefined, NumberHolder, randSeedFloat, randSeedInt, randSeedItem, toDmgValue, toReadableString } from "#utils/common";
|
import { BooleanHolder, type Constructor, isNullOrUndefined, NumberHolder, randSeedFloat, randSeedInt, randSeedItem, toDmgValue } from "#utils/common";
|
||||||
import { getEnumValues } from "#utils/enums";
|
import { getEnumValues } from "#utils/enums";
|
||||||
|
import { toTitleCase } from "#utils/strings";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -8137,7 +8138,7 @@ export class ResistLastMoveTypeAttr extends MoveEffectAttr {
|
|||||||
}
|
}
|
||||||
const type = validTypes[user.randBattleSeedInt(validTypes.length)];
|
const type = validTypes[user.randBattleSeedInt(validTypes.length)];
|
||||||
user.summonData.types = [ type ];
|
user.summonData.types = [ type ];
|
||||||
globalScene.phaseManager.queueMessage(i18next.t("battle:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), type: toReadableString(PokemonType[type]) }));
|
globalScene.phaseManager.queueMessage(i18next.t("battle:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), type: toTitleCase(PokemonType[type]) }));
|
||||||
user.updateInfo();
|
user.updateInfo();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { TextStyle } from "#ui/text";
|
import type { TextStyle } from "#enums/text-style";
|
||||||
|
|
||||||
export class TextDisplay {
|
export class TextDisplay {
|
||||||
speaker?: string;
|
speaker?: string;
|
||||||
|
@ -25,7 +25,8 @@ import {
|
|||||||
StatusEffectRequirement,
|
StatusEffectRequirement,
|
||||||
WaveRangeRequirement,
|
WaveRangeRequirement,
|
||||||
} from "#mystery-encounters/mystery-encounter-requirements";
|
} from "#mystery-encounters/mystery-encounter-requirements";
|
||||||
import { capitalizeFirstLetter, coerceArray, isNullOrUndefined, randSeedInt } from "#utils/common";
|
import { coerceArray, isNullOrUndefined, randSeedInt } from "#utils/common";
|
||||||
|
import { capitalizeFirstLetter } from "#utils/strings";
|
||||||
|
|
||||||
export interface EncounterStartOfBattleEffect {
|
export interface EncounterStartOfBattleEffect {
|
||||||
sourcePokemon?: Pokemon;
|
sourcePokemon?: Pokemon;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import type { TextStyle } from "#enums/text-style";
|
||||||
import { UiTheme } from "#enums/ui-theme";
|
import { UiTheme } from "#enums/ui-theme";
|
||||||
import type { TextStyle } from "#ui/text";
|
|
||||||
import { getTextWithColors } from "#ui/text";
|
import { getTextWithColors } from "#ui/text";
|
||||||
import { isNullOrUndefined } from "#utils/common";
|
import { isNullOrUndefined } from "#utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { Nature } from "#enums/nature";
|
import { Nature } from "#enums/nature";
|
||||||
import { EFFECTIVE_STATS, getShortenedStatKey, Stat } from "#enums/stat";
|
import { EFFECTIVE_STATS, getShortenedStatKey, Stat } from "#enums/stat";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiTheme } from "#enums/ui-theme";
|
import { UiTheme } from "#enums/ui-theme";
|
||||||
import { getBBCodeFrag, TextStyle } from "#ui/text";
|
import { getBBCodeFrag } from "#ui/text";
|
||||||
import { toReadableString } from "#utils/common";
|
import { toTitleCase } from "#utils/strings";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export function getNatureName(
|
export function getNatureName(
|
||||||
@ -12,7 +13,7 @@ export function getNatureName(
|
|||||||
ignoreBBCode = false,
|
ignoreBBCode = false,
|
||||||
uiTheme: UiTheme = UiTheme.DEFAULT,
|
uiTheme: UiTheme = UiTheme.DEFAULT,
|
||||||
): string {
|
): string {
|
||||||
let ret = toReadableString(Nature[nature]);
|
let ret = toTitleCase(Nature[nature]);
|
||||||
//Translating nature
|
//Translating nature
|
||||||
if (i18next.exists(`nature:${ret}`)) {
|
if (i18next.exists(`nature:${ret}`)) {
|
||||||
ret = i18next.t(`nature:${ret}` as any);
|
ret = i18next.t(`nature:${ret}` as any);
|
||||||
|
@ -29,15 +29,9 @@ import type { Variant, VariantSet } from "#sprites/variant";
|
|||||||
import { populateVariantColorCache, variantColorCache, variantData } from "#sprites/variant";
|
import { populateVariantColorCache, variantColorCache, variantData } from "#sprites/variant";
|
||||||
import type { StarterMoveset } from "#system/game-data";
|
import type { StarterMoveset } from "#system/game-data";
|
||||||
import type { Localizable } from "#types/locales";
|
import type { Localizable } from "#types/locales";
|
||||||
import {
|
import { isNullOrUndefined, randSeedFloat, randSeedGauss, randSeedInt, randSeedItem } from "#utils/common";
|
||||||
capitalizeString,
|
|
||||||
isNullOrUndefined,
|
|
||||||
randSeedFloat,
|
|
||||||
randSeedGauss,
|
|
||||||
randSeedInt,
|
|
||||||
randSeedItem,
|
|
||||||
} from "#utils/common";
|
|
||||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||||
|
import { toCamelCase, toPascalCase } from "#utils/strings";
|
||||||
import { argbFromRgba, QuantizerCelebi, rgbaFromArgb } from "@material/material-color-utilities";
|
import { argbFromRgba, QuantizerCelebi, rgbaFromArgb } from "@material/material-color-utilities";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
@ -91,6 +85,7 @@ export function getPokemonSpeciesForm(species: SpeciesId, formIndex: number): Po
|
|||||||
return retSpecies;
|
return retSpecies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Clean this up and seriously review alternate means of fusion naming
|
||||||
export function getFusedSpeciesName(speciesAName: string, speciesBName: string): string {
|
export function getFusedSpeciesName(speciesAName: string, speciesBName: string): string {
|
||||||
const fragAPattern = /([a-z]{2}.*?[aeiou(?:y$)\-']+)(.*?)$/i;
|
const fragAPattern = /([a-z]{2}.*?[aeiou(?:y$)\-']+)(.*?)$/i;
|
||||||
const fragBPattern = /([a-z]{2}.*?[aeiou(?:y$)\-'])(.*?)$/i;
|
const fragBPattern = /([a-z]{2}.*?[aeiou(?:y$)\-'])(.*?)$/i;
|
||||||
@ -904,14 +899,14 @@ export class PokemonSpecies extends PokemonSpeciesForm implements Localizable {
|
|||||||
* @returns the pokemon-form locale key for the single form name ("Alolan Form", "Eternal Flower" etc)
|
* @returns the pokemon-form locale key for the single form name ("Alolan Form", "Eternal Flower" etc)
|
||||||
*/
|
*/
|
||||||
getFormNameToDisplay(formIndex = 0, append = false): string {
|
getFormNameToDisplay(formIndex = 0, append = false): string {
|
||||||
const formKey = this.forms?.[formIndex!]?.formKey;
|
const formKey = this.forms[formIndex]?.formKey ?? "";
|
||||||
const formText = capitalizeString(formKey, "-", false, false) || "";
|
const formText = toPascalCase(formKey);
|
||||||
const speciesName = capitalizeString(SpeciesId[this.speciesId], "_", true, false);
|
const speciesName = toCamelCase(SpeciesId[this.speciesId]);
|
||||||
let ret = "";
|
let ret = "";
|
||||||
|
|
||||||
const region = this.getRegion();
|
const region = this.getRegion();
|
||||||
if (this.speciesId === SpeciesId.ARCEUS) {
|
if (this.speciesId === SpeciesId.ARCEUS) {
|
||||||
ret = i18next.t(`pokemonInfo:Type.${formText?.toUpperCase()}`);
|
ret = i18next.t(`pokemonInfo:Type.${formText.toUpperCase()}`);
|
||||||
} else if (
|
} else if (
|
||||||
[
|
[
|
||||||
SpeciesFormKey.MEGA,
|
SpeciesFormKey.MEGA,
|
||||||
@ -937,7 +932,7 @@ export class PokemonSpecies extends PokemonSpeciesForm implements Localizable {
|
|||||||
if (i18next.exists(i18key)) {
|
if (i18next.exists(i18key)) {
|
||||||
ret = i18next.t(i18key);
|
ret = i18next.t(i18key);
|
||||||
} else {
|
} else {
|
||||||
const rootSpeciesName = capitalizeString(SpeciesId[this.getRootSpeciesId()], "_", true, false);
|
const rootSpeciesName = toCamelCase(SpeciesId[this.getRootSpeciesId()]);
|
||||||
const i18RootKey = `pokemonForm:${rootSpeciesName}${formText}`;
|
const i18RootKey = `pokemonForm:${rootSpeciesName}${formText}`;
|
||||||
ret = i18next.exists(i18RootKey) ? i18next.t(i18RootKey) : formText;
|
ret = i18next.exists(i18RootKey) ? i18next.t(i18RootKey) : formText;
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,29 @@
|
|||||||
import { type BattlerTag, loadBattlerTag } from "#data/battler-tags";
|
import { type BattlerTag, loadBattlerTag } from "#data/battler-tags";
|
||||||
|
import { allSpecies } from "#data/data-lists";
|
||||||
import type { Gender } from "#data/gender";
|
import type { Gender } from "#data/gender";
|
||||||
import { PokemonMove } from "#data/moves/pokemon-move";
|
import { PokemonMove } from "#data/moves/pokemon-move";
|
||||||
import type { PokemonSpeciesForm } from "#data/pokemon-species";
|
import { getPokemonSpeciesForm, type PokemonSpeciesForm } from "#data/pokemon-species";
|
||||||
import type { TypeDamageMultiplier } from "#data/type";
|
import type { TypeDamageMultiplier } from "#data/type";
|
||||||
import type { AbilityId } from "#enums/ability-id";
|
import type { AbilityId } from "#enums/ability-id";
|
||||||
import type { BerryType } from "#enums/berry-type";
|
import type { BerryType } from "#enums/berry-type";
|
||||||
import type { MoveId } from "#enums/move-id";
|
import type { MoveId } from "#enums/move-id";
|
||||||
import type { Nature } from "#enums/nature";
|
import type { Nature } from "#enums/nature";
|
||||||
import type { PokemonType } from "#enums/pokemon-type";
|
import type { PokemonType } from "#enums/pokemon-type";
|
||||||
|
import type { SpeciesId } from "#enums/species-id";
|
||||||
import type { AttackMoveResult } from "#types/attack-move-result";
|
import type { AttackMoveResult } from "#types/attack-move-result";
|
||||||
import type { IllusionData } from "#types/illusion-data";
|
import type { IllusionData } from "#types/illusion-data";
|
||||||
import type { TurnMove } from "#types/turn-move";
|
import type { TurnMove } from "#types/turn-move";
|
||||||
|
import type { CoerceNullPropertiesToUndefined } from "#types/type-helpers";
|
||||||
import { isNullOrUndefined } from "#utils/common";
|
import { isNullOrUndefined } from "#utils/common";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type that {@linkcode PokemonSpeciesForm} is converted to when an object containing it serializes it.
|
||||||
|
*/
|
||||||
|
type SerializedSpeciesForm = {
|
||||||
|
id: SpeciesId;
|
||||||
|
formIdx: number;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permanent data that can customize a Pokemon in non-standard ways from its Species.
|
* Permanent data that can customize a Pokemon in non-standard ways from its Species.
|
||||||
* Includes abilities, nature, changed types, etc.
|
* Includes abilities, nature, changed types, etc.
|
||||||
@ -41,9 +52,59 @@ export class CustomPokemonData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize a pokemon species form from an object containing `id` and `formIdx` properties.
|
||||||
|
* @param value - The value to deserialize
|
||||||
|
* @returns The `PokemonSpeciesForm` or `null` if the fields could not be properly discerned
|
||||||
|
*/
|
||||||
|
function deserializePokemonSpeciesForm(value: SerializedSpeciesForm | PokemonSpeciesForm): PokemonSpeciesForm | null {
|
||||||
|
// @ts-expect-error: We may be deserializing a PokemonSpeciesForm, but we catch later on
|
||||||
|
let { id, formIdx } = value;
|
||||||
|
|
||||||
|
if (isNullOrUndefined(id) || isNullOrUndefined(formIdx)) {
|
||||||
|
// @ts-expect-error: Typescript doesn't know that in block, `value` must be a PokemonSpeciesForm
|
||||||
|
id = value.speciesId;
|
||||||
|
// @ts-expect-error: Same as above (plus we are accessing a protected property)
|
||||||
|
formIdx = value._formIndex;
|
||||||
|
}
|
||||||
|
// If for some reason either of these fields are null/undefined, we cannot reconstruct the species form
|
||||||
|
if (isNullOrUndefined(id) || isNullOrUndefined(formIdx)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return getPokemonSpeciesForm(id, formIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SerializedIllusionData extends Omit<IllusionData, "fusionSpecies"> {
|
||||||
|
/** The id of the illusioned fusion species, or `undefined` if not a fusion */
|
||||||
|
fusionSpecies?: SpeciesId;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SerializedPokemonSummonData {
|
||||||
|
statStages: number[];
|
||||||
|
moveQueue: TurnMove[];
|
||||||
|
tags: BattlerTag[];
|
||||||
|
abilitySuppressed: boolean;
|
||||||
|
speciesForm?: SerializedSpeciesForm;
|
||||||
|
fusionSpeciesForm?: SerializedSpeciesForm;
|
||||||
|
ability?: AbilityId;
|
||||||
|
passiveAbility?: AbilityId;
|
||||||
|
gender?: Gender;
|
||||||
|
fusionGender?: Gender;
|
||||||
|
stats: number[];
|
||||||
|
moveset?: PokemonMove[];
|
||||||
|
types: PokemonType[];
|
||||||
|
addedType?: PokemonType;
|
||||||
|
illusion?: SerializedIllusionData;
|
||||||
|
illusionBroken: boolean;
|
||||||
|
berriesEatenLast: BerryType[];
|
||||||
|
moveHistory: TurnMove[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persistent in-battle data for a {@linkcode Pokemon}.
|
* Persistent in-battle data for a {@linkcode Pokemon}.
|
||||||
* Resets on switch or new battle.
|
* Resets on switch or new battle.
|
||||||
|
*
|
||||||
|
* @sealed
|
||||||
*/
|
*/
|
||||||
export class PokemonSummonData {
|
export class PokemonSummonData {
|
||||||
/** [Atk, Def, SpAtk, SpDef, Spd, Acc, Eva] */
|
/** [Atk, Def, SpAtk, SpDef, Spd, Acc, Eva] */
|
||||||
@ -86,7 +147,7 @@ export class PokemonSummonData {
|
|||||||
*/
|
*/
|
||||||
public moveHistory: TurnMove[] = [];
|
public moveHistory: TurnMove[] = [];
|
||||||
|
|
||||||
constructor(source?: PokemonSummonData | Partial<PokemonSummonData>) {
|
constructor(source?: PokemonSummonData | SerializedPokemonSummonData) {
|
||||||
if (isNullOrUndefined(source)) {
|
if (isNullOrUndefined(source)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -97,6 +158,30 @@ export class PokemonSummonData {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key === "speciesForm" || key === "fusionSpeciesForm") {
|
||||||
|
this[key] = deserializePokemonSpeciesForm(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key === "illusion" && typeof value === "object") {
|
||||||
|
// Make a copy so as not to mutate provided value
|
||||||
|
const illusionData = {
|
||||||
|
...value,
|
||||||
|
};
|
||||||
|
if (!isNullOrUndefined(illusionData.fusionSpecies)) {
|
||||||
|
switch (typeof illusionData.fusionSpecies) {
|
||||||
|
case "object":
|
||||||
|
illusionData.fusionSpecies = allSpecies[illusionData.fusionSpecies.speciesId];
|
||||||
|
break;
|
||||||
|
case "number":
|
||||||
|
illusionData.fusionSpecies = allSpecies[illusionData.fusionSpecies];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
illusionData.fusionSpecies = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this[key] = illusionData as IllusionData;
|
||||||
|
}
|
||||||
|
|
||||||
if (key === "moveset") {
|
if (key === "moveset") {
|
||||||
this.moveset = value?.map((m: any) => PokemonMove.loadMove(m));
|
this.moveset = value?.map((m: any) => PokemonMove.loadMove(m));
|
||||||
continue;
|
continue;
|
||||||
@ -110,6 +195,49 @@ export class PokemonSummonData {
|
|||||||
this[key] = value;
|
this[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize this PokemonSummonData to JSON, converting {@linkcode PokemonSpeciesForm} and {@linkcode IllusionData.fusionSpecies}
|
||||||
|
* into simpler types instead of serializing all of their fields.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* - `IllusionData.fusionSpecies` is serialized as just the species ID
|
||||||
|
* - `PokemonSpeciesForm` and `PokemonSpeciesForm.fusionSpeciesForm` are converted into {@linkcode SerializedSpeciesForm} objects
|
||||||
|
*/
|
||||||
|
public toJSON(): SerializedPokemonSummonData {
|
||||||
|
// Pokemon species forms are never saved, only the species ID.
|
||||||
|
const illusion = this.illusion;
|
||||||
|
const speciesForm = this.speciesForm;
|
||||||
|
const fusionSpeciesForm = this.fusionSpeciesForm;
|
||||||
|
const illusionSpeciesForm = illusion?.fusionSpecies;
|
||||||
|
const t = {
|
||||||
|
// the "as omit" is required to avoid TS resolving the overwritten properties to "never"
|
||||||
|
// We coerce null to undefined in the type, as the for loop below replaces `null` with `undefined`
|
||||||
|
...(this as Omit<
|
||||||
|
CoerceNullPropertiesToUndefined<PokemonSummonData>,
|
||||||
|
"speciesForm" | "fusionSpeciesForm" | "illusion"
|
||||||
|
>),
|
||||||
|
speciesForm: isNullOrUndefined(speciesForm)
|
||||||
|
? undefined
|
||||||
|
: { id: speciesForm.speciesId, formIdx: speciesForm.formIndex },
|
||||||
|
fusionSpeciesForm: isNullOrUndefined(fusionSpeciesForm)
|
||||||
|
? undefined
|
||||||
|
: { id: fusionSpeciesForm.speciesId, formIdx: fusionSpeciesForm.formIndex },
|
||||||
|
illusion: isNullOrUndefined(illusion)
|
||||||
|
? undefined
|
||||||
|
: {
|
||||||
|
...(this.illusion as Omit<typeof illusion, "fusionSpecies">),
|
||||||
|
fusionSpecies: illusionSpeciesForm?.speciesId,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// Replace `null` with `undefined`, as `undefined` never gets serialized
|
||||||
|
for (const [key, value] of Object.entries(t)) {
|
||||||
|
if (value === null) {
|
||||||
|
t[key] = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Merge this inside `summmonData` but exclude from save if/when a save data serializer is added
|
// TODO: Merge this inside `summmonData` but exclude from save if/when a save data serializer is added
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { TrainerType } from "#enums/trainer-type";
|
import { TrainerType } from "#enums/trainer-type";
|
||||||
import { toReadableString } from "#utils/common";
|
import { toPascalSnakeCase } from "#utils/strings";
|
||||||
|
|
||||||
class TrainerNameConfig {
|
class TrainerNameConfig {
|
||||||
public urls: string[];
|
public urls: string[];
|
||||||
public femaleUrls: string[] | null;
|
public femaleUrls: string[] | null;
|
||||||
|
|
||||||
constructor(type: TrainerType, ...urls: string[]) {
|
constructor(type: TrainerType, ...urls: string[]) {
|
||||||
this.urls = urls.length ? urls : [toReadableString(TrainerType[type]).replace(/ /g, "_")];
|
this.urls = urls.length ? urls : [toPascalSnakeCase(TrainerType[type])];
|
||||||
}
|
}
|
||||||
|
|
||||||
hasGenderVariant(...femaleUrls: string[]): TrainerNameConfig {
|
hasGenderVariant(...femaleUrls: string[]): TrainerNameConfig {
|
||||||
|
@ -41,15 +41,9 @@ import type {
|
|||||||
TrainerConfigs,
|
TrainerConfigs,
|
||||||
TrainerTierPools,
|
TrainerTierPools,
|
||||||
} from "#types/trainer-funcs";
|
} from "#types/trainer-funcs";
|
||||||
import {
|
import { coerceArray, isNullOrUndefined, randSeedInt, randSeedIntRange, randSeedItem } from "#utils/common";
|
||||||
coerceArray,
|
|
||||||
isNullOrUndefined,
|
|
||||||
randSeedInt,
|
|
||||||
randSeedIntRange,
|
|
||||||
randSeedItem,
|
|
||||||
toReadableString,
|
|
||||||
} from "#utils/common";
|
|
||||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||||
|
import { toSnakeCase, toTitleCase } from "#utils/strings";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
/** Minimum BST for Pokemon generated onto the Elite Four's teams */
|
/** Minimum BST for Pokemon generated onto the Elite Four's teams */
|
||||||
@ -140,7 +134,7 @@ export class TrainerConfig {
|
|||||||
constructor(trainerType: TrainerType, allowLegendaries?: boolean) {
|
constructor(trainerType: TrainerType, allowLegendaries?: boolean) {
|
||||||
this.trainerType = trainerType;
|
this.trainerType = trainerType;
|
||||||
this.trainerAI = new TrainerAI();
|
this.trainerAI = new TrainerAI();
|
||||||
this.name = toReadableString(TrainerType[this.getDerivedType()]);
|
this.name = toTitleCase(TrainerType[this.getDerivedType()]);
|
||||||
this.battleBgm = "battle_trainer";
|
this.battleBgm = "battle_trainer";
|
||||||
this.mixedBattleBgm = "battle_trainer";
|
this.mixedBattleBgm = "battle_trainer";
|
||||||
this.victoryBgm = "victory_trainer";
|
this.victoryBgm = "victory_trainer";
|
||||||
@ -734,7 +728,7 @@ export class TrainerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Localize the trainer's name by converting it to lowercase and replacing spaces with underscores.
|
// Localize the trainer's name by converting it to lowercase and replacing spaces with underscores.
|
||||||
const nameForCall = this.name.toLowerCase().replace(/\s/g, "_");
|
const nameForCall = toSnakeCase(this.name);
|
||||||
this.name = i18next.t(`trainerNames:${nameForCall}`);
|
this.name = i18next.t(`trainerNames:${nameForCall}`);
|
||||||
|
|
||||||
// Set the title to "elite_four". (this is the key in the i18n file)
|
// Set the title to "elite_four". (this is the key in the i18n file)
|
||||||
|
59
src/enums/text-style.ts
Normal file
59
src/enums/text-style.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
export const TextStyle = Object.freeze({
|
||||||
|
MESSAGE: 1,
|
||||||
|
WINDOW: 2,
|
||||||
|
WINDOW_ALT: 3,
|
||||||
|
WINDOW_BATTLE_COMMAND: 4,
|
||||||
|
BATTLE_INFO: 5,
|
||||||
|
PARTY: 6,
|
||||||
|
PARTY_RED: 7,
|
||||||
|
PARTY_CANCEL_BUTTON: 8,
|
||||||
|
INSTRUCTIONS_TEXT: 9,
|
||||||
|
MOVE_LABEL: 10,
|
||||||
|
SUMMARY: 11,
|
||||||
|
SUMMARY_DEX_NUM: 12,
|
||||||
|
SUMMARY_DEX_NUM_GOLD: 13,
|
||||||
|
SUMMARY_ALT: 14,
|
||||||
|
SUMMARY_HEADER: 15,
|
||||||
|
SUMMARY_RED: 16,
|
||||||
|
SUMMARY_BLUE: 17,
|
||||||
|
SUMMARY_PINK: 18,
|
||||||
|
SUMMARY_GOLD: 19,
|
||||||
|
SUMMARY_GRAY: 20,
|
||||||
|
SUMMARY_GREEN: 21,
|
||||||
|
SUMMARY_STATS: 22,
|
||||||
|
SUMMARY_STATS_BLUE: 23,
|
||||||
|
SUMMARY_STATS_PINK: 24,
|
||||||
|
SUMMARY_STATS_GOLD: 25,
|
||||||
|
LUCK_VALUE: 26,
|
||||||
|
STATS_HEXAGON: 27,
|
||||||
|
GROWTH_RATE_TYPE: 28,
|
||||||
|
MONEY: 29, // Money default styling (pale yellow)
|
||||||
|
MONEY_WINDOW: 30, // Money displayed in Windows (needs different colors based on theme)
|
||||||
|
HEADER_LABEL: 31,
|
||||||
|
STATS_LABEL: 32,
|
||||||
|
STATS_VALUE: 33,
|
||||||
|
SETTINGS_VALUE: 34,
|
||||||
|
SETTINGS_LABEL: 35,
|
||||||
|
SETTINGS_LABEL_NAVBAR: 36,
|
||||||
|
SETTINGS_SELECTED: 37,
|
||||||
|
SETTINGS_LOCKED: 38,
|
||||||
|
EGG_LIST: 39,
|
||||||
|
EGG_SUMMARY_NAME: 40,
|
||||||
|
EGG_SUMMARY_DEX: 41,
|
||||||
|
STARTER_VALUE_LIMIT: 42,
|
||||||
|
TOOLTIP_TITLE: 43,
|
||||||
|
TOOLTIP_CONTENT: 44,
|
||||||
|
FILTER_BAR_MAIN: 45,
|
||||||
|
MOVE_INFO_CONTENT: 46,
|
||||||
|
MOVE_PP_FULL: 47,
|
||||||
|
MOVE_PP_HALF_FULL: 48,
|
||||||
|
MOVE_PP_NEAR_EMPTY: 49,
|
||||||
|
MOVE_PP_EMPTY: 50,
|
||||||
|
SMALLER_WINDOW_ALT: 51,
|
||||||
|
BGM_BAR: 52,
|
||||||
|
PERFECT_IV: 53,
|
||||||
|
ME_OPTION_DEFAULT: 54, // Default style for choices in ME
|
||||||
|
ME_OPTION_SPECIAL: 55, // Style for choices with special requirements in ME
|
||||||
|
SHADOW_TEXT: 56 // to obscure unavailable options
|
||||||
|
})
|
||||||
|
export type TextStyle = typeof TextStyle[keyof typeof TextStyle];
|
@ -1,9 +1,10 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { BattlerIndex } from "#enums/battler-index";
|
import type { BattlerIndex } from "#enums/battler-index";
|
||||||
import { HitResult } from "#enums/hit-result";
|
import { HitResult } from "#enums/hit-result";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { Pokemon } from "#field/pokemon";
|
import type { Pokemon } from "#field/pokemon";
|
||||||
import type { DamageResult } from "#types/damage-result";
|
import type { DamageResult } from "#types/damage-result";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { fixedInt, formatStat } from "#utils/common";
|
import { fixedInt, formatStat } from "#utils/common";
|
||||||
|
|
||||||
type TextAndShadowArr = [string | null, string | null];
|
type TextAndShadowArr = [string | null, string | null];
|
||||||
|
@ -5,10 +5,11 @@ import { coerceArray, fixedInt, randInt } from "#utils/common";
|
|||||||
export class PokemonSpriteSparkleHandler {
|
export class PokemonSpriteSparkleHandler {
|
||||||
private sprites: Set<Phaser.GameObjects.Sprite>;
|
private sprites: Set<Phaser.GameObjects.Sprite>;
|
||||||
|
|
||||||
|
private counterTween?: Phaser.Tweens.Tween;
|
||||||
|
|
||||||
setup(): void {
|
setup(): void {
|
||||||
this.sprites = new Set();
|
this.sprites = new Set();
|
||||||
|
this.counterTween = globalScene.tweens.addCounter({
|
||||||
globalScene.tweens.addCounter({
|
|
||||||
duration: fixedInt(200),
|
duration: fixedInt(200),
|
||||||
from: 0,
|
from: 0,
|
||||||
to: 1,
|
to: 1,
|
||||||
@ -78,4 +79,12 @@ export class PokemonSpriteSparkleHandler {
|
|||||||
this.sprites.delete(s);
|
this.sprites.delete(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
destroy(): void {
|
||||||
|
this.removeAll();
|
||||||
|
if (this.counterTween) {
|
||||||
|
this.counterTween.destroy();
|
||||||
|
this.counterTween = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,6 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
* TODO: Stop treating this like a unique ID and stop treating 0 as no pokemon
|
* TODO: Stop treating this like a unique ID and stop treating 0 as no pokemon
|
||||||
*/
|
*/
|
||||||
public id: number;
|
public id: number;
|
||||||
public name: string;
|
|
||||||
public nickname: string;
|
public nickname: string;
|
||||||
public species: PokemonSpecies;
|
public species: PokemonSpecies;
|
||||||
public formIndex: number;
|
public formIndex: number;
|
||||||
@ -442,10 +441,9 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
* @returns The name to render for this {@linkcode Pokemon}.
|
* @returns The name to render for this {@linkcode Pokemon}.
|
||||||
*/
|
*/
|
||||||
getNameToRender(useIllusion = true) {
|
getNameToRender(useIllusion = true) {
|
||||||
const name: string =
|
const illusion = this.summonData.illusion;
|
||||||
!useIllusion && this.summonData.illusion ? this.summonData.illusion.basePokemon.name : this.name;
|
const name = useIllusion ? (illusion?.name ?? this.name) : this.name;
|
||||||
const nickname: string =
|
const nickname: string = useIllusion ? (illusion?.nickname ?? this.nickname) : this.nickname;
|
||||||
!useIllusion && this.summonData.illusion ? this.summonData.illusion.basePokemon.nickname : this.nickname;
|
|
||||||
try {
|
try {
|
||||||
if (nickname) {
|
if (nickname) {
|
||||||
return decodeURIComponent(escape(atob(nickname))); // TODO: Remove `atob` and `escape`... eventually...
|
return decodeURIComponent(escape(atob(nickname))); // TODO: Remove `atob` and `escape`... eventually...
|
||||||
@ -463,7 +461,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
* @returns The {@linkcode PokeballType} that will be shown when this Pokemon is sent out into battle.
|
* @returns The {@linkcode PokeballType} that will be shown when this Pokemon is sent out into battle.
|
||||||
*/
|
*/
|
||||||
getPokeball(useIllusion = false): PokeballType {
|
getPokeball(useIllusion = false): PokeballType {
|
||||||
return useIllusion && this.summonData.illusion ? this.summonData.illusion.pokeball : this.pokeball;
|
return useIllusion ? (this.summonData.illusion?.pokeball ?? this.pokeball) : this.pokeball;
|
||||||
}
|
}
|
||||||
|
|
||||||
init(): void {
|
init(): void {
|
||||||
@ -609,24 +607,33 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate an illusion of the last pokemon in the party, as other wild pokemon in the area.
|
* Set this pokemon's illusion to the data of the given pokemon.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* When setting the illusion of a wild pokemon, a {@linkcode PokemonSpecies} is generally passed.
|
||||||
|
* When setting the illusion of a pokemon in this way, the fields required by illusion data
|
||||||
|
* but missing from `PokemonSpecies` are set as follows
|
||||||
|
* - `pokeball` and `nickname` are both inherited from this pokemon
|
||||||
|
* - `shiny` will always be set if this pokemon OR its fusion is shiny
|
||||||
|
* - `variant` will always be 0
|
||||||
|
* - Fields related to fusion will be set to `undefined` or `0` as appropriate
|
||||||
|
* - The gender is set to be the same as this pokemon, if it is compatible with the provided pokemon.
|
||||||
|
* - If the provided pokemon can only ever exist as one gender, it is always that gender
|
||||||
|
* - If this pokemon is genderless but the provided pokemon isn't, then a gender roll is done based on this
|
||||||
|
* pokemon's ID
|
||||||
*/
|
*/
|
||||||
setIllusion(pokemon: Pokemon): boolean {
|
setIllusion(pokemon: Pokemon | PokemonSpecies): boolean {
|
||||||
if (this.summonData.illusion) {
|
this.breakIllusion();
|
||||||
this.breakIllusion();
|
if (pokemon instanceof Pokemon) {
|
||||||
}
|
|
||||||
if (this.hasTrainer()) {
|
|
||||||
const speciesId = pokemon.species.speciesId;
|
const speciesId = pokemon.species.speciesId;
|
||||||
|
|
||||||
this.summonData.illusion = {
|
this.summonData.illusion = {
|
||||||
basePokemon: {
|
name: pokemon.name,
|
||||||
name: this.name,
|
nickname: pokemon.nickname,
|
||||||
nickname: this.nickname,
|
shiny: pokemon.shiny,
|
||||||
shiny: this.shiny,
|
variant: pokemon.variant,
|
||||||
variant: this.variant,
|
fusionShiny: pokemon.fusionShiny,
|
||||||
fusionShiny: this.fusionShiny,
|
fusionVariant: pokemon.fusionVariant,
|
||||||
fusionVariant: this.fusionVariant,
|
|
||||||
},
|
|
||||||
species: speciesId,
|
species: speciesId,
|
||||||
formIndex: pokemon.formIndex,
|
formIndex: pokemon.formIndex,
|
||||||
gender: pokemon.gender,
|
gender: pokemon.gender,
|
||||||
@ -636,54 +643,61 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
fusionGender: pokemon.fusionGender,
|
fusionGender: pokemon.fusionGender,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.name = pokemon.name;
|
if (pokemon.shiny || pokemon.fusionShiny) {
|
||||||
this.nickname = pokemon.nickname;
|
|
||||||
this.shiny = pokemon.shiny;
|
|
||||||
this.variant = pokemon.variant;
|
|
||||||
this.fusionVariant = pokemon.fusionVariant;
|
|
||||||
this.fusionShiny = pokemon.fusionShiny;
|
|
||||||
if (this.shiny) {
|
|
||||||
this.initShinySparkle();
|
this.initShinySparkle();
|
||||||
}
|
}
|
||||||
this.loadAssets(false, true).then(() => this.playAnim());
|
|
||||||
this.updateInfo();
|
|
||||||
} else {
|
} else {
|
||||||
const randomIllusion: PokemonSpecies = globalScene.arena.randomSpecies(
|
// Correct the gender in case the illusioned species has a gender incompatible with this pokemon
|
||||||
globalScene.currentBattle.waveIndex,
|
let gender = this.gender;
|
||||||
this.level,
|
switch (pokemon.malePercent) {
|
||||||
);
|
case null:
|
||||||
|
gender = Gender.GENDERLESS;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
gender = Gender.FEMALE;
|
||||||
|
break;
|
||||||
|
case 100:
|
||||||
|
gender = Gender.MALE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gender = (this.id % 256) * 0.390625 < pokemon.malePercent ? Gender.MALE : Gender.FEMALE;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
TODO: Allow setting `variant` to something other than 0, which would require first loading the
|
||||||
|
assets for the provided species, as its entry would otherwise not
|
||||||
|
be guaranteed to exist in the `variantData` map. But this would prevent `summonData` from being populated
|
||||||
|
until the assets are loaded, which would cause issues as this method cannot be easily promisified.
|
||||||
|
*/
|
||||||
this.summonData.illusion = {
|
this.summonData.illusion = {
|
||||||
basePokemon: {
|
fusionShiny: false,
|
||||||
name: this.name,
|
fusionVariant: 0,
|
||||||
nickname: this.nickname,
|
shiny: this.shiny || this.fusionShiny,
|
||||||
shiny: this.shiny,
|
variant: 0,
|
||||||
variant: this.variant,
|
nickname: this.nickname,
|
||||||
fusionShiny: this.fusionShiny,
|
name: pokemon.name,
|
||||||
fusionVariant: this.fusionVariant,
|
species: pokemon.speciesId,
|
||||||
},
|
formIndex: pokemon.formIndex,
|
||||||
species: randomIllusion.speciesId,
|
gender,
|
||||||
formIndex: randomIllusion.formIndex,
|
|
||||||
gender: this.gender,
|
|
||||||
pokeball: this.pokeball,
|
pokeball: this.pokeball,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.name = randomIllusion.name;
|
if (this.shiny || this.fusionShiny) {
|
||||||
this.loadAssets(false, true).then(() => this.playAnim());
|
this.initShinySparkle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this.loadAssets(false, true).then(() => this.playAnim());
|
||||||
|
this.updateInfo();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Break the illusion of this pokemon, if it has an active illusion.
|
||||||
|
* @returns Whether an illusion was broken.
|
||||||
|
*/
|
||||||
breakIllusion(): boolean {
|
breakIllusion(): boolean {
|
||||||
if (!this.summonData.illusion) {
|
if (!this.summonData.illusion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.name = this.summonData.illusion.basePokemon.name;
|
|
||||||
this.nickname = this.summonData.illusion.basePokemon.nickname;
|
|
||||||
this.shiny = this.summonData.illusion.basePokemon.shiny;
|
|
||||||
this.variant = this.summonData.illusion.basePokemon.variant;
|
|
||||||
this.fusionVariant = this.summonData.illusion.basePokemon.fusionVariant;
|
|
||||||
this.fusionShiny = this.summonData.illusion.basePokemon.fusionShiny;
|
|
||||||
this.summonData.illusion = null;
|
this.summonData.illusion = null;
|
||||||
if (this.isOnField()) {
|
if (this.isOnField()) {
|
||||||
globalScene.playSound("PRSFX- Transform");
|
globalScene.playSound("PRSFX- Transform");
|
||||||
@ -718,8 +732,12 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
// Assets for moves
|
// Assets for moves
|
||||||
loadPromises.push(loadMoveAnimations(this.getMoveset().map(m => m.getMove().id)));
|
loadPromises.push(loadMoveAnimations(this.getMoveset().map(m => m.getMove().id)));
|
||||||
|
|
||||||
|
/** alias for `this.summonData.illusion`; bangs on this are safe when guarded with `useIllusion` being true */
|
||||||
|
const illusion = this.summonData.illusion;
|
||||||
|
useIllusion = useIllusion && !!illusion;
|
||||||
|
|
||||||
// Load the assets for the species form
|
// Load the assets for the species form
|
||||||
const formIndex = useIllusion && this.summonData.illusion ? this.summonData.illusion.formIndex : this.formIndex;
|
const formIndex = useIllusion ? illusion!.formIndex : this.formIndex;
|
||||||
loadPromises.push(
|
loadPromises.push(
|
||||||
this.getSpeciesForm(false, useIllusion).loadAssets(
|
this.getSpeciesForm(false, useIllusion).loadAssets(
|
||||||
this.getGender(useIllusion) === Gender.FEMALE,
|
this.getGender(useIllusion) === Gender.FEMALE,
|
||||||
@ -736,16 +754,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (this.getFusionSpeciesForm()) {
|
if (this.getFusionSpeciesForm()) {
|
||||||
const fusionFormIndex =
|
const { fusionFormIndex, fusionShiny, fusionVariant } = useIllusion ? illusion! : this;
|
||||||
useIllusion && this.summonData.illusion ? this.summonData.illusion.fusionFormIndex : this.fusionFormIndex;
|
|
||||||
const fusionShiny =
|
|
||||||
!useIllusion && this.summonData.illusion?.basePokemon
|
|
||||||
? this.summonData.illusion.basePokemon.fusionShiny
|
|
||||||
: this.fusionShiny;
|
|
||||||
const fusionVariant =
|
|
||||||
!useIllusion && this.summonData.illusion?.basePokemon
|
|
||||||
? this.summonData.illusion.basePokemon.fusionVariant
|
|
||||||
: this.fusionVariant;
|
|
||||||
loadPromises.push(
|
loadPromises.push(
|
||||||
this.getFusionSpeciesForm(false, useIllusion).loadAssets(
|
this.getFusionSpeciesForm(false, useIllusion).loadAssets(
|
||||||
this.getFusionGender(false, useIllusion) === Gender.FEMALE,
|
this.getFusionGender(false, useIllusion) === Gender.FEMALE,
|
||||||
@ -933,8 +942,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
return this.getSpeciesForm(ignoreOverride, false).getSpriteKey(
|
return this.getSpeciesForm(ignoreOverride, false).getSpriteKey(
|
||||||
this.getGender(ignoreOverride) === Gender.FEMALE,
|
this.getGender(ignoreOverride) === Gender.FEMALE,
|
||||||
this.formIndex,
|
this.formIndex,
|
||||||
this.summonData.illusion?.basePokemon.shiny ?? this.shiny,
|
this.isShiny(false),
|
||||||
this.summonData.illusion?.basePokemon.variant ?? this.variant,
|
this.getVariant(false),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -977,11 +986,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getIconAtlasKey(ignoreOverride = false, useIllusion = true): string {
|
getIconAtlasKey(ignoreOverride = false, useIllusion = true): string {
|
||||||
// TODO: confirm the correct behavior here (is it intentional that the check fails if `illusion.formIndex` is `0`?)
|
const illusion = this.summonData.illusion;
|
||||||
const formIndex =
|
const { formIndex, variant } = useIllusion && illusion ? illusion : this;
|
||||||
useIllusion && this.summonData.illusion?.formIndex ? this.summonData.illusion.formIndex : this.formIndex;
|
|
||||||
const variant =
|
|
||||||
!useIllusion && this.summonData.illusion ? this.summonData.illusion.basePokemon.variant : this.variant;
|
|
||||||
return this.getSpeciesForm(ignoreOverride, useIllusion).getIconAtlasKey(
|
return this.getSpeciesForm(ignoreOverride, useIllusion).getIconAtlasKey(
|
||||||
formIndex,
|
formIndex,
|
||||||
this.isBaseShiny(useIllusion),
|
this.isBaseShiny(useIllusion),
|
||||||
@ -990,15 +996,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getFusionIconAtlasKey(ignoreOverride = false, useIllusion = true): string {
|
getFusionIconAtlasKey(ignoreOverride = false, useIllusion = true): string {
|
||||||
// TODO: confirm the correct behavior here (is it intentional that the check fails if `illusion.fusionFormIndex` is `0`?)
|
const illusion = this.summonData.illusion;
|
||||||
const fusionFormIndex =
|
const { fusionFormIndex, fusionVariant } = useIllusion && illusion ? illusion : this;
|
||||||
useIllusion && this.summonData.illusion?.fusionFormIndex
|
|
||||||
? this.summonData.illusion.fusionFormIndex
|
|
||||||
: this.fusionFormIndex;
|
|
||||||
const fusionVariant =
|
|
||||||
!useIllusion && this.summonData.illusion
|
|
||||||
? this.summonData.illusion.basePokemon.fusionVariant
|
|
||||||
: this.fusionVariant;
|
|
||||||
return this.getFusionSpeciesForm(ignoreOverride, useIllusion).getIconAtlasKey(
|
return this.getFusionSpeciesForm(ignoreOverride, useIllusion).getIconAtlasKey(
|
||||||
fusionFormIndex,
|
fusionFormIndex,
|
||||||
this.isFusionShiny(),
|
this.isFusionShiny(),
|
||||||
@ -1006,11 +1005,9 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getIconId(ignoreOverride?: boolean, useIllusion = true): string {
|
getIconId(ignoreOverride?: boolean, useIllusion = false): string {
|
||||||
const formIndex =
|
const illusion = this.summonData.illusion;
|
||||||
useIllusion && this.summonData.illusion?.formIndex ? this.summonData.illusion?.formIndex : this.formIndex;
|
const { formIndex, variant } = useIllusion && illusion ? illusion : this;
|
||||||
const variant =
|
|
||||||
!useIllusion && !!this.summonData.illusion ? this.summonData.illusion?.basePokemon.variant : this.variant;
|
|
||||||
return this.getSpeciesForm(ignoreOverride, useIllusion).getIconId(
|
return this.getSpeciesForm(ignoreOverride, useIllusion).getIconId(
|
||||||
this.getGender(ignoreOverride, useIllusion) === Gender.FEMALE,
|
this.getGender(ignoreOverride, useIllusion) === Gender.FEMALE,
|
||||||
formIndex,
|
formIndex,
|
||||||
@ -1020,14 +1017,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getFusionIconId(ignoreOverride?: boolean, useIllusion = true): string {
|
getFusionIconId(ignoreOverride?: boolean, useIllusion = true): string {
|
||||||
const fusionFormIndex =
|
const illusion = this.summonData.illusion;
|
||||||
useIllusion && this.summonData.illusion?.fusionFormIndex
|
const { fusionFormIndex, fusionVariant } = useIllusion && illusion ? illusion : this;
|
||||||
? this.summonData.illusion?.fusionFormIndex
|
|
||||||
: this.fusionFormIndex;
|
|
||||||
const fusionVariant =
|
|
||||||
!useIllusion && !!this.summonData.illusion
|
|
||||||
? this.summonData.illusion?.basePokemon.fusionVariant
|
|
||||||
: this.fusionVariant;
|
|
||||||
return this.getFusionSpeciesForm(ignoreOverride, useIllusion).getIconId(
|
return this.getFusionSpeciesForm(ignoreOverride, useIllusion).getIconId(
|
||||||
this.getFusionGender(ignoreOverride, useIllusion) === Gender.FEMALE,
|
this.getFusionGender(ignoreOverride, useIllusion) === Gender.FEMALE,
|
||||||
fusionFormIndex,
|
fusionFormIndex,
|
||||||
@ -1702,29 +1693,18 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
* @returns Whether this Pokemon is shiny
|
* @returns Whether this Pokemon is shiny
|
||||||
*/
|
*/
|
||||||
isShiny(useIllusion = false): boolean {
|
isShiny(useIllusion = false): boolean {
|
||||||
if (!useIllusion && this.summonData.illusion) {
|
return this.isBaseShiny(useIllusion) || this.isFusionShiny(useIllusion);
|
||||||
return (
|
|
||||||
this.summonData.illusion.basePokemon?.shiny ||
|
|
||||||
(this.summonData.illusion.fusionSpecies && this.summonData.illusion.basePokemon?.fusionShiny) ||
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.shiny || (this.isFusion(useIllusion) && this.fusionShiny);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isBaseShiny(useIllusion = false) {
|
isBaseShiny(useIllusion = false) {
|
||||||
if (!useIllusion && this.summonData.illusion) {
|
return useIllusion ? (this.summonData.illusion?.shiny ?? this.shiny) : this.shiny;
|
||||||
return !!this.summonData.illusion.basePokemon?.shiny;
|
|
||||||
}
|
|
||||||
return this.shiny;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isFusionShiny(useIllusion = false) {
|
isFusionShiny(useIllusion = false) {
|
||||||
if (!useIllusion && this.summonData.illusion) {
|
if (!this.isFusion(useIllusion)) {
|
||||||
return !!this.summonData.illusion.basePokemon?.fusionShiny;
|
return false;
|
||||||
}
|
}
|
||||||
return this.isFusion(useIllusion) && this.fusionShiny;
|
return useIllusion ? (this.summonData.illusion?.fusionShiny ?? this.fusionShiny) : this.fusionShiny;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1733,39 +1713,48 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
* @returns Whether this pokemon's base and fusion counterparts are both shiny.
|
* @returns Whether this pokemon's base and fusion counterparts are both shiny.
|
||||||
*/
|
*/
|
||||||
isDoubleShiny(useIllusion = false): boolean {
|
isDoubleShiny(useIllusion = false): boolean {
|
||||||
if (!useIllusion && this.summonData.illusion?.basePokemon) {
|
return this.isFusion(useIllusion) && this.isBaseShiny(useIllusion) && this.isFusionShiny(useIllusion);
|
||||||
return (
|
|
||||||
this.isFusion(false) &&
|
|
||||||
this.summonData.illusion.basePokemon.shiny &&
|
|
||||||
this.summonData.illusion.basePokemon.fusionShiny
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.isFusion(useIllusion) && this.shiny && this.fusionShiny;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return this Pokemon's {@linkcode Variant | shiny variant}.
|
* Return this Pokemon's {@linkcode Variant | shiny variant}.
|
||||||
|
* If a fusion, returns the maximum of the two variants.
|
||||||
* Only meaningful if this pokemon is actually shiny.
|
* Only meaningful if this pokemon is actually shiny.
|
||||||
* @param useIllusion - Whether to consider this pokemon's illusion if present; default `false`
|
* @param useIllusion - Whether to consider this pokemon's illusion if present; default `false`
|
||||||
* @returns The shiny variant of this Pokemon.
|
* @returns The shiny variant of this Pokemon.
|
||||||
*/
|
*/
|
||||||
getVariant(useIllusion = false): Variant {
|
getVariant(useIllusion = false): Variant {
|
||||||
if (!useIllusion && this.summonData.illusion) {
|
const illusion = this.summonData.illusion;
|
||||||
return !this.isFusion(false)
|
const baseVariant = useIllusion ? (illusion?.variant ?? this.variant) : this.variant;
|
||||||
? this.summonData.illusion.basePokemon!.variant
|
if (!this.isFusion(useIllusion)) {
|
||||||
: (Math.max(this.variant, this.fusionVariant) as Variant);
|
return baseVariant;
|
||||||
}
|
}
|
||||||
|
const fusionVariant = useIllusion ? (illusion?.fusionVariant ?? this.fusionVariant) : this.fusionVariant;
|
||||||
return !this.isFusion(true) ? this.variant : (Math.max(this.variant, this.fusionVariant) as Variant);
|
return Math.max(baseVariant, fusionVariant) as Variant;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Clarify how this differs from `getVariant`
|
/**
|
||||||
getBaseVariant(doubleShiny: boolean): Variant {
|
* Return the base pokemon's variant. Equivalent to {@linkcode getVariant} if this pokemon is not a fusion.
|
||||||
if (doubleShiny) {
|
* @returns The shiny variant of this Pokemon's base species.
|
||||||
return this.summonData.illusion?.basePokemon?.variant ?? this.variant;
|
*/
|
||||||
|
getBaseVariant(useIllusion = false): Variant {
|
||||||
|
const illusion = this.summonData.illusion;
|
||||||
|
return useIllusion && illusion ? (illusion.variant ?? this.variant) : this.variant;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the fused pokemon's variant.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* Always returns `0` if the pokemon is not a fusion.
|
||||||
|
* @returns The shiny variant of this pokemon's fusion species.
|
||||||
|
*/
|
||||||
|
getFusionVariant(useIllusion = false): Variant {
|
||||||
|
if (!this.isFusion(useIllusion)) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
return this.getVariant();
|
const illusion = this.summonData.illusion;
|
||||||
|
return illusion ? (illusion.fusionVariant ?? this.fusionVariant) : this.fusionVariant;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1782,7 +1771,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
* @returns Whether this Pokemon is currently fused with another species.
|
* @returns Whether this Pokemon is currently fused with another species.
|
||||||
*/
|
*/
|
||||||
isFusion(useIllusion = false): boolean {
|
isFusion(useIllusion = false): boolean {
|
||||||
return useIllusion && this.summonData.illusion ? !!this.summonData.illusion.fusionSpecies : !!this.fusionSpecies;
|
return useIllusion ? !!this.summonData.illusion?.fusionSpecies : !!this.fusionSpecies;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1792,9 +1781,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
* @see {@linkcode getNameToRender} - gets this Pokemon's display name.
|
* @see {@linkcode getNameToRender} - gets this Pokemon's display name.
|
||||||
*/
|
*/
|
||||||
getName(useIllusion = false): string {
|
getName(useIllusion = false): string {
|
||||||
return !useIllusion && this.summonData.illusion?.basePokemon
|
return useIllusion ? (this.summonData.illusion?.name ?? this.name) : this.name;
|
||||||
? this.summonData.illusion.basePokemon.name
|
|
||||||
: this.name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -5676,7 +5663,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PlayerPokemon extends Pokemon {
|
export class PlayerPokemon extends Pokemon {
|
||||||
protected battleInfo: PlayerBattleInfo;
|
protected declare battleInfo: PlayerBattleInfo;
|
||||||
public compatibleTms: MoveId[];
|
public compatibleTms: MoveId[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -6205,7 +6192,7 @@ export class PlayerPokemon extends Pokemon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class EnemyPokemon extends Pokemon {
|
export class EnemyPokemon extends Pokemon {
|
||||||
protected battleInfo: EnemyBattleInfo;
|
protected declare battleInfo: EnemyBattleInfo;
|
||||||
public trainerSlot: TrainerSlot;
|
public trainerSlot: TrainerSlot;
|
||||||
public aiType: AiType;
|
public aiType: AiType;
|
||||||
public bossSegments: number;
|
public bossSegments: number;
|
||||||
|
@ -23,13 +23,13 @@ import {
|
|||||||
} from "#trainers/trainer-party-template";
|
} from "#trainers/trainer-party-template";
|
||||||
import { randSeedInt, randSeedItem, randSeedWeightedItem } from "#utils/common";
|
import { randSeedInt, randSeedItem, randSeedWeightedItem } from "#utils/common";
|
||||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||||
|
import { toSnakeCase } from "#utils/strings";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class Trainer extends Phaser.GameObjects.Container {
|
export class Trainer extends Phaser.GameObjects.Container {
|
||||||
public config: TrainerConfig;
|
public config: TrainerConfig;
|
||||||
public variant: TrainerVariant;
|
public variant: TrainerVariant;
|
||||||
public partyTemplateIndex: number;
|
public partyTemplateIndex: number;
|
||||||
public name: string;
|
|
||||||
public partnerName: string;
|
public partnerName: string;
|
||||||
public nameKey: string;
|
public nameKey: string;
|
||||||
public partnerNameKey: string | undefined;
|
public partnerNameKey: string | undefined;
|
||||||
@ -170,7 +170,7 @@ export class Trainer extends Phaser.GameObjects.Container {
|
|||||||
const evilTeamTitles = ["grunt"];
|
const evilTeamTitles = ["grunt"];
|
||||||
if (this.name === "" && evilTeamTitles.some(t => name.toLocaleLowerCase().includes(t))) {
|
if (this.name === "" && evilTeamTitles.some(t => name.toLocaleLowerCase().includes(t))) {
|
||||||
// This is a evil team grunt so we localize it by only using the "name" as the title
|
// This is a evil team grunt so we localize it by only using the "name" as the title
|
||||||
title = i18next.t(`trainerClasses:${name.toLowerCase().replace(/\s/g, "_")}`);
|
title = i18next.t(`trainerClasses:${toSnakeCase(name)}`);
|
||||||
console.log("Localized grunt name: " + title);
|
console.log("Localized grunt name: " + title);
|
||||||
// Since grunts are not named we can just return the title
|
// Since grunts are not named we can just return the title
|
||||||
return title;
|
return title;
|
||||||
@ -187,7 +187,7 @@ export class Trainer extends Phaser.GameObjects.Container {
|
|||||||
}
|
}
|
||||||
// Get the localized trainer class name from the i18n file and set it as the title.
|
// Get the localized trainer class name from the i18n file and set it as the title.
|
||||||
// This is used for trainer class names, not titles like "Elite Four, Champion, etc."
|
// This is used for trainer class names, not titles like "Elite Four, Champion, etc."
|
||||||
title = i18next.t(`trainerClasses:${name.toLowerCase().replace(/\s/g, "_")}`);
|
title = i18next.t(`trainerClasses:${toSnakeCase(name)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no specific trainer slot is set.
|
// If no specific trainer slot is set.
|
||||||
@ -208,7 +208,7 @@ export class Trainer extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
if (this.config.titleDouble && this.variant === TrainerVariant.DOUBLE && !this.config.doubleOnly) {
|
if (this.config.titleDouble && this.variant === TrainerVariant.DOUBLE && !this.config.doubleOnly) {
|
||||||
title = this.config.titleDouble;
|
title = this.config.titleDouble;
|
||||||
name = i18next.t(`trainerNames:${this.config.nameDouble.toLowerCase().replace(/\s/g, "_")}`);
|
name = i18next.t(`trainerNames:${toSnakeCase(this.config.nameDouble)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(title ? `${title} ${name}` : name);
|
console.log(title ? `${title} ${name}` : name);
|
||||||
|
@ -23,6 +23,7 @@ import type { PokemonType } from "#enums/pokemon-type";
|
|||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { BATTLE_STATS, type PermanentStat, Stat, TEMP_BATTLE_STATS, type TempBattleStat } from "#enums/stat";
|
import { BATTLE_STATS, type PermanentStat, Stat, TEMP_BATTLE_STATS, type TempBattleStat } from "#enums/stat";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { PlayerPokemon, Pokemon } from "#field/pokemon";
|
import type { PlayerPokemon, Pokemon } from "#field/pokemon";
|
||||||
import type {
|
import type {
|
||||||
DoubleBattleChanceBoosterModifierType,
|
DoubleBattleChanceBoosterModifierType,
|
||||||
@ -40,7 +41,7 @@ import type {
|
|||||||
} from "#modifiers/modifier-type";
|
} from "#modifiers/modifier-type";
|
||||||
import type { VoucherType } from "#system/voucher";
|
import type { VoucherType } from "#system/voucher";
|
||||||
import type { ModifierInstanceMap, ModifierString } from "#types/modifier-types";
|
import type { ModifierInstanceMap, ModifierString } from "#types/modifier-types";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { BooleanHolder, hslToHex, isNullOrUndefined, NumberHolder, randSeedFloat, toDmgValue } from "#utils/common";
|
import { BooleanHolder, hslToHex, isNullOrUndefined, NumberHolder, randSeedFloat, toDmgValue } from "#utils/common";
|
||||||
import { getModifierType } from "#utils/modifier-utils";
|
import { getModifierType } from "#utils/modifier-utils";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
@ -461,7 +462,7 @@ export abstract class LapsingPersistentModifier extends PersistentModifier {
|
|||||||
* @see {@linkcode apply}
|
* @see {@linkcode apply}
|
||||||
*/
|
*/
|
||||||
export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier {
|
export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier {
|
||||||
public override type: DoubleBattleChanceBoosterModifierType;
|
public declare type: DoubleBattleChanceBoosterModifierType;
|
||||||
|
|
||||||
match(modifier: Modifier): boolean {
|
match(modifier: Modifier): boolean {
|
||||||
return modifier instanceof DoubleBattleChanceBoosterModifier && modifier.getMaxBattles() === this.getMaxBattles();
|
return modifier instanceof DoubleBattleChanceBoosterModifier && modifier.getMaxBattles() === this.getMaxBattles();
|
||||||
@ -935,7 +936,7 @@ export class EvoTrackerModifier extends PokemonHeldItemModifier {
|
|||||||
* Currently used by Shuckle Juice item
|
* Currently used by Shuckle Juice item
|
||||||
*/
|
*/
|
||||||
export class PokemonBaseStatTotalModifier extends PokemonHeldItemModifier {
|
export class PokemonBaseStatTotalModifier extends PokemonHeldItemModifier {
|
||||||
public override type: PokemonBaseStatTotalModifierType;
|
public declare type: PokemonBaseStatTotalModifierType;
|
||||||
public isTransferable = false;
|
public isTransferable = false;
|
||||||
public statModifier: 10 | -15;
|
public statModifier: 10 | -15;
|
||||||
|
|
||||||
@ -2073,7 +2074,7 @@ export abstract class ConsumablePokemonModifier extends ConsumableModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class TerrastalizeModifier extends ConsumablePokemonModifier {
|
export class TerrastalizeModifier extends ConsumablePokemonModifier {
|
||||||
public override type: TerastallizeModifierType;
|
public declare type: TerastallizeModifierType;
|
||||||
public teraType: PokemonType;
|
public teraType: PokemonType;
|
||||||
|
|
||||||
constructor(type: TerastallizeModifierType, pokemonId: number, teraType: PokemonType) {
|
constructor(type: TerastallizeModifierType, pokemonId: number, teraType: PokemonType) {
|
||||||
@ -2317,7 +2318,7 @@ export class PokemonLevelIncrementModifier extends ConsumablePokemonModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class TmModifier extends ConsumablePokemonModifier {
|
export class TmModifier extends ConsumablePokemonModifier {
|
||||||
public override type: TmModifierType;
|
public declare type: TmModifierType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies {@linkcode TmModifier}
|
* Applies {@linkcode TmModifier}
|
||||||
@ -2364,7 +2365,7 @@ export class RememberMoveModifier extends ConsumablePokemonModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class EvolutionItemModifier extends ConsumablePokemonModifier {
|
export class EvolutionItemModifier extends ConsumablePokemonModifier {
|
||||||
public override type: EvolutionItemModifierType;
|
public declare type: EvolutionItemModifierType;
|
||||||
/**
|
/**
|
||||||
* Applies {@linkcode EvolutionItemModifier}
|
* Applies {@linkcode EvolutionItemModifier}
|
||||||
* @param playerPokemon The {@linkcode PlayerPokemon} that should evolve via item
|
* @param playerPokemon The {@linkcode PlayerPokemon} that should evolve via item
|
||||||
@ -2529,7 +2530,7 @@ export class ExpBoosterModifier extends PersistentModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PokemonExpBoosterModifier extends PokemonHeldItemModifier {
|
export class PokemonExpBoosterModifier extends PokemonHeldItemModifier {
|
||||||
public override type: PokemonExpBoosterModifierType;
|
public declare type: PokemonExpBoosterModifierType;
|
||||||
|
|
||||||
private boostMultiplier: number;
|
private boostMultiplier: number;
|
||||||
|
|
||||||
@ -2626,7 +2627,7 @@ export class ExpBalanceModifier extends PersistentModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PokemonFriendshipBoosterModifier extends PokemonHeldItemModifier {
|
export class PokemonFriendshipBoosterModifier extends PokemonHeldItemModifier {
|
||||||
public override type: PokemonFriendshipBoosterModifierType;
|
public declare type: PokemonFriendshipBoosterModifierType;
|
||||||
|
|
||||||
matchType(modifier: Modifier): boolean {
|
matchType(modifier: Modifier): boolean {
|
||||||
return modifier instanceof PokemonFriendshipBoosterModifier;
|
return modifier instanceof PokemonFriendshipBoosterModifier;
|
||||||
@ -2683,7 +2684,7 @@ export class PokemonNatureWeightModifier extends PokemonHeldItemModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PokemonMoveAccuracyBoosterModifier extends PokemonHeldItemModifier {
|
export class PokemonMoveAccuracyBoosterModifier extends PokemonHeldItemModifier {
|
||||||
public override type: PokemonMoveAccuracyBoosterModifierType;
|
public declare type: PokemonMoveAccuracyBoosterModifierType;
|
||||||
private accuracyAmount: number;
|
private accuracyAmount: number;
|
||||||
|
|
||||||
constructor(type: PokemonMoveAccuracyBoosterModifierType, pokemonId: number, accuracy: number, stackCount?: number) {
|
constructor(type: PokemonMoveAccuracyBoosterModifierType, pokemonId: number, accuracy: number, stackCount?: number) {
|
||||||
@ -2735,7 +2736,7 @@ export class PokemonMoveAccuracyBoosterModifier extends PokemonHeldItemModifier
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PokemonMultiHitModifier extends PokemonHeldItemModifier {
|
export class PokemonMultiHitModifier extends PokemonHeldItemModifier {
|
||||||
public override type: PokemonMultiHitModifierType;
|
public declare type: PokemonMultiHitModifierType;
|
||||||
|
|
||||||
matchType(modifier: Modifier): boolean {
|
matchType(modifier: Modifier): boolean {
|
||||||
return modifier instanceof PokemonMultiHitModifier;
|
return modifier instanceof PokemonMultiHitModifier;
|
||||||
@ -2816,7 +2817,7 @@ export class PokemonMultiHitModifier extends PokemonHeldItemModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PokemonFormChangeItemModifier extends PokemonHeldItemModifier {
|
export class PokemonFormChangeItemModifier extends PokemonHeldItemModifier {
|
||||||
public override type: FormChangeItemModifierType;
|
public declare type: FormChangeItemModifierType;
|
||||||
public formChangeItem: FormChangeItem;
|
public formChangeItem: FormChangeItem;
|
||||||
public active: boolean;
|
public active: boolean;
|
||||||
public isTransferable = false;
|
public isTransferable = false;
|
||||||
|
@ -2,7 +2,6 @@ import type { TurnCommand } from "#app/battle";
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { speciesStarterCosts } from "#balance/starters";
|
import { speciesStarterCosts } from "#balance/starters";
|
||||||
import type { EncoreTag } from "#data/battler-tags";
|
|
||||||
import { TrappedTag } from "#data/battler-tags";
|
import { TrappedTag } from "#data/battler-tags";
|
||||||
import { AbilityId } from "#enums/ability-id";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { ArenaTagSide } from "#enums/arena-tag-side";
|
import { ArenaTagSide } from "#enums/arena-tag-side";
|
||||||
@ -22,59 +21,77 @@ import type { MoveTargetSet } from "#moves/move";
|
|||||||
import { getMoveTargets } from "#moves/move-utils";
|
import { getMoveTargets } from "#moves/move-utils";
|
||||||
import { FieldPhase } from "#phases/field-phase";
|
import { FieldPhase } from "#phases/field-phase";
|
||||||
import type { TurnMove } from "#types/turn-move";
|
import type { TurnMove } from "#types/turn-move";
|
||||||
import { isNullOrUndefined } from "#utils/common";
|
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class CommandPhase extends FieldPhase {
|
export class CommandPhase extends FieldPhase {
|
||||||
public readonly phaseName = "CommandPhase";
|
public readonly phaseName = "CommandPhase";
|
||||||
protected fieldIndex: number;
|
protected fieldIndex: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the command phase is handling a switch command
|
||||||
|
*/
|
||||||
|
private isSwitch = false;
|
||||||
|
|
||||||
constructor(fieldIndex: number) {
|
constructor(fieldIndex: number) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.fieldIndex = fieldIndex;
|
this.fieldIndex = fieldIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
/**
|
||||||
super.start();
|
* Resets the cursor to the position of {@linkcode Command.FIGHT} if any of the following are true
|
||||||
|
* - The setting to remember the last action is not enabled
|
||||||
globalScene.updateGameInfo();
|
* - This is the first turn of a mystery encounter, trainer battle, or the END biome
|
||||||
|
* - The cursor is currently on the POKEMON command
|
||||||
|
*/
|
||||||
|
private resetCursorIfNeeded(): void {
|
||||||
const commandUiHandler = globalScene.ui.handlers[UiMode.COMMAND];
|
const commandUiHandler = globalScene.ui.handlers[UiMode.COMMAND];
|
||||||
|
const { arena, commandCursorMemory, currentBattle } = globalScene;
|
||||||
|
const { battleType, turn } = currentBattle;
|
||||||
|
const { biomeType } = arena;
|
||||||
|
|
||||||
// If one of these conditions is true, we always reset the cursor to Command.FIGHT
|
// If one of these conditions is true, we always reset the cursor to Command.FIGHT
|
||||||
const cursorResetEvent =
|
const cursorResetEvent =
|
||||||
globalScene.currentBattle.battleType === BattleType.MYSTERY_ENCOUNTER ||
|
battleType === BattleType.MYSTERY_ENCOUNTER || battleType === BattleType.TRAINER || biomeType === BiomeId.END;
|
||||||
globalScene.currentBattle.battleType === BattleType.TRAINER ||
|
|
||||||
globalScene.arena.biomeType === BiomeId.END;
|
|
||||||
|
|
||||||
if (commandUiHandler) {
|
if (!commandUiHandler) {
|
||||||
if (
|
return;
|
||||||
(globalScene.currentBattle.turn === 1 && (!globalScene.commandCursorMemory || cursorResetEvent)) ||
|
}
|
||||||
commandUiHandler.getCursor() === Command.POKEMON
|
if (
|
||||||
) {
|
(turn === 1 && (!commandCursorMemory || cursorResetEvent)) ||
|
||||||
commandUiHandler.setCursor(Command.FIGHT);
|
commandUiHandler.getCursor() === Command.POKEMON
|
||||||
} else {
|
) {
|
||||||
commandUiHandler.setCursor(commandUiHandler.getCursor());
|
commandUiHandler.setCursor(Command.FIGHT);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submethod of {@linkcode start} that validates field index logic for nonzero field indices.
|
||||||
|
* Must only be called if the field index is nonzero.
|
||||||
|
*/
|
||||||
|
private handleFieldIndexLogic(): void {
|
||||||
|
// If we somehow are attempting to check the right pokemon but there's only one pokemon out
|
||||||
|
// Switch back to the center pokemon. This can happen rarely in double battles with mid turn switching
|
||||||
|
// TODO: Prevent this from happening in the first place
|
||||||
|
if (globalScene.getPlayerField().filter(p => p.isActive()).length === 1) {
|
||||||
|
this.fieldIndex = FieldPosition.CENTER;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.fieldIndex) {
|
const allyCommand = globalScene.currentBattle.turnCommands[this.fieldIndex - 1];
|
||||||
// If we somehow are attempting to check the right pokemon but there's only one pokemon out
|
if (allyCommand?.command === Command.BALL || allyCommand?.command === Command.RUN) {
|
||||||
// Switch back to the center pokemon. This can happen rarely in double battles with mid turn switching
|
globalScene.currentBattle.turnCommands[this.fieldIndex] = {
|
||||||
if (globalScene.getPlayerField().filter(p => p.isActive()).length === 1) {
|
command: allyCommand?.command,
|
||||||
this.fieldIndex = FieldPosition.CENTER;
|
skip: true,
|
||||||
} else {
|
};
|
||||||
const allyCommand = globalScene.currentBattle.turnCommands[this.fieldIndex - 1];
|
|
||||||
if (allyCommand?.command === Command.BALL || allyCommand?.command === Command.RUN) {
|
|
||||||
globalScene.currentBattle.turnCommands[this.fieldIndex] = {
|
|
||||||
command: allyCommand?.command,
|
|
||||||
skip: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submethod of {@linkcode start} that sets the turn command to skip if this pokemon
|
||||||
|
* is commanding its ally via {@linkcode AbilityId.COMMANDER}.
|
||||||
|
*/
|
||||||
|
private checkCommander(): void {
|
||||||
// If the Pokemon has applied Commander's effects to its ally, skip this command
|
// If the Pokemon has applied Commander's effects to its ally, skip this command
|
||||||
if (
|
if (
|
||||||
globalScene.currentBattle?.double &&
|
globalScene.currentBattle?.double &&
|
||||||
@ -86,377 +103,521 @@ export class CommandPhase extends FieldPhase {
|
|||||||
skip: true,
|
skip: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Checks if the Pokemon is under the effects of Encore. If so, Encore can end early if the encored move has no more PP.
|
/**
|
||||||
const encoreTag = this.getPokemon().getTag(BattlerTagType.ENCORE) as EncoreTag | undefined;
|
* Clear out all unusable moves in front of the currently acting pokemon's move queue.
|
||||||
if (encoreTag) {
|
*/
|
||||||
this.getPokemon().lapseTag(BattlerTagType.ENCORE);
|
// TODO: Refactor move queue handling to ensure that this method is not necessary.
|
||||||
}
|
private clearUnusuableMoves(): void {
|
||||||
|
const playerPokemon = this.getPokemon();
|
||||||
if (globalScene.currentBattle.turnCommands[this.fieldIndex]?.skip) {
|
|
||||||
return this.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
const playerPokemon = globalScene.getPlayerField()[this.fieldIndex];
|
|
||||||
|
|
||||||
const moveQueue = playerPokemon.getMoveQueue();
|
const moveQueue = playerPokemon.getMoveQueue();
|
||||||
|
if (moveQueue.length === 0) {
|
||||||
while (
|
return;
|
||||||
moveQueue.length &&
|
|
||||||
moveQueue[0] &&
|
|
||||||
moveQueue[0].move &&
|
|
||||||
!isVirtual(moveQueue[0].useMode) &&
|
|
||||||
(!playerPokemon.getMoveset().find(m => m.moveId === moveQueue[0].move) ||
|
|
||||||
!playerPokemon
|
|
||||||
.getMoveset()
|
|
||||||
[playerPokemon.getMoveset().findIndex(m => m.moveId === moveQueue[0].move)].isUsable(
|
|
||||||
playerPokemon,
|
|
||||||
isIgnorePP(moveQueue[0].useMode),
|
|
||||||
))
|
|
||||||
) {
|
|
||||||
moveQueue.shift();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Refactor this. I did a few simple find/replace matches but this is just ABHORRENTLY structured
|
let entriesToDelete = 0;
|
||||||
if (moveQueue.length > 0) {
|
const moveset = playerPokemon.getMoveset();
|
||||||
const queuedMove = moveQueue[0];
|
for (const queuedMove of moveQueue) {
|
||||||
if (!queuedMove.move) {
|
const movesetQueuedMove = moveset.find(m => m.moveId === queuedMove.move);
|
||||||
this.handleCommand(Command.FIGHT, -1, MoveUseMode.NORMAL);
|
|
||||||
} else {
|
|
||||||
const moveIndex = playerPokemon.getMoveset().findIndex(m => m.moveId === queuedMove.move);
|
|
||||||
if (
|
|
||||||
(moveIndex > -1 &&
|
|
||||||
playerPokemon.getMoveset()[moveIndex].isUsable(playerPokemon, isIgnorePP(queuedMove.useMode))) ||
|
|
||||||
isVirtual(queuedMove.useMode)
|
|
||||||
) {
|
|
||||||
this.handleCommand(Command.FIGHT, moveIndex, queuedMove.useMode, queuedMove);
|
|
||||||
} else {
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (
|
if (
|
||||||
globalScene.currentBattle.isBattleMysteryEncounter() &&
|
queuedMove.move !== MoveId.NONE &&
|
||||||
globalScene.currentBattle.mysteryEncounter?.skipToFightInput
|
!isVirtual(queuedMove.useMode) &&
|
||||||
|
!movesetQueuedMove?.isUsable(playerPokemon, isIgnorePP(queuedMove.useMode))
|
||||||
) {
|
) {
|
||||||
globalScene.ui.clearText();
|
entriesToDelete++;
|
||||||
globalScene.ui.setMode(UiMode.FIGHT, this.fieldIndex);
|
|
||||||
} else {
|
} else {
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (entriesToDelete) {
|
||||||
|
moveQueue.splice(0, entriesToDelete);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Remove `args` and clean this thing up
|
* Attempt to execute the first usable move in this Pokemon's move queue
|
||||||
* Code will need to be copied over from pkty except replacing the `virtual` and `ignorePP` args with a corresponding `MoveUseMode`.
|
* @returns Whether a queued move was successfully set to be executed.
|
||||||
*/
|
*/
|
||||||
handleCommand(command: Command, cursor: number, ...args: any[]): boolean {
|
private tryExecuteQueuedMove(): boolean {
|
||||||
|
this.clearUnusuableMoves();
|
||||||
const playerPokemon = globalScene.getPlayerField()[this.fieldIndex];
|
const playerPokemon = globalScene.getPlayerField()[this.fieldIndex];
|
||||||
|
const moveQueue = playerPokemon.getMoveQueue();
|
||||||
|
|
||||||
|
if (moveQueue.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const queuedMove = moveQueue[0];
|
||||||
|
if (queuedMove.move === MoveId.NONE) {
|
||||||
|
this.handleCommand(Command.FIGHT, -1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const moveIndex = playerPokemon.getMoveset().findIndex(m => m.moveId === queuedMove.move);
|
||||||
|
if (!isVirtual(queuedMove.useMode) && moveIndex === -1) {
|
||||||
|
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
||||||
|
} else {
|
||||||
|
this.handleCommand(Command.FIGHT, moveIndex, queuedMove.useMode, queuedMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override start(): void {
|
||||||
|
super.start();
|
||||||
|
|
||||||
|
globalScene.updateGameInfo();
|
||||||
|
this.resetCursorIfNeeded();
|
||||||
|
|
||||||
|
if (this.fieldIndex) {
|
||||||
|
this.handleFieldIndexLogic();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.checkCommander();
|
||||||
|
|
||||||
|
const playerPokemon = this.getPokemon();
|
||||||
|
|
||||||
|
// Note: It is OK to call this if the target is not under the effect of encore; it will simply do nothing.
|
||||||
|
playerPokemon.lapseTag(BattlerTagType.ENCORE);
|
||||||
|
|
||||||
|
if (globalScene.currentBattle.turnCommands[this.fieldIndex]?.skip) {
|
||||||
|
this.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.tryExecuteQueuedMove()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
globalScene.currentBattle.isBattleMysteryEncounter() &&
|
||||||
|
globalScene.currentBattle.mysteryEncounter?.skipToFightInput
|
||||||
|
) {
|
||||||
|
globalScene.ui.clearText();
|
||||||
|
globalScene.ui.setMode(UiMode.FIGHT, this.fieldIndex);
|
||||||
|
} else {
|
||||||
|
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submethod of {@linkcode handleFightCommand} responsible for queuing the appropriate
|
||||||
|
* error message when a move cannot be used.
|
||||||
|
* @param user - The pokemon using the move
|
||||||
|
* @param cursor - The index of the move in the moveset
|
||||||
|
*/
|
||||||
|
private queueFightErrorMessage(user: PlayerPokemon, cursor: number) {
|
||||||
|
const move = user.getMoveset()[cursor];
|
||||||
|
globalScene.ui.setMode(UiMode.MESSAGE);
|
||||||
|
|
||||||
|
// Decides between a Disabled, Not Implemented, or No PP translation message
|
||||||
|
const errorMessage = user.isMoveRestricted(move.moveId, user)
|
||||||
|
? user.getRestrictingTag(move.moveId, user)!.selectionDeniedText(user, move.moveId)
|
||||||
|
: move.getName().endsWith(" (N)")
|
||||||
|
? "battle:moveNotImplemented"
|
||||||
|
: "battle:moveNoPP";
|
||||||
|
const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator
|
||||||
|
|
||||||
|
globalScene.ui.showText(
|
||||||
|
i18next.t(errorMessage, { moveName: moveName }),
|
||||||
|
null,
|
||||||
|
() => {
|
||||||
|
globalScene.ui.clearText();
|
||||||
|
globalScene.ui.setMode(UiMode.FIGHT, this.fieldIndex);
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for {@linkcode handleFightCommand} that returns the moveID for the phase
|
||||||
|
* based on the move passed in or the cursor.
|
||||||
|
*
|
||||||
|
* Does not check if the move is usable or not, that should be handled by the caller.
|
||||||
|
*/
|
||||||
|
private computeMoveId(playerPokemon: PlayerPokemon, cursor: number, move: TurnMove | undefined): MoveId {
|
||||||
|
return move?.move ?? (cursor > -1 ? playerPokemon.getMoveset()[cursor]?.moveId : MoveId.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the logic for executing a fight-related command
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* - Validates whether the move can be used, using struggle if not
|
||||||
|
* - Constructs the turn command and inserts it into the battle's turn commands
|
||||||
|
*
|
||||||
|
* @param command - The command to handle (FIGHT or TERA)
|
||||||
|
* @param cursor - The index that the cursor is placed on, or -1 if no move can be selected.
|
||||||
|
* @param ignorePP - Whether to ignore PP when checking if the move can be used.
|
||||||
|
* @param move - The move to force the command to use, if any.
|
||||||
|
*/
|
||||||
|
private handleFightCommand(
|
||||||
|
command: Command.FIGHT | Command.TERA,
|
||||||
|
cursor: number,
|
||||||
|
useMode: MoveUseMode = MoveUseMode.NORMAL,
|
||||||
|
move?: TurnMove,
|
||||||
|
): boolean {
|
||||||
|
const playerPokemon = this.getPokemon();
|
||||||
|
const ignorePP = isIgnorePP(useMode);
|
||||||
|
|
||||||
|
let canUse = cursor === -1 || playerPokemon.trySelectMove(cursor, ignorePP);
|
||||||
|
|
||||||
|
// Ternary here ensures we don't compute struggle conditions unless necessary
|
||||||
|
const useStruggle = canUse
|
||||||
|
? false
|
||||||
|
: cursor > -1 && !playerPokemon.getMoveset().some(m => m.isUsable(playerPokemon));
|
||||||
|
|
||||||
|
canUse ||= useStruggle;
|
||||||
|
|
||||||
|
if (!canUse) {
|
||||||
|
this.queueFightErrorMessage(playerPokemon, cursor);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const moveId = useStruggle ? MoveId.STRUGGLE : this.computeMoveId(playerPokemon, cursor, move);
|
||||||
|
|
||||||
|
const turnCommand: TurnCommand = {
|
||||||
|
command: Command.FIGHT,
|
||||||
|
cursor,
|
||||||
|
move: { move: moveId, targets: [], useMode },
|
||||||
|
args: [useMode, move],
|
||||||
|
};
|
||||||
|
const preTurnCommand: TurnCommand = {
|
||||||
|
command,
|
||||||
|
targets: [this.fieldIndex],
|
||||||
|
skip: command === Command.FIGHT,
|
||||||
|
};
|
||||||
|
|
||||||
|
const moveTargets: MoveTargetSet =
|
||||||
|
move === undefined
|
||||||
|
? getMoveTargets(playerPokemon, moveId)
|
||||||
|
: {
|
||||||
|
targets: move.targets,
|
||||||
|
multiple: move.targets.length > 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (moveId === MoveId.NONE) {
|
||||||
|
turnCommand.targets = [this.fieldIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"Move:",
|
||||||
|
MoveId[moveId],
|
||||||
|
"Move targets:",
|
||||||
|
moveTargets,
|
||||||
|
"\nPlayer Pokemon:",
|
||||||
|
getPokemonNameWithAffix(playerPokemon),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (moveTargets.targets.length > 1 && moveTargets.multiple) {
|
||||||
|
globalScene.phaseManager.unshiftNew("SelectTargetPhase", this.fieldIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (turnCommand.move && (moveTargets.targets.length <= 1 || moveTargets.multiple)) {
|
||||||
|
turnCommand.move.targets = moveTargets.targets;
|
||||||
|
} else if (
|
||||||
|
turnCommand.move &&
|
||||||
|
playerPokemon.getTag(BattlerTagType.CHARGING) &&
|
||||||
|
playerPokemon.getMoveQueue().length >= 1
|
||||||
|
) {
|
||||||
|
turnCommand.move.targets = playerPokemon.getMoveQueue()[0].targets;
|
||||||
|
} else {
|
||||||
|
globalScene.phaseManager.unshiftNew("SelectTargetPhase", this.fieldIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
globalScene.currentBattle.preTurnCommands[this.fieldIndex] = preTurnCommand;
|
||||||
|
globalScene.currentBattle.turnCommands[this.fieldIndex] = turnCommand;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the mode in preparation to show the text, and then show the text.
|
||||||
|
* Only works for parameterless i18next keys.
|
||||||
|
* @param key - The i18next key for the text to show
|
||||||
|
*/
|
||||||
|
private queueShowText(key: string): void {
|
||||||
|
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
||||||
|
globalScene.ui.setMode(UiMode.MESSAGE);
|
||||||
|
|
||||||
|
globalScene.ui.showText(
|
||||||
|
i18next.t(key),
|
||||||
|
null,
|
||||||
|
() => {
|
||||||
|
globalScene.ui.showText("", 0);
|
||||||
|
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for {@linkcode handleBallCommand} that checks if a pokeball can be thrown
|
||||||
|
* and displays the appropriate error message.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* The pokeball may not be thrown if any of the following are true:
|
||||||
|
* - It is a trainer battle
|
||||||
|
* - The player is in the {@linkcode BiomeId.END | End} biome and
|
||||||
|
* - it is not classic mode; or
|
||||||
|
* - the fresh start challenge is active; or
|
||||||
|
* - the player has not caught the target before and the player is still missing more than one starter
|
||||||
|
* - The player is in a mystery encounter that disallows catching the pokemon
|
||||||
|
* @returns Whether a pokeball can be thrown
|
||||||
|
*/
|
||||||
|
private checkCanUseBall(): boolean {
|
||||||
|
const { arena, currentBattle, gameData, gameMode } = globalScene;
|
||||||
|
const { battleType } = currentBattle;
|
||||||
|
const { biomeType } = arena;
|
||||||
|
const { isClassic } = gameMode;
|
||||||
|
const { dexData } = gameData;
|
||||||
|
|
||||||
|
const someUncaughtSpeciesOnField = globalScene
|
||||||
|
.getEnemyField()
|
||||||
|
.some(p => p.isActive() && !dexData[p.species.speciesId].caughtAttr);
|
||||||
|
const missingMultipleStarters =
|
||||||
|
gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarterCosts).length - 1;
|
||||||
|
if (
|
||||||
|
biomeType === BiomeId.END &&
|
||||||
|
(!isClassic || gameMode.isFreshStartChallenge() || (someUncaughtSpeciesOnField && missingMultipleStarters))
|
||||||
|
) {
|
||||||
|
this.queueShowText("battle:noPokeballForce");
|
||||||
|
} else if (battleType === BattleType.TRAINER) {
|
||||||
|
this.queueShowText("battle:noPokeballTrainer");
|
||||||
|
} else if (currentBattle.isBattleMysteryEncounter() && !currentBattle.mysteryEncounter!.catchAllowed) {
|
||||||
|
this.queueShowText("battle:noPokeballMysteryEncounter");
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for {@linkcode handleCommand} that handles the logic when the selected command is to use a pokeball.
|
||||||
|
*
|
||||||
|
* @param cursor - The index of the pokeball to use
|
||||||
|
* @returns Whether the command was successfully initiated
|
||||||
|
*/
|
||||||
|
private handleBallCommand(cursor: number): boolean {
|
||||||
|
const targets = globalScene
|
||||||
|
.getEnemyField()
|
||||||
|
.filter(p => p.isActive(true))
|
||||||
|
.map(p => p.getBattlerIndex());
|
||||||
|
if (targets.length > 1) {
|
||||||
|
this.queueShowText("battle:noPokeballMulti");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.checkCanUseBall()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const numBallTypes = 5;
|
||||||
|
if (cursor < numBallTypes) {
|
||||||
|
const targetPokemon = globalScene.getEnemyPokemon();
|
||||||
|
if (
|
||||||
|
targetPokemon?.isBoss() &&
|
||||||
|
targetPokemon?.bossSegmentIndex >= 1 &&
|
||||||
|
// TODO: Decouple this hardcoded exception for wonder guard and just check the target...
|
||||||
|
!targetPokemon?.hasAbility(AbilityId.WONDER_GUARD, false, true) &&
|
||||||
|
cursor < PokeballType.MASTER_BALL
|
||||||
|
) {
|
||||||
|
this.queueShowText("battle:noPokeballStrong");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
globalScene.currentBattle.turnCommands[this.fieldIndex] = {
|
||||||
|
command: Command.BALL,
|
||||||
|
cursor: cursor,
|
||||||
|
};
|
||||||
|
globalScene.currentBattle.turnCommands[this.fieldIndex]!.targets = targets;
|
||||||
|
if (this.fieldIndex) {
|
||||||
|
globalScene.currentBattle.turnCommands[this.fieldIndex - 1]!.skip = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submethod of {@linkcode tryLeaveField} to handle the logic for effects that prevent the pokemon from leaving the field
|
||||||
|
* due to trapping abilities or effects.
|
||||||
|
*
|
||||||
|
* This method queues the proper messages in the case of trapping abilities or effects.
|
||||||
|
*
|
||||||
|
* @returns Whether the pokemon is currently trapped
|
||||||
|
*/
|
||||||
|
private handleTrap(): boolean {
|
||||||
|
const playerPokemon = this.getPokemon();
|
||||||
|
const trappedAbMessages: string[] = [];
|
||||||
|
const isSwitch = this.isSwitch;
|
||||||
|
if (!playerPokemon.isTrapped(trappedAbMessages)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (trappedAbMessages.length > 0) {
|
||||||
|
if (isSwitch) {
|
||||||
|
globalScene.ui.setMode(UiMode.MESSAGE);
|
||||||
|
}
|
||||||
|
globalScene.ui.showText(
|
||||||
|
trappedAbMessages[0],
|
||||||
|
null,
|
||||||
|
() => {
|
||||||
|
globalScene.ui.showText("", 0);
|
||||||
|
if (isSwitch) {
|
||||||
|
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const trapTag = playerPokemon.getTag(TrappedTag);
|
||||||
|
const fairyLockTag = globalScene.arena.getTagOnSide(ArenaTagType.FAIRY_LOCK, ArenaTagSide.PLAYER);
|
||||||
|
|
||||||
|
if (!isSwitch) {
|
||||||
|
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
||||||
|
globalScene.ui.setMode(UiMode.MESSAGE);
|
||||||
|
}
|
||||||
|
if (trapTag) {
|
||||||
|
this.showNoEscapeText(trapTag, false);
|
||||||
|
} else if (fairyLockTag) {
|
||||||
|
this.showNoEscapeText(fairyLockTag, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common helper method that attempts to have the pokemon leave the field.
|
||||||
|
* Checks for trapping abilities and effects.
|
||||||
|
*
|
||||||
|
* @param cursor - The index of the option that the cursor is on
|
||||||
|
* @returns Whether the pokemon is able to leave the field, indicating the command phase should end
|
||||||
|
*/
|
||||||
|
private tryLeaveField(cursor?: number, isBatonSwitch = false): boolean {
|
||||||
|
const currentBattle = globalScene.currentBattle;
|
||||||
|
|
||||||
|
if (isBatonSwitch || !this.handleTrap()) {
|
||||||
|
currentBattle.turnCommands[this.fieldIndex] = this.isSwitch
|
||||||
|
? {
|
||||||
|
command: Command.POKEMON,
|
||||||
|
cursor,
|
||||||
|
args: [isBatonSwitch],
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
command: Command.RUN,
|
||||||
|
};
|
||||||
|
if (!this.isSwitch && this.fieldIndex) {
|
||||||
|
currentBattle.turnCommands[this.fieldIndex - 1]!.skip = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for {@linkcode handleCommand} that handles the logic when the selected command is RUN.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* Checks if the player is allowed to flee, and if not, queues the appropriate message.
|
||||||
|
*
|
||||||
|
* The player cannot flee if:
|
||||||
|
* - The player is in the {@linkcode BiomeId.END | End} biome
|
||||||
|
* - The player is in a trainer battle
|
||||||
|
* - The player is in a mystery encounter that disallows fleeing
|
||||||
|
* - The player's pokemon is trapped by an ability or effect
|
||||||
|
* @returns Whether the pokemon is able to leave the field, indicating the command phase should end
|
||||||
|
*/
|
||||||
|
private handleRunCommand(): boolean {
|
||||||
|
const { currentBattle, arena } = globalScene;
|
||||||
|
const mysteryEncounterFleeAllowed = currentBattle.mysteryEncounter?.fleeAllowed ?? true;
|
||||||
|
if (arena.biomeType === BiomeId.END || !mysteryEncounterFleeAllowed) {
|
||||||
|
this.queueShowText("battle:noEscapeForce");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
currentBattle.battleType === BattleType.TRAINER ||
|
||||||
|
currentBattle.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE
|
||||||
|
) {
|
||||||
|
this.queueShowText("battle:noEscapeTrainer");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const success = this.tryLeaveField();
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a message indicating that the pokemon cannot escape, and then return to the command phase.
|
||||||
|
*/
|
||||||
|
private showNoEscapeText(tag: any, isSwitch: boolean): void {
|
||||||
|
globalScene.ui.showText(
|
||||||
|
i18next.t("battle:noEscapePokemon", {
|
||||||
|
pokemonName:
|
||||||
|
tag.sourceId && globalScene.getPokemonById(tag.sourceId)
|
||||||
|
? getPokemonNameWithAffix(globalScene.getPokemonById(tag.sourceId)!)
|
||||||
|
: "",
|
||||||
|
moveName: tag.getMoveName(),
|
||||||
|
escapeVerb: i18next.t(isSwitch ? "battle:escapeVerbSwitch" : "battle:escapeVerbFlee"),
|
||||||
|
}),
|
||||||
|
null,
|
||||||
|
() => {
|
||||||
|
globalScene.ui.showText("", 0);
|
||||||
|
if (!isSwitch) {
|
||||||
|
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overloads for handleCommand to provide a more specific signature for the different options
|
||||||
|
/**
|
||||||
|
* Process the command phase logic based on the selected command
|
||||||
|
*
|
||||||
|
* @param command - The kind of command to handle
|
||||||
|
* @param cursor - The index of option that the cursor is on, or -1 if no option is selected
|
||||||
|
* @param useMode - The mode to use for the move, if applicable. For switches, a boolean that specifies whether the switch is a Baton switch.
|
||||||
|
* @param move - For {@linkcode Command.FIGHT}, the move to use
|
||||||
|
* @returns Whether the command was successful
|
||||||
|
*/
|
||||||
|
handleCommand(command: Command.FIGHT | Command.TERA, cursor: number, useMode?: MoveUseMode, move?: TurnMove): boolean;
|
||||||
|
handleCommand(command: Command.BALL, cursor: number): boolean;
|
||||||
|
handleCommand(command: Command.POKEMON, cursor: number, useBaton: boolean): boolean;
|
||||||
|
handleCommand(command: Command.RUN, cursor: number): boolean;
|
||||||
|
handleCommand(command: Command, cursor: number, useMode?: boolean | MoveUseMode, move?: TurnMove): boolean;
|
||||||
|
|
||||||
|
public handleCommand(
|
||||||
|
command: Command,
|
||||||
|
cursor: number,
|
||||||
|
useMode: boolean | MoveUseMode = false,
|
||||||
|
move?: TurnMove,
|
||||||
|
): boolean {
|
||||||
let success = false;
|
let success = false;
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
// TODO: We don't need 2 args for this - moveUseMode is carried over from queuedMove
|
|
||||||
case Command.TERA:
|
case Command.TERA:
|
||||||
case Command.FIGHT: {
|
case Command.FIGHT:
|
||||||
let useStruggle = false;
|
success = this.handleFightCommand(command, cursor, typeof useMode === "boolean" ? undefined : useMode, move);
|
||||||
const turnMove: TurnMove | undefined = args.length === 2 ? (args[1] as TurnMove) : undefined;
|
|
||||||
if (
|
|
||||||
cursor === -1 ||
|
|
||||||
playerPokemon.trySelectMove(cursor, isIgnorePP(args[0] as MoveUseMode)) ||
|
|
||||||
(useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m.isUsable(playerPokemon)).length)
|
|
||||||
) {
|
|
||||||
let moveId: MoveId;
|
|
||||||
if (useStruggle) {
|
|
||||||
moveId = MoveId.STRUGGLE;
|
|
||||||
} else if (turnMove !== undefined) {
|
|
||||||
moveId = turnMove.move;
|
|
||||||
} else if (cursor > -1) {
|
|
||||||
moveId = playerPokemon.getMoveset()[cursor].moveId;
|
|
||||||
} else {
|
|
||||||
moveId = MoveId.NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const turnCommand: TurnCommand = {
|
|
||||||
command: Command.FIGHT,
|
|
||||||
cursor: cursor,
|
|
||||||
move: { move: moveId, targets: [], useMode: args[0] },
|
|
||||||
args: args,
|
|
||||||
};
|
|
||||||
const preTurnCommand: TurnCommand = {
|
|
||||||
command: command,
|
|
||||||
targets: [this.fieldIndex],
|
|
||||||
skip: command === Command.FIGHT,
|
|
||||||
};
|
|
||||||
const moveTargets: MoveTargetSet =
|
|
||||||
turnMove === undefined
|
|
||||||
? getMoveTargets(playerPokemon, moveId)
|
|
||||||
: {
|
|
||||||
targets: turnMove.targets,
|
|
||||||
multiple: turnMove.targets.length > 1,
|
|
||||||
};
|
|
||||||
if (!moveId) {
|
|
||||||
turnCommand.targets = [this.fieldIndex];
|
|
||||||
}
|
|
||||||
console.log(moveTargets, getPokemonNameWithAffix(playerPokemon));
|
|
||||||
if (moveTargets.targets.length > 1 && moveTargets.multiple) {
|
|
||||||
globalScene.phaseManager.unshiftNew("SelectTargetPhase", this.fieldIndex);
|
|
||||||
}
|
|
||||||
if (turnCommand.move && (moveTargets.targets.length <= 1 || moveTargets.multiple)) {
|
|
||||||
turnCommand.move.targets = moveTargets.targets;
|
|
||||||
} else if (
|
|
||||||
turnCommand.move &&
|
|
||||||
playerPokemon.getTag(BattlerTagType.CHARGING) &&
|
|
||||||
playerPokemon.getMoveQueue().length >= 1
|
|
||||||
) {
|
|
||||||
turnCommand.move.targets = playerPokemon.getMoveQueue()[0].targets;
|
|
||||||
} else {
|
|
||||||
globalScene.phaseManager.unshiftNew("SelectTargetPhase", this.fieldIndex);
|
|
||||||
}
|
|
||||||
globalScene.currentBattle.preTurnCommands[this.fieldIndex] = preTurnCommand;
|
|
||||||
globalScene.currentBattle.turnCommands[this.fieldIndex] = turnCommand;
|
|
||||||
success = true;
|
|
||||||
} else if (cursor < playerPokemon.getMoveset().length) {
|
|
||||||
const move = playerPokemon.getMoveset()[cursor];
|
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
|
||||||
|
|
||||||
// Decides between a Disabled, Not Implemented, or No PP translation message
|
|
||||||
const errorMessage = playerPokemon.isMoveRestricted(move.moveId, playerPokemon)
|
|
||||||
? playerPokemon
|
|
||||||
.getRestrictingTag(move.moveId, playerPokemon)!
|
|
||||||
.selectionDeniedText(playerPokemon, move.moveId)
|
|
||||||
: move.getName().endsWith(" (N)")
|
|
||||||
? "battle:moveNotImplemented"
|
|
||||||
: "battle:moveNoPP";
|
|
||||||
const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator
|
|
||||||
|
|
||||||
globalScene.ui.showText(
|
|
||||||
i18next.t(errorMessage, { moveName: moveName }),
|
|
||||||
null,
|
|
||||||
() => {
|
|
||||||
globalScene.ui.clearText();
|
|
||||||
globalScene.ui.setMode(UiMode.FIGHT, this.fieldIndex);
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
case Command.BALL:
|
||||||
case Command.BALL: {
|
success = this.handleBallCommand(cursor);
|
||||||
const notInDex =
|
|
||||||
globalScene
|
|
||||||
.getEnemyField()
|
|
||||||
.filter(p => p.isActive(true))
|
|
||||||
.some(p => !globalScene.gameData.dexData[p.species.speciesId].caughtAttr) &&
|
|
||||||
globalScene.gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarterCosts).length - 1;
|
|
||||||
if (
|
|
||||||
globalScene.arena.biomeType === BiomeId.END &&
|
|
||||||
(!globalScene.gameMode.isClassic || globalScene.gameMode.isFreshStartChallenge() || notInDex)
|
|
||||||
) {
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
|
||||||
globalScene.ui.showText(
|
|
||||||
i18next.t("battle:noPokeballForce"),
|
|
||||||
null,
|
|
||||||
() => {
|
|
||||||
globalScene.ui.showText("", 0);
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
} else if (globalScene.currentBattle.battleType === BattleType.TRAINER) {
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
|
||||||
globalScene.ui.showText(
|
|
||||||
i18next.t("battle:noPokeballTrainer"),
|
|
||||||
null,
|
|
||||||
() => {
|
|
||||||
globalScene.ui.showText("", 0);
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
} else if (
|
|
||||||
globalScene.currentBattle.isBattleMysteryEncounter() &&
|
|
||||||
!globalScene.currentBattle.mysteryEncounter!.catchAllowed
|
|
||||||
) {
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
|
||||||
globalScene.ui.showText(
|
|
||||||
i18next.t("battle:noPokeballMysteryEncounter"),
|
|
||||||
null,
|
|
||||||
() => {
|
|
||||||
globalScene.ui.showText("", 0);
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const targets = globalScene
|
|
||||||
.getEnemyField()
|
|
||||||
.filter(p => p.isActive(true))
|
|
||||||
.map(p => p.getBattlerIndex());
|
|
||||||
if (targets.length > 1) {
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
|
||||||
globalScene.ui.showText(
|
|
||||||
i18next.t("battle:noPokeballMulti"),
|
|
||||||
null,
|
|
||||||
() => {
|
|
||||||
globalScene.ui.showText("", 0);
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
} else if (cursor < 5) {
|
|
||||||
const targetPokemon = globalScene.getEnemyField().find(p => p.isActive(true));
|
|
||||||
if (
|
|
||||||
targetPokemon?.isBoss() &&
|
|
||||||
targetPokemon?.bossSegmentIndex >= 1 &&
|
|
||||||
!targetPokemon?.hasAbility(AbilityId.WONDER_GUARD, false, true) &&
|
|
||||||
cursor < PokeballType.MASTER_BALL
|
|
||||||
) {
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
|
||||||
globalScene.ui.showText(
|
|
||||||
i18next.t("battle:noPokeballStrong"),
|
|
||||||
null,
|
|
||||||
() => {
|
|
||||||
globalScene.ui.showText("", 0);
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
globalScene.currentBattle.turnCommands[this.fieldIndex] = {
|
|
||||||
command: Command.BALL,
|
|
||||||
cursor: cursor,
|
|
||||||
};
|
|
||||||
globalScene.currentBattle.turnCommands[this.fieldIndex]!.targets = targets;
|
|
||||||
if (this.fieldIndex) {
|
|
||||||
globalScene.currentBattle.turnCommands[this.fieldIndex - 1]!.skip = true;
|
|
||||||
}
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case Command.POKEMON:
|
case Command.POKEMON:
|
||||||
case Command.RUN: {
|
this.isSwitch = true;
|
||||||
const isSwitch = command === Command.POKEMON;
|
success = this.tryLeaveField(cursor, typeof useMode === "boolean" ? useMode : undefined);
|
||||||
const { currentBattle, arena } = globalScene;
|
this.isSwitch = false;
|
||||||
const mysteryEncounterFleeAllowed = currentBattle.mysteryEncounter?.fleeAllowed;
|
|
||||||
if (
|
|
||||||
!isSwitch &&
|
|
||||||
(arena.biomeType === BiomeId.END ||
|
|
||||||
(!isNullOrUndefined(mysteryEncounterFleeAllowed) && !mysteryEncounterFleeAllowed))
|
|
||||||
) {
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
|
||||||
globalScene.ui.showText(
|
|
||||||
i18next.t("battle:noEscapeForce"),
|
|
||||||
null,
|
|
||||||
() => {
|
|
||||||
globalScene.ui.showText("", 0);
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
} else if (
|
|
||||||
!isSwitch &&
|
|
||||||
(currentBattle.battleType === BattleType.TRAINER ||
|
|
||||||
currentBattle.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE)
|
|
||||||
) {
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
|
||||||
globalScene.ui.showText(
|
|
||||||
i18next.t("battle:noEscapeTrainer"),
|
|
||||||
null,
|
|
||||||
() => {
|
|
||||||
globalScene.ui.showText("", 0);
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const batonPass = isSwitch && (args[0] as boolean);
|
|
||||||
const trappedAbMessages: string[] = [];
|
|
||||||
if (batonPass || !playerPokemon.isTrapped(trappedAbMessages)) {
|
|
||||||
currentBattle.turnCommands[this.fieldIndex] = isSwitch
|
|
||||||
? { command: Command.POKEMON, cursor: cursor, args: args }
|
|
||||||
: { command: Command.RUN };
|
|
||||||
success = true;
|
|
||||||
if (!isSwitch && this.fieldIndex) {
|
|
||||||
currentBattle.turnCommands[this.fieldIndex - 1]!.skip = true;
|
|
||||||
}
|
|
||||||
} else if (trappedAbMessages.length > 0) {
|
|
||||||
if (!isSwitch) {
|
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
|
||||||
}
|
|
||||||
globalScene.ui.showText(
|
|
||||||
trappedAbMessages[0],
|
|
||||||
null,
|
|
||||||
() => {
|
|
||||||
globalScene.ui.showText("", 0);
|
|
||||||
if (!isSwitch) {
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
const trapTag = playerPokemon.getTag(TrappedTag);
|
|
||||||
const fairyLockTag = globalScene.arena.getTagOnSide(ArenaTagType.FAIRY_LOCK, ArenaTagSide.PLAYER);
|
|
||||||
|
|
||||||
if (!trapTag && !fairyLockTag) {
|
|
||||||
i18next.t(`battle:noEscape${isSwitch ? "Switch" : "Flee"}`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!isSwitch) {
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
globalScene.ui.setMode(UiMode.MESSAGE);
|
|
||||||
}
|
|
||||||
const showNoEscapeText = (tag: any) => {
|
|
||||||
globalScene.ui.showText(
|
|
||||||
i18next.t("battle:noEscapePokemon", {
|
|
||||||
pokemonName:
|
|
||||||
tag.sourceId && globalScene.getPokemonById(tag.sourceId)
|
|
||||||
? getPokemonNameWithAffix(globalScene.getPokemonById(tag.sourceId)!)
|
|
||||||
: "",
|
|
||||||
moveName: tag.getMoveName(),
|
|
||||||
escapeVerb: isSwitch ? i18next.t("battle:escapeVerbSwitch") : i18next.t("battle:escapeVerbFlee"),
|
|
||||||
}),
|
|
||||||
null,
|
|
||||||
() => {
|
|
||||||
globalScene.ui.showText("", 0);
|
|
||||||
if (!isSwitch) {
|
|
||||||
globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (trapTag) {
|
|
||||||
showNoEscapeText(trapTag);
|
|
||||||
} else if (fairyLockTag) {
|
|
||||||
showNoEscapeText(fairyLockTag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
case Command.RUN:
|
||||||
|
success = this.handleRunCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Phase } from "#app/phase";
|
import { Phase } from "#app/phase";
|
||||||
import { PlayerGender } from "#enums/player-gender";
|
import { PlayerGender } from "#enums/player-gender";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { TextStyle } from "#enums/text-style";
|
||||||
|
import { addTextObject } from "#ui/text";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class EndCardPhase extends Phase {
|
export class EndCardPhase extends Phase {
|
||||||
|
@ -135,7 +135,7 @@ export class EvolutionPhase extends Phase {
|
|||||||
|
|
||||||
sprite
|
sprite
|
||||||
.setPipelineData("ignoreTimeTint", true)
|
.setPipelineData("ignoreTimeTint", true)
|
||||||
.setPipelineData("spriteKey", pokemon.getSpriteKey())
|
.setPipelineData("spriteKey", spriteKey)
|
||||||
.setPipelineData("shiny", pokemon.shiny)
|
.setPipelineData("shiny", pokemon.shiny)
|
||||||
.setPipelineData("variant", pokemon.variant);
|
.setPipelineData("variant", pokemon.variant);
|
||||||
|
|
||||||
|
@ -2,9 +2,10 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import type { BattlerIndex } from "#enums/battler-index";
|
import type { BattlerIndex } from "#enums/battler-index";
|
||||||
import { PERMANENT_STATS, Stat } from "#enums/stat";
|
import { PERMANENT_STATS, Stat } from "#enums/stat";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { PokemonPhase } from "#phases/pokemon-phase";
|
import { PokemonPhase } from "#phases/pokemon-phase";
|
||||||
import { getTextColor, TextStyle } from "#ui/text";
|
import { getTextColor } from "#ui/text";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class ScanIvsPhase extends PokemonPhase {
|
export class ScanIvsPhase extends PokemonPhase {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import pkg from "#package.json";
|
import pkg from "#package.json";
|
||||||
import { camelCaseToKebabCase } from "#utils/common";
|
import { toKebabCase } from "#utils/strings";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import LanguageDetector from "i18next-browser-languagedetector";
|
import LanguageDetector from "i18next-browser-languagedetector";
|
||||||
import HttpBackend from "i18next-http-backend";
|
import HttpBackend from "i18next-http-backend";
|
||||||
@ -194,14 +194,16 @@ export async function initI18n(): Promise<void> {
|
|||||||
],
|
],
|
||||||
backend: {
|
backend: {
|
||||||
loadPath(lng: string, [ns]: string[]) {
|
loadPath(lng: string, [ns]: string[]) {
|
||||||
|
// Use namespace maps where required
|
||||||
let fileName: string;
|
let fileName: string;
|
||||||
if (namespaceMap[ns]) {
|
if (namespaceMap[ns]) {
|
||||||
fileName = namespaceMap[ns];
|
fileName = namespaceMap[ns];
|
||||||
} else if (ns.startsWith("mysteryEncounters/")) {
|
} else if (ns.startsWith("mysteryEncounters/")) {
|
||||||
fileName = camelCaseToKebabCase(ns + "Dialogue");
|
fileName = toKebabCase(ns + "-dialogue"); // mystery-encounters/a-trainers-test-dialogue
|
||||||
} else {
|
} else {
|
||||||
fileName = camelCaseToKebabCase(ns);
|
fileName = toKebabCase(ns);
|
||||||
}
|
}
|
||||||
|
// ex: "./locales/en/move-anims"
|
||||||
return `./locales/${lng}/${fileName}.json?v=${pkg.version}`;
|
return `./locales/${lng}/${fileName}.json?v=${pkg.version}`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -890,7 +890,7 @@ export const achvs = {
|
|||||||
100,
|
100,
|
||||||
c =>
|
c =>
|
||||||
c instanceof FreshStartChallenge &&
|
c instanceof FreshStartChallenge &&
|
||||||
c.value > 0 &&
|
c.value === 1 &&
|
||||||
!globalScene.gameMode.challenges.some(
|
!globalScene.gameMode.challenges.some(
|
||||||
c => [Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT].includes(c.id) && c.value > 0,
|
c => [Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT].includes(c.id) && c.value > 0,
|
||||||
),
|
),
|
||||||
|
@ -1454,11 +1454,10 @@ export class GameData {
|
|||||||
|
|
||||||
reader.onload = (_ => {
|
reader.onload = (_ => {
|
||||||
return e => {
|
return e => {
|
||||||
let dataName: string;
|
let dataName = GameDataType[dataType].toLowerCase();
|
||||||
let dataStr = AES.decrypt(e.target?.result?.toString()!, saveKey).toString(enc.Utf8); // TODO: is this bang correct?
|
let dataStr = AES.decrypt(e.target?.result?.toString()!, saveKey).toString(enc.Utf8); // TODO: is this bang correct?
|
||||||
let valid = false;
|
let valid = false;
|
||||||
try {
|
try {
|
||||||
dataName = GameDataType[dataType].toLowerCase();
|
|
||||||
switch (dataType) {
|
switch (dataType) {
|
||||||
case GameDataType.SYSTEM: {
|
case GameDataType.SYSTEM: {
|
||||||
dataStr = this.convertSystemDataStr(dataStr);
|
dataStr = this.convertSystemDataStr(dataStr);
|
||||||
@ -1493,7 +1492,6 @@ export class GameData {
|
|||||||
|
|
||||||
const displayError = (error: string) =>
|
const displayError = (error: string) =>
|
||||||
globalScene.ui.showText(error, null, () => globalScene.ui.showText("", 0), fixedInt(1500));
|
globalScene.ui.showText(error, null, () => globalScene.ui.showText("", 0), fixedInt(1500));
|
||||||
dataName = dataName!; // tell TS compiler that dataName is defined!
|
|
||||||
|
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return globalScene.ui.showText(
|
return globalScene.ui.showText(
|
||||||
|
@ -88,12 +88,12 @@ export class PokemonData {
|
|||||||
this.id = source.id;
|
this.id = source.id;
|
||||||
this.player = sourcePokemon?.isPlayer() ?? source.player;
|
this.player = sourcePokemon?.isPlayer() ?? source.player;
|
||||||
this.species = sourcePokemon?.species.speciesId ?? source.species;
|
this.species = sourcePokemon?.species.speciesId ?? source.species;
|
||||||
this.nickname = sourcePokemon?.summonData.illusion?.basePokemon.nickname ?? source.nickname;
|
this.nickname = source.nickname;
|
||||||
this.formIndex = Math.max(Math.min(source.formIndex, getPokemonSpecies(this.species).forms.length - 1), 0);
|
this.formIndex = Math.max(Math.min(source.formIndex, getPokemonSpecies(this.species).forms.length - 1), 0);
|
||||||
this.abilityIndex = source.abilityIndex;
|
this.abilityIndex = source.abilityIndex;
|
||||||
this.passive = source.passive;
|
this.passive = source.passive;
|
||||||
this.shiny = sourcePokemon?.summonData.illusion?.basePokemon.shiny ?? source.shiny;
|
this.shiny = source.shiny;
|
||||||
this.variant = sourcePokemon?.summonData.illusion?.basePokemon.variant ?? source.variant;
|
this.variant = source.variant;
|
||||||
this.pokeball = source.pokeball ?? PokeballType.POKEBALL;
|
this.pokeball = source.pokeball ?? PokeballType.POKEBALL;
|
||||||
this.level = source.level;
|
this.level = source.level;
|
||||||
this.exp = source.exp;
|
this.exp = source.exp;
|
||||||
@ -134,8 +134,8 @@ export class PokemonData {
|
|||||||
this.fusionSpecies = sourcePokemon?.fusionSpecies?.speciesId ?? source.fusionSpecies;
|
this.fusionSpecies = sourcePokemon?.fusionSpecies?.speciesId ?? source.fusionSpecies;
|
||||||
this.fusionFormIndex = source.fusionFormIndex;
|
this.fusionFormIndex = source.fusionFormIndex;
|
||||||
this.fusionAbilityIndex = source.fusionAbilityIndex;
|
this.fusionAbilityIndex = source.fusionAbilityIndex;
|
||||||
this.fusionShiny = sourcePokemon?.summonData.illusion?.basePokemon.fusionShiny ?? source.fusionShiny;
|
this.fusionShiny = source.fusionShiny;
|
||||||
this.fusionVariant = sourcePokemon?.summonData.illusion?.basePokemon.fusionVariant ?? source.fusionVariant;
|
this.fusionVariant = source.fusionVariant;
|
||||||
this.fusionGender = source.fusionGender;
|
this.fusionGender = source.fusionGender;
|
||||||
this.fusionLuck = source.fusionLuck ?? (source.fusionShiny ? source.fusionVariant + 1 : 0);
|
this.fusionLuck = source.fusionLuck ?? (source.fusionShiny ? source.fusionVariant + 1 : 0);
|
||||||
this.fusionTeraType = (source.fusionTeraType ?? 0) as PokemonType;
|
this.fusionTeraType = (source.fusionTeraType ?? 0) as PokemonType;
|
||||||
|
@ -171,6 +171,7 @@ export const SettingKeys = {
|
|||||||
UI_Volume: "UI_SOUND_EFFECTS",
|
UI_Volume: "UI_SOUND_EFFECTS",
|
||||||
Battle_Music: "BATTLE_MUSIC",
|
Battle_Music: "BATTLE_MUSIC",
|
||||||
Show_BGM_Bar: "SHOW_BGM_BAR",
|
Show_BGM_Bar: "SHOW_BGM_BAR",
|
||||||
|
Hide_Username: "HIDE_USERNAME",
|
||||||
Move_Touch_Controls: "MOVE_TOUCH_CONTROLS",
|
Move_Touch_Controls: "MOVE_TOUCH_CONTROLS",
|
||||||
Shop_Overlay_Opacity: "SHOP_OVERLAY_OPACITY",
|
Shop_Overlay_Opacity: "SHOP_OVERLAY_OPACITY",
|
||||||
};
|
};
|
||||||
@ -625,6 +626,13 @@ export const Setting: Array<Setting> = [
|
|||||||
default: 1,
|
default: 1,
|
||||||
type: SettingType.DISPLAY,
|
type: SettingType.DISPLAY,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: SettingKeys.Hide_Username,
|
||||||
|
label: i18next.t("settings:hideUsername"),
|
||||||
|
options: OFF_ON,
|
||||||
|
default: 0,
|
||||||
|
type: SettingType.DISPLAY,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: SettingKeys.Master_Volume,
|
key: SettingKeys.Master_Volume,
|
||||||
label: i18next.t("settings:masterVolume"),
|
label: i18next.t("settings:masterVolume"),
|
||||||
@ -792,6 +800,9 @@ export function setSetting(setting: string, value: number): boolean {
|
|||||||
case SettingKeys.Show_BGM_Bar:
|
case SettingKeys.Show_BGM_Bar:
|
||||||
globalScene.showBgmBar = Setting[index].options[value].value === "On";
|
globalScene.showBgmBar = Setting[index].options[value].value === "On";
|
||||||
break;
|
break;
|
||||||
|
case SettingKeys.Hide_Username:
|
||||||
|
globalScene.hideUsername = Setting[index].options[value].value === "On";
|
||||||
|
break;
|
||||||
case SettingKeys.Candy_Upgrade_Notification:
|
case SettingKeys.Candy_Upgrade_Notification:
|
||||||
if (globalScene.candyUpgradeNotification === value) {
|
if (globalScene.candyUpgradeNotification === value) {
|
||||||
break;
|
break;
|
||||||
|
@ -5,8 +5,9 @@ import { Challenges } from "#enums/challenges";
|
|||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { WeatherType } from "#enums/weather-type";
|
import { WeatherType } from "#enums/weather-type";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import type { nil } from "#utils/common";
|
import type { nil } from "#utils/common";
|
||||||
import { isNullOrUndefined } from "#utils/common";
|
import { isNullOrUndefined } from "#utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { TextStyle } from "#enums/text-style";
|
||||||
|
import { addTextObject } from "#ui/text";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
const barWidth = 118;
|
const barWidth = 118;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { addBBCodeTextObject, getTextColor, getTextStyleOptions, TextStyle } from "#ui/text";
|
import { addBBCodeTextObject, getTextColor, getTextStyleOptions } from "#ui/text";
|
||||||
import { UiHandler } from "#ui/ui-handler";
|
import { UiHandler } from "#ui/ui-handler";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { fixedInt, rgbHexToRgba } from "#utils/common";
|
import { fixedInt, rgbHexToRgba } from "#utils/common";
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { PlayerGender } from "#enums/player-gender";
|
import type { PlayerGender } from "#enums/player-gender";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { Achv, getAchievementDescription } from "#system/achv";
|
import { Achv, getAchievementDescription } from "#system/achv";
|
||||||
import { Voucher } from "#system/voucher";
|
import { Voucher } from "#system/voucher";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
|
|
||||||
export class AchvBar extends Phaser.GameObjects.Container {
|
export class AchvBar extends Phaser.GameObjects.Container {
|
||||||
private defaultWidth: number;
|
private defaultWidth: number;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
import { PlayerGender } from "#enums/player-gender";
|
import { PlayerGender } from "#enums/player-gender";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { UiMode } from "#enums/ui-mode";
|
import type { UiMode } from "#enums/ui-mode";
|
||||||
import type { Achv } from "#system/achv";
|
import type { Achv } from "#system/achv";
|
||||||
import { achvs, getAchievementDescription } from "#system/achv";
|
import { achvs, getAchievementDescription } from "#system/achv";
|
||||||
@ -9,7 +10,7 @@ import type { Voucher } from "#system/voucher";
|
|||||||
import { getVoucherTypeIcon, getVoucherTypeName, vouchers } from "#system/voucher";
|
import { getVoucherTypeIcon, getVoucherTypeName, vouchers } from "#system/voucher";
|
||||||
import { MessageUiHandler } from "#ui/message-ui-handler";
|
import { MessageUiHandler } from "#ui/message-ui-handler";
|
||||||
import { ScrollBar } from "#ui/scroll-bar";
|
import { ScrollBar } from "#ui/scroll-bar";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { pokerogueApi } from "#api/pokerogue-api";
|
import { pokerogueApi } from "#api/pokerogue-api";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { InputFieldConfig } from "#ui/form-modal-ui-handler";
|
import type { InputFieldConfig } from "#ui/form-modal-ui-handler";
|
||||||
import { FormModalUiHandler } from "#ui/form-modal-ui-handler";
|
import { FormModalUiHandler } from "#ui/form-modal-ui-handler";
|
||||||
import type { ModalConfig } from "#ui/modal-ui-handler";
|
import type { ModalConfig } from "#ui/modal-ui-handler";
|
||||||
import { TextStyle } from "#ui/text";
|
import { toTitleCase } from "#utils/strings";
|
||||||
import { formatText } from "#utils/common";
|
|
||||||
|
|
||||||
type AdminUiHandlerService = "discord" | "google";
|
type AdminUiHandlerService = "discord" | "google";
|
||||||
type AdminUiHandlerServiceMode = "Link" | "Unlink";
|
type AdminUiHandlerServiceMode = "Link" | "Unlink";
|
||||||
@ -21,9 +21,9 @@ export class AdminUiHandler extends FormModalUiHandler {
|
|||||||
private readonly httpUserNotFoundErrorCode: number = 404;
|
private readonly httpUserNotFoundErrorCode: number = 404;
|
||||||
private readonly ERR_REQUIRED_FIELD = (field: string) => {
|
private readonly ERR_REQUIRED_FIELD = (field: string) => {
|
||||||
if (field === "username") {
|
if (field === "username") {
|
||||||
return `${formatText(field)} is required`;
|
return `${toTitleCase(field)} is required`;
|
||||||
}
|
}
|
||||||
return `${formatText(field)} Id is required`;
|
return `${toTitleCase(field)} Id is required`;
|
||||||
};
|
};
|
||||||
// returns a string saying whether a username has been successfully linked/unlinked to discord/google
|
// returns a string saying whether a username has been successfully linked/unlinked to discord/google
|
||||||
private readonly SUCCESS_SERVICE_MODE = (service: string, mode: string) => {
|
private readonly SUCCESS_SERVICE_MODE = (service: string, mode: string) => {
|
||||||
|
@ -3,6 +3,7 @@ import { ArenaTrapTag } from "#data/arena-tag";
|
|||||||
import { TerrainType } from "#data/terrain";
|
import { TerrainType } from "#data/terrain";
|
||||||
import { ArenaTagSide } from "#enums/arena-tag-side";
|
import { ArenaTagSide } from "#enums/arena-tag-side";
|
||||||
import { ArenaTagType } from "#enums/arena-tag-type";
|
import { ArenaTagType } from "#enums/arena-tag-type";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { WeatherType } from "#enums/weather-type";
|
import { WeatherType } from "#enums/weather-type";
|
||||||
import type { ArenaEvent } from "#events/arena";
|
import type { ArenaEvent } from "#events/arena";
|
||||||
import {
|
import {
|
||||||
@ -14,10 +15,11 @@ import {
|
|||||||
} from "#events/arena";
|
} from "#events/arena";
|
||||||
import type { TurnEndEvent } from "#events/battle-scene";
|
import type { TurnEndEvent } from "#events/battle-scene";
|
||||||
import { BattleSceneEventType } from "#events/battle-scene";
|
import { BattleSceneEventType } from "#events/battle-scene";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { TimeOfDayWidget } from "#ui/time-of-day-widget";
|
import { TimeOfDayWidget } from "#ui/time-of-day-widget";
|
||||||
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
||||||
import { fixedInt, formatText, toCamelCaseString } from "#utils/common";
|
import { fixedInt } from "#utils/common";
|
||||||
|
import { toCamelCase, toTitleCase } from "#utils/strings";
|
||||||
import type { ParseKeys } from "i18next";
|
import type { ParseKeys } from "i18next";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
@ -48,10 +50,10 @@ export function getFieldEffectText(arenaTagType: string): string {
|
|||||||
if (!arenaTagType || arenaTagType === ArenaTagType.NONE) {
|
if (!arenaTagType || arenaTagType === ArenaTagType.NONE) {
|
||||||
return arenaTagType;
|
return arenaTagType;
|
||||||
}
|
}
|
||||||
const effectName = toCamelCaseString(arenaTagType);
|
const effectName = toCamelCase(arenaTagType);
|
||||||
const i18nKey = `arenaFlyout:${effectName}` as ParseKeys;
|
const i18nKey = `arenaFlyout:${effectName}` as ParseKeys;
|
||||||
const resultName = i18next.t(i18nKey);
|
const resultName = i18next.t(i18nKey);
|
||||||
return !resultName || resultName === i18nKey ? formatText(arenaTagType) : resultName;
|
return !resultName || resultName === i18nKey ? toTitleCase(arenaTagType) : resultName;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ArenaFlyout extends Phaser.GameObjects.Container {
|
export class ArenaFlyout extends Phaser.GameObjects.Container {
|
||||||
|
@ -2,9 +2,10 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { getPokeballName } from "#data/pokeball";
|
import { getPokeballName } from "#data/pokeball";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
import { Command } from "#enums/command";
|
import { Command } from "#enums/command";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { CommandPhase } from "#phases/command-phase";
|
import type { CommandPhase } from "#phases/command-phase";
|
||||||
import { addTextObject, getTextStyleOptions, TextStyle } from "#ui/text";
|
import { addTextObject, getTextStyleOptions } from "#ui/text";
|
||||||
import { UiHandler } from "#ui/ui-handler";
|
import { UiHandler } from "#ui/ui-handler";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import type { InfoToggle } from "#app/battle-scene";
|
import type { InfoToggle } from "#app/battle-scene";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { TextStyle } from "#enums/text-style";
|
||||||
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { fixedInt } from "#utils/common";
|
import { fixedInt } from "#utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@ -2,12 +2,13 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { getPokemonNameWithAffix } from "#app/messages";
|
import { getPokemonNameWithAffix } from "#app/messages";
|
||||||
import { BerryType } from "#enums/berry-type";
|
import { BerryType } from "#enums/berry-type";
|
||||||
import { MoveId } from "#enums/move-id";
|
import { MoveId } from "#enums/move-id";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiTheme } from "#enums/ui-theme";
|
import { UiTheme } from "#enums/ui-theme";
|
||||||
import type { BerryUsedEvent, MoveUsedEvent } from "#events/battle-scene";
|
import type { BerryUsedEvent, MoveUsedEvent } from "#events/battle-scene";
|
||||||
import { BattleSceneEventType } from "#events/battle-scene";
|
import { BattleSceneEventType } from "#events/battle-scene";
|
||||||
import type { EnemyPokemon, Pokemon } from "#field/pokemon";
|
import type { EnemyPokemon, Pokemon } from "#field/pokemon";
|
||||||
import type { Move } from "#moves/move";
|
import type { Move } from "#moves/move";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { fixedInt } from "#utils/common";
|
import { fixedInt } from "#utils/common";
|
||||||
|
|
||||||
/** Container for info about a {@linkcode Move} */
|
/** Container for info about a {@linkcode Move} */
|
||||||
|
@ -4,9 +4,10 @@ import { getTypeRgb } from "#data/type";
|
|||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { Pokemon } from "#field/pokemon";
|
import type { Pokemon } from "#field/pokemon";
|
||||||
import { getVariantTint } from "#sprites/variant";
|
import { getVariantTint } from "#sprites/variant";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { fixedInt, getLocalizedSpriteKey, getShinyDescriptor } from "#utils/common";
|
import { fixedInt, getLocalizedSpriteKey, getShinyDescriptor } from "#utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { EnemyPokemon } from "#field/pokemon";
|
import type { EnemyPokemon } from "#field/pokemon";
|
||||||
import { BattleFlyout } from "#ui/battle-flyout";
|
import { BattleFlyout } from "#ui/battle-flyout";
|
||||||
import type { BattleInfoParamList } from "#ui/battle-info";
|
import type { BattleInfoParamList } from "#ui/battle-info";
|
||||||
import { BattleInfo } from "#ui/battle-info";
|
import { BattleInfo } from "#ui/battle-info";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import type { GameObjects } from "phaser";
|
import type { GameObjects } from "phaser";
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
import { getStatKey, PERMANENT_STATS } from "#enums/stat";
|
import { getStatKey, PERMANENT_STATS } from "#enums/stat";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { MessageUiHandler } from "#ui/message-ui-handler";
|
import { MessageUiHandler } from "#ui/message-ui-handler";
|
||||||
import { addBBCodeTextObject, addTextObject, getTextColor, TextStyle } from "#ui/text";
|
import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import type BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
|
import type BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { formatText } from "#utils/common";
|
import { addTextObject } from "#ui/text";
|
||||||
|
import { toTitleCase } from "#utils/strings";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
const hiddenX = -150;
|
const hiddenX = -150;
|
||||||
@ -100,7 +101,7 @@ export class BgmBar extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
getRealBgmName(bgmName: string): string {
|
getRealBgmName(bgmName: string): string {
|
||||||
return i18next.t([`bgmName:${bgmName}`, "bgmName:missing_entries"], {
|
return i18next.t([`bgmName:${bgmName}`, "bgmName:missing_entries"], {
|
||||||
name: formatText(bgmName),
|
name: toTitleCase(bgmName),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { starterColors } from "#app/global-vars/starter-colors";
|
import { starterColors } from "#app/global-vars/starter-colors";
|
||||||
import type { SpeciesId } from "#enums/species-id";
|
import type { SpeciesId } from "#enums/species-id";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { TextStyle } from "#enums/text-style";
|
||||||
|
import { addTextObject } from "#ui/text";
|
||||||
import { rgbHexToRgba } from "#utils/common";
|
import { rgbHexToRgba } from "#utils/common";
|
||||||
import { argbFromRgba } from "@material/material-color-utilities";
|
import { argbFromRgba } from "@material/material-color-utilities";
|
||||||
|
|
||||||
|
@ -3,8 +3,9 @@ import type { Challenge } from "#data/challenge";
|
|||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
import { Challenges } from "#enums/challenges";
|
import { Challenges } from "#enums/challenges";
|
||||||
import { Color, ShadowColor } from "#enums/color";
|
import { Color, ShadowColor } from "#enums/color";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { UiMode } from "#enums/ui-mode";
|
import type { UiMode } from "#enums/ui-mode";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { UiHandler } from "#ui/ui-handler";
|
import { UiHandler } from "#ui/ui-handler";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { getLocalizedSpriteKey } from "#utils/common";
|
import { getLocalizedSpriteKey } from "#utils/common";
|
||||||
|
@ -5,11 +5,12 @@ import { Button } from "#enums/buttons";
|
|||||||
import { Command } from "#enums/command";
|
import { Command } from "#enums/command";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { TerastallizeAccessModifier } from "#modifiers/modifier";
|
import { TerastallizeAccessModifier } from "#modifiers/modifier";
|
||||||
import type { CommandPhase } from "#phases/command-phase";
|
import type { CommandPhase } from "#phases/command-phase";
|
||||||
import { PartyUiHandler, PartyUiMode } from "#ui/party-ui-handler";
|
import { PartyUiHandler, PartyUiMode } from "#ui/party-ui-handler";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { UiHandler } from "#ui/ui-handler";
|
import { UiHandler } from "#ui/ui-handler";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { pokerogueApi } from "#api/pokerogue-api";
|
import { pokerogueApi } from "#api/pokerogue-api";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { TextStyle } from "#enums/text-style";
|
||||||
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
||||||
import { executeIf } from "#utils/common";
|
import { executeIf } from "#utils/common";
|
||||||
import { getEnumKeys } from "#utils/enums";
|
import { getEnumKeys } from "#utils/enums";
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { ScrollBar } from "#ui/scroll-bar";
|
import { ScrollBar } from "#ui/scroll-bar";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { EggCountChangedEvent } from "#events/egg";
|
import type { EggCountChangedEvent } from "#events/egg";
|
||||||
import { EggEventType } from "#events/egg";
|
import { EggEventType } from "#events/egg";
|
||||||
import type { EggHatchSceneHandler } from "#ui/egg-hatch-scene-handler";
|
import type { EggHatchSceneHandler } from "#ui/egg-hatch-scene-handler";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,10 +6,11 @@ import { Egg, getLegendaryGachaSpeciesForTimestamp } from "#data/egg";
|
|||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
import { EggTier } from "#enums/egg-type";
|
import { EggTier } from "#enums/egg-type";
|
||||||
import { GachaType } from "#enums/gacha-types";
|
import { GachaType } from "#enums/gacha-types";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { getVoucherTypeIcon, VoucherType } from "#system/voucher";
|
import { getVoucherTypeIcon, VoucherType } from "#system/voucher";
|
||||||
import { MessageUiHandler } from "#ui/message-ui-handler";
|
import { MessageUiHandler } from "#ui/message-ui-handler";
|
||||||
import { addTextObject, getEggTierTextTint, getTextStyleOptions, TextStyle } from "#ui/text";
|
import { addTextObject, getEggTierTextTint, getTextStyleOptions } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { fixedInt, randSeedShuffle } from "#utils/common";
|
import { fixedInt, randSeedShuffle } from "#utils/common";
|
||||||
import { getEnumValues } from "#utils/enums";
|
import { getEnumValues } from "#utils/enums";
|
||||||
@ -74,7 +75,7 @@ export class EggGachaUiHandler extends MessageUiHandler {
|
|||||||
const gachaInfoContainer = globalScene.add.container(160, 46);
|
const gachaInfoContainer = globalScene.add.container(160, 46);
|
||||||
|
|
||||||
const currentLanguage = i18next.resolvedLanguage ?? "en";
|
const currentLanguage = i18next.resolvedLanguage ?? "en";
|
||||||
let gachaTextStyle = TextStyle.WINDOW_ALT;
|
let gachaTextStyle: TextStyle = TextStyle.WINDOW_ALT;
|
||||||
let gachaX = 4;
|
let gachaX = 4;
|
||||||
let gachaY = 0;
|
let gachaY = 0;
|
||||||
let pokemonIconX = -20;
|
let pokemonIconX = -20;
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { MessageUiHandler } from "#ui/message-ui-handler";
|
import { MessageUiHandler } from "#ui/message-ui-handler";
|
||||||
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/pokemon-icon-anim-handler";
|
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/pokemon-icon-anim-handler";
|
||||||
import { ScrollBar } from "#ui/scroll-bar";
|
import { ScrollBar } from "#ui/scroll-bar";
|
||||||
import { ScrollableGridUiHandler } from "#ui/scrollable-grid-handler";
|
import { ScrollableGridUiHandler } from "#ui/scrollable-grid-handler";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { MessageUiHandler } from "#ui/message-ui-handler";
|
import { MessageUiHandler } from "#ui/message-ui-handler";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
|
|
||||||
export class EvolutionSceneHandler extends MessageUiHandler {
|
export class EvolutionSceneHandler extends MessageUiHandler {
|
||||||
public evolutionContainer: Phaser.GameObjects.Container;
|
public evolutionContainer: Phaser.GameObjects.Container;
|
||||||
|
@ -7,12 +7,13 @@ import { Command } from "#enums/command";
|
|||||||
import { MoveCategory } from "#enums/move-category";
|
import { MoveCategory } from "#enums/move-category";
|
||||||
import { MoveUseMode } from "#enums/move-use-mode";
|
import { MoveUseMode } from "#enums/move-use-mode";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { EnemyPokemon, Pokemon } from "#field/pokemon";
|
import type { EnemyPokemon, Pokemon } from "#field/pokemon";
|
||||||
import type { PokemonMove } from "#moves/pokemon-move";
|
import type { PokemonMove } from "#moves/pokemon-move";
|
||||||
import type { CommandPhase } from "#phases/command-phase";
|
import type { CommandPhase } from "#phases/command-phase";
|
||||||
import { MoveInfoOverlay } from "#ui/move-info-overlay";
|
import { MoveInfoOverlay } from "#ui/move-info-overlay";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { UiHandler } from "#ui/ui-handler";
|
import { UiHandler } from "#ui/ui-handler";
|
||||||
import { fixedInt, getLocalizedSpriteKey, padInt } from "#utils/common";
|
import { fixedInt, getLocalizedSpriteKey, padInt } from "#utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
@ -284,7 +285,7 @@ export class FightUiHandler extends UiHandler implements InfoToggle {
|
|||||||
|
|
||||||
const ppColorStyle = FightUiHandler.ppRatioToColor(pp / maxPP);
|
const ppColorStyle = FightUiHandler.ppRatioToColor(pp / maxPP);
|
||||||
|
|
||||||
//** Changes the text color and shadow according to the determined TextStyle */
|
// Changes the text color and shadow according to the determined TextStyle
|
||||||
this.ppText.setColor(this.getTextColor(ppColorStyle, false)).setShadowColor(this.getTextColor(ppColorStyle, true));
|
this.ppText.setColor(this.getTextColor(ppColorStyle, false)).setShadowColor(this.getTextColor(ppColorStyle, true));
|
||||||
this.moveInfoOverlay.show(pokemonMove.getMove());
|
this.moveInfoOverlay.show(pokemonMove.getMove());
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { DropDownColumn } from "#enums/drop-down-column";
|
import type { DropDownColumn } from "#enums/drop-down-column";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { UiTheme } from "#enums/ui-theme";
|
import type { UiTheme } from "#enums/ui-theme";
|
||||||
import type { DropDown } from "#ui/dropdown";
|
import type { DropDown } from "#ui/dropdown";
|
||||||
import { DropDownType } from "#ui/dropdown";
|
import { DropDownType } from "#ui/dropdown";
|
||||||
import type { StarterContainer } from "#ui/starter-container";
|
import type { StarterContainer } from "#ui/starter-container";
|
||||||
import { addTextObject, getTextColor, TextStyle } from "#ui/text";
|
import { addTextObject, getTextColor } from "#ui/text";
|
||||||
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
||||||
|
|
||||||
export class FilterBar extends Phaser.GameObjects.Container {
|
export class FilterBar extends Phaser.GameObjects.Container {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { UiTheme } from "#enums/ui-theme";
|
import type { UiTheme } from "#enums/ui-theme";
|
||||||
import type { AwaitableUiHandler } from "#ui/awaitable-ui-handler";
|
import type { AwaitableUiHandler } from "#ui/awaitable-ui-handler";
|
||||||
import type { StarterContainer } from "#ui/starter-container";
|
import type { StarterContainer } from "#ui/starter-container";
|
||||||
import { addTextObject, getTextColor, TextStyle } from "#ui/text";
|
import { addTextObject, getTextColor } from "#ui/text";
|
||||||
import type { UI } from "#ui/ui";
|
import type { UI } from "#ui/ui";
|
||||||
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { UiMode } from "#enums/ui-mode";
|
import type { UiMode } from "#enums/ui-mode";
|
||||||
import type { ModalConfig } from "#ui/modal-ui-handler";
|
import type { ModalConfig } from "#ui/modal-ui-handler";
|
||||||
import { ModalUiHandler } from "#ui/modal-ui-handler";
|
import { ModalUiHandler } from "#ui/modal-ui-handler";
|
||||||
import { addTextInputObject, addTextObject, TextStyle } from "#ui/text";
|
import { addTextInputObject, addTextObject } from "#ui/text";
|
||||||
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
||||||
import { fixedInt } from "#utils/common";
|
import { fixedInt } from "#utils/common";
|
||||||
import type InputText from "phaser3-rex-plugins/plugins/inputtext";
|
import type InputText from "phaser3-rex-plugins/plugins/inputtext";
|
||||||
|
@ -2,12 +2,14 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import { speciesStarterCosts } from "#balance/starters";
|
import { speciesStarterCosts } from "#balance/starters";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
import { DexAttr } from "#enums/dex-attr";
|
import { DexAttr } from "#enums/dex-attr";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiTheme } from "#enums/ui-theme";
|
import { UiTheme } from "#enums/ui-theme";
|
||||||
import type { GameData } from "#system/game-data";
|
import type { GameData } from "#system/game-data";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { UiHandler } from "#ui/ui-handler";
|
import { UiHandler } from "#ui/ui-handler";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { formatFancyLargeNumber, getPlayTimeString, toReadableString } from "#utils/common";
|
import { formatFancyLargeNumber, getPlayTimeString } from "#utils/common";
|
||||||
|
import { toTitleCase } from "#utils/strings";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
|
|
||||||
@ -501,11 +503,9 @@ export function initStatsKeys() {
|
|||||||
sourceFunc: gameData => gameData.gameStats[key].toString(),
|
sourceFunc: gameData => gameData.gameStats[key].toString(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (!(displayStats[key] as DisplayStat).label_key) {
|
if (!displayStats[key].label_key) {
|
||||||
const splittableKey = key.replace(/([a-z]{2,})([A-Z]{1}(?:[^A-Z]|$))/g, "$1_$2");
|
const splittableKey = key.replace(/([a-z]{2,})([A-Z]{1}(?:[^A-Z]|$))/g, "$1_$2");
|
||||||
(displayStats[key] as DisplayStat).label_key = toReadableString(
|
displayStats[key].label_key = toTitleCase(splittableKey);
|
||||||
`${splittableKey[0].toUpperCase()}${splittableKey.slice(1)}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { UiMode } from "#enums/ui-mode";
|
import type { UiMode } from "#enums/ui-mode";
|
||||||
import { ModalUiHandler } from "#ui/modal-ui-handler";
|
import { ModalUiHandler } from "#ui/modal-ui-handler";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class LoadingModalUiHandler extends ModalUiHandler {
|
export class LoadingModalUiHandler extends ModalUiHandler {
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { pokerogueApi } from "#api/pokerogue-api";
|
import { pokerogueApi } from "#api/pokerogue-api";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler";
|
import type { OptionSelectItem } from "#ui/abstact-option-select-ui-handler";
|
||||||
import type { InputFieldConfig } from "#ui/form-modal-ui-handler";
|
import type { InputFieldConfig } from "#ui/form-modal-ui-handler";
|
||||||
import { FormModalUiHandler } from "#ui/form-modal-ui-handler";
|
import { FormModalUiHandler } from "#ui/form-modal-ui-handler";
|
||||||
import type { ModalConfig } from "#ui/modal-ui-handler";
|
import type { ModalConfig } from "#ui/modal-ui-handler";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { fixedInt } from "#utils/common";
|
import { fixedInt } from "#utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@ -5,13 +5,14 @@ import { bypassLogin } from "#app/global-vars/bypass-login";
|
|||||||
import { handleTutorial, Tutorial } from "#app/tutorial";
|
import { handleTutorial, Tutorial } from "#app/tutorial";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
import { GameDataType } from "#enums/game-data-type";
|
import { GameDataType } from "#enums/game-data-type";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { OptionSelectConfig, OptionSelectItem } from "#ui/abstact-option-select-ui-handler";
|
import type { OptionSelectConfig, OptionSelectItem } from "#ui/abstact-option-select-ui-handler";
|
||||||
import { AdminMode, getAdminModeName } from "#ui/admin-ui-handler";
|
import { AdminMode, getAdminModeName } from "#ui/admin-ui-handler";
|
||||||
import type { AwaitableUiHandler } from "#ui/awaitable-ui-handler";
|
import type { AwaitableUiHandler } from "#ui/awaitable-ui-handler";
|
||||||
import { BgmBar } from "#ui/bgm-bar";
|
import { BgmBar } from "#ui/bgm-bar";
|
||||||
import { MessageUiHandler } from "#ui/message-ui-handler";
|
import { MessageUiHandler } from "#ui/message-ui-handler";
|
||||||
import { addTextObject, getTextStyleOptions, TextStyle } from "#ui/text";
|
import { addTextObject, getTextStyleOptions } from "#ui/text";
|
||||||
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
||||||
import { fixedInt, isLocal, sessionIdKey } from "#utils/common";
|
import { fixedInt, isLocal, sessionIdKey } from "#utils/common";
|
||||||
import { getCookie } from "#utils/cookies";
|
import { getCookie } from "#utils/cookies";
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { Button } from "#enums/buttons";
|
import type { Button } from "#enums/buttons";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { UiMode } from "#enums/ui-mode";
|
import type { UiMode } from "#enums/ui-mode";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { UiHandler } from "#ui/ui-handler";
|
import { UiHandler } from "#ui/ui-handler";
|
||||||
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
||||||
|
|
||||||
|
@ -6,13 +6,14 @@ import { getPokeballAtlasKey } from "#data/pokeball";
|
|||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
import type { PokeballType } from "#enums/pokeball";
|
import type { PokeballType } from "#enums/pokeball";
|
||||||
import { ShopCursorTarget } from "#enums/shop-cursor-target";
|
import { ShopCursorTarget } from "#enums/shop-cursor-target";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { HealShopCostModifier, LockModifierTiersModifier, PokemonHeldItemModifier } from "#modifiers/modifier";
|
import { HealShopCostModifier, LockModifierTiersModifier, PokemonHeldItemModifier } from "#modifiers/modifier";
|
||||||
import type { ModifierTypeOption } from "#modifiers/modifier-type";
|
import type { ModifierTypeOption } from "#modifiers/modifier-type";
|
||||||
import { getPlayerShopModifierTypeOptionsForWave, TmModifierType } from "#modifiers/modifier-type";
|
import { getPlayerShopModifierTypeOptionsForWave, TmModifierType } from "#modifiers/modifier-type";
|
||||||
import { AwaitableUiHandler } from "#ui/awaitable-ui-handler";
|
import { AwaitableUiHandler } from "#ui/awaitable-ui-handler";
|
||||||
import { MoveInfoOverlay } from "#ui/move-info-overlay";
|
import { MoveInfoOverlay } from "#ui/move-info-overlay";
|
||||||
import { addTextObject, getModifierTierTextTint, getTextColor, getTextStyleOptions, TextStyle } from "#ui/text";
|
import { addTextObject, getModifierTierTextTint, getTextColor, getTextStyleOptions } from "#ui/text";
|
||||||
import { formatMoney, NumberHolder } from "#utils/common";
|
import { formatMoney, NumberHolder } from "#utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
|
@ -2,8 +2,9 @@ import type { InfoToggle } from "#app/battle-scene";
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { MoveCategory } from "#enums/move-category";
|
import { MoveCategory } from "#enums/move-category";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { Move } from "#moves/move";
|
import type { Move } from "#moves/move";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { fixedInt, getLocalizedSpriteKey } from "#utils/common";
|
import { fixedInt, getLocalizedSpriteKey } from "#utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@ -3,13 +3,14 @@ import { getPokeballAtlasKey } from "#data/pokeball";
|
|||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
|
||||||
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import { getEncounterText } from "#mystery-encounters/encounter-dialogue-utils";
|
import { getEncounterText } from "#mystery-encounters/encounter-dialogue-utils";
|
||||||
import type { OptionSelectSettings } from "#mystery-encounters/encounter-phase-utils";
|
import type { OptionSelectSettings } from "#mystery-encounters/encounter-phase-utils";
|
||||||
import type { MysteryEncounterOption } from "#mystery-encounters/mystery-encounter-option";
|
import type { MysteryEncounterOption } from "#mystery-encounters/mystery-encounter-option";
|
||||||
import type { MysteryEncounterPhase } from "#phases/mystery-encounter-phases";
|
import type { MysteryEncounterPhase } from "#phases/mystery-encounter-phases";
|
||||||
import { PartyUiMode } from "#ui/party-ui-handler";
|
import { PartyUiMode } from "#ui/party-ui-handler";
|
||||||
import { addBBCodeTextObject, getBBCodeFrag, TextStyle } from "#ui/text";
|
import { addBBCodeTextObject, getBBCodeFrag } from "#ui/text";
|
||||||
import { UiHandler } from "#ui/ui-handler";
|
import { UiHandler } from "#ui/ui-handler";
|
||||||
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
import { addWindow, WindowVariant } from "#ui/ui-theme";
|
||||||
import { fixedInt, isNullOrUndefined } from "#utils/common";
|
import { fixedInt, isNullOrUndefined } from "#utils/common";
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { Pokemon } from "#field/pokemon";
|
import type { Pokemon } from "#field/pokemon";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class PartyExpBar extends Phaser.GameObjects.Container {
|
export class PartyExpBar extends Phaser.GameObjects.Container {
|
||||||
|
@ -13,6 +13,7 @@ import { MoveId } from "#enums/move-id";
|
|||||||
import { MoveResult } from "#enums/move-result";
|
import { MoveResult } from "#enums/move-result";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { PlayerPokemon, Pokemon } from "#field/pokemon";
|
import type { PlayerPokemon, Pokemon } from "#field/pokemon";
|
||||||
import type { PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#modifiers/modifier";
|
import type { PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#modifiers/modifier";
|
||||||
@ -23,9 +24,10 @@ import type { TurnMove } from "#types/turn-move";
|
|||||||
import { MessageUiHandler } from "#ui/message-ui-handler";
|
import { MessageUiHandler } from "#ui/message-ui-handler";
|
||||||
import { MoveInfoOverlay } from "#ui/move-info-overlay";
|
import { MoveInfoOverlay } from "#ui/move-info-overlay";
|
||||||
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/pokemon-icon-anim-handler";
|
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/pokemon-icon-anim-handler";
|
||||||
import { addBBCodeTextObject, addTextObject, getTextColor, TextStyle } from "#ui/text";
|
import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { BooleanHolder, getLocalizedSpriteKey, randInt, toReadableString } from "#utils/common";
|
import { BooleanHolder, getLocalizedSpriteKey, randInt } from "#utils/common";
|
||||||
|
import { toTitleCase } from "#utils/strings";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import type BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
|
import type BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext";
|
||||||
|
|
||||||
@ -1408,7 +1410,7 @@ export class PartyUiHandler extends MessageUiHandler {
|
|||||||
if (this.localizedOptions.includes(option)) {
|
if (this.localizedOptions.includes(option)) {
|
||||||
optionName = i18next.t(`partyUiHandler:${PartyOption[option]}`);
|
optionName = i18next.t(`partyUiHandler:${PartyOption[option]}`);
|
||||||
} else {
|
} else {
|
||||||
optionName = toReadableString(PartyOption[option]);
|
optionName = toTitleCase(PartyOption[option]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1791,17 +1793,16 @@ class PartySlot extends Phaser.GameObjects.Container {
|
|||||||
const shinyStar = globalScene.add.image(0, 0, `shiny_star_small${doubleShiny ? "_1" : ""}`);
|
const shinyStar = globalScene.add.image(0, 0, `shiny_star_small${doubleShiny ? "_1" : ""}`);
|
||||||
shinyStar.setOrigin(0, 0);
|
shinyStar.setOrigin(0, 0);
|
||||||
shinyStar.setPositionRelative(this.slotName, -9, 3);
|
shinyStar.setPositionRelative(this.slotName, -9, 3);
|
||||||
shinyStar.setTint(getVariantTint(this.pokemon.getBaseVariant(doubleShiny)));
|
shinyStar.setTint(getVariantTint(this.pokemon.getBaseVariant()));
|
||||||
|
|
||||||
slotInfoContainer.add(shinyStar);
|
slotInfoContainer.add(shinyStar);
|
||||||
|
|
||||||
if (doubleShiny) {
|
if (doubleShiny) {
|
||||||
const fusionShinyStar = globalScene.add.image(0, 0, "shiny_star_small_2");
|
const fusionShinyStar = globalScene.add
|
||||||
fusionShinyStar.setOrigin(0, 0);
|
.image(0, 0, "shiny_star_small_2")
|
||||||
fusionShinyStar.setPosition(shinyStar.x, shinyStar.y);
|
.setOrigin(0)
|
||||||
fusionShinyStar.setTint(
|
.setPosition(shinyStar.x, shinyStar.y)
|
||||||
getVariantTint(this.pokemon.summonData.illusion?.basePokemon.fusionVariant ?? this.pokemon.fusionVariant),
|
.setTint(getVariantTint(this.pokemon.fusionVariant));
|
||||||
);
|
|
||||||
|
|
||||||
slotInfoContainer.add(fusionShinyStar);
|
slotInfoContainer.add(fusionShinyStar);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import type { InfoToggle } from "#app/battle-scene";
|
import type { InfoToggle } from "#app/battle-scene";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { TextStyle } from "#enums/text-style";
|
||||||
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { fixedInt } from "#utils/common";
|
import { fixedInt } from "#utils/common";
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { Variant } from "#sprites/variant";
|
import type { Variant } from "#sprites/variant";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { isNullOrUndefined } from "#utils/common";
|
import { isNullOrUndefined } from "#utils/common";
|
||||||
|
|
||||||
interface SpeciesDetails {
|
interface SpeciesDetails {
|
||||||
|
@ -38,6 +38,7 @@ import type { Nature } from "#enums/nature";
|
|||||||
import { Passive as PassiveAttr } from "#enums/passive";
|
import { Passive as PassiveAttr } from "#enums/passive";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { TimeOfDay } from "#enums/time-of-day";
|
import { TimeOfDay } from "#enums/time-of-day";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { Variant } from "#sprites/variant";
|
import type { Variant } from "#sprites/variant";
|
||||||
@ -51,18 +52,12 @@ import { MessageUiHandler } from "#ui/message-ui-handler";
|
|||||||
import { MoveInfoOverlay } from "#ui/move-info-overlay";
|
import { MoveInfoOverlay } from "#ui/move-info-overlay";
|
||||||
import { PokedexInfoOverlay } from "#ui/pokedex-info-overlay";
|
import { PokedexInfoOverlay } from "#ui/pokedex-info-overlay";
|
||||||
import { StatsContainer } from "#ui/stats-container";
|
import { StatsContainer } from "#ui/stats-container";
|
||||||
import { addBBCodeTextObject, addTextObject, getTextColor, getTextStyleOptions, TextStyle } from "#ui/text";
|
import { addBBCodeTextObject, addTextObject, getTextColor, getTextStyleOptions } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import {
|
import { BooleanHolder, getLocalizedSpriteKey, isNullOrUndefined, padInt, rgbHexToRgba } from "#utils/common";
|
||||||
BooleanHolder,
|
|
||||||
getLocalizedSpriteKey,
|
|
||||||
isNullOrUndefined,
|
|
||||||
padInt,
|
|
||||||
rgbHexToRgba,
|
|
||||||
toReadableString,
|
|
||||||
} from "#utils/common";
|
|
||||||
import { getEnumValues } from "#utils/enums";
|
import { getEnumValues } from "#utils/enums";
|
||||||
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
import { getPokemonSpecies } from "#utils/pokemon-utils";
|
||||||
|
import { toTitleCase } from "#utils/strings";
|
||||||
import { argbFromRgba } from "@material/material-color-utilities";
|
import { argbFromRgba } from "@material/material-color-utilities";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import type BBCodeText from "phaser3-rex-plugins/plugins/gameobjects/tagtext/bbcodetext/BBCodeText";
|
import type BBCodeText from "phaser3-rex-plugins/plugins/gameobjects/tagtext/bbcodetext/BBCodeText";
|
||||||
@ -2619,7 +2614,7 @@ export class PokedexPageUiHandler extends MessageUiHandler {
|
|||||||
|
|
||||||
// Setting growth rate text
|
// Setting growth rate text
|
||||||
if (isFormCaught) {
|
if (isFormCaught) {
|
||||||
let growthReadable = toReadableString(GrowthRate[species.growthRate]);
|
let growthReadable = toTitleCase(GrowthRate[species.growthRate]);
|
||||||
const growthAux = growthReadable.replace(" ", "_");
|
const growthAux = growthReadable.replace(" ", "_");
|
||||||
if (i18next.exists("growth:" + growthAux)) {
|
if (i18next.exists("growth:" + growthAux)) {
|
||||||
growthReadable = i18next.t(("growth:" + growthAux) as any);
|
growthReadable = i18next.t(("growth:" + growthAux) as any);
|
||||||
|
@ -26,6 +26,7 @@ import type { Nature } from "#enums/nature";
|
|||||||
import { Passive as PassiveAttr } from "#enums/passive";
|
import { Passive as PassiveAttr } from "#enums/passive";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import type { SpeciesId } from "#enums/species-id";
|
import type { SpeciesId } from "#enums/species-id";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { Variant } from "#sprites/variant";
|
import type { Variant } from "#sprites/variant";
|
||||||
import { getVariantIcon, getVariantTint } from "#sprites/variant";
|
import { getVariantIcon, getVariantTint } from "#sprites/variant";
|
||||||
@ -40,7 +41,7 @@ import { MessageUiHandler } from "#ui/message-ui-handler";
|
|||||||
import { PokedexMonContainer } from "#ui/pokedex-mon-container";
|
import { PokedexMonContainer } from "#ui/pokedex-mon-container";
|
||||||
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/pokemon-icon-anim-handler";
|
import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/pokemon-icon-anim-handler";
|
||||||
import { ScrollBar } from "#ui/scroll-bar";
|
import { ScrollBar } from "#ui/scroll-bar";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { BooleanHolder, fixedInt, getLocalizedSpriteKey, padInt, randIntRange, rgbHexToRgba } from "#utils/common";
|
import { BooleanHolder, fixedInt, getLocalizedSpriteKey, padInt, randIntRange, rgbHexToRgba } from "#utils/common";
|
||||||
import type { StarterPreferences } from "#utils/data";
|
import type { StarterPreferences } from "#utils/data";
|
||||||
|
@ -8,9 +8,10 @@ import { Gender } from "#data/gender";
|
|||||||
import { getPokemonSpeciesForm } from "#data/pokemon-species";
|
import { getPokemonSpeciesForm } from "#data/pokemon-species";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { PlayerPokemon } from "#field/pokemon";
|
import type { PlayerPokemon } from "#field/pokemon";
|
||||||
import { PokemonInfoContainer } from "#ui/pokemon-info-container";
|
import { PokemonInfoContainer } from "#ui/pokemon-info-container";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { padInt, rgbHexToRgba } from "#utils/common";
|
import { padInt, rgbHexToRgba } from "#utils/common";
|
||||||
import { argbFromRgba } from "@material/material-color-utilities";
|
import { argbFromRgba } from "@material/material-color-utilities";
|
||||||
|
|
||||||
|
@ -3,13 +3,14 @@ import { Gender, getGenderColor, getGenderSymbol } from "#data/gender";
|
|||||||
import { getNatureName } from "#data/nature";
|
import { getNatureName } from "#data/nature";
|
||||||
import { DexAttr } from "#enums/dex-attr";
|
import { DexAttr } from "#enums/dex-attr";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { Pokemon } from "#field/pokemon";
|
import type { Pokemon } from "#field/pokemon";
|
||||||
import { getVariantTint } from "#sprites/variant";
|
import { getVariantTint } from "#sprites/variant";
|
||||||
import type { StarterDataEntry } from "#system/game-data";
|
import type { StarterDataEntry } from "#system/game-data";
|
||||||
import type { DexEntry } from "#types/dex-data";
|
import type { DexEntry } from "#types/dex-data";
|
||||||
import { ConfirmUiHandler } from "#ui/confirm-ui-handler";
|
import { ConfirmUiHandler } from "#ui/confirm-ui-handler";
|
||||||
import { StatsContainer } from "#ui/stats-container";
|
import { StatsContainer } from "#ui/stats-container";
|
||||||
import { addBBCodeTextObject, addTextObject, getTextColor, TextStyle } from "#ui/text";
|
import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { fixedInt, getShinyDescriptor } from "#utils/common";
|
import { fixedInt, getShinyDescriptor } from "#utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { pokerogueApi } from "#api/pokerogue-api";
|
import { pokerogueApi } from "#api/pokerogue-api";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { InputFieldConfig } from "#ui/form-modal-ui-handler";
|
import type { InputFieldConfig } from "#ui/form-modal-ui-handler";
|
||||||
import { FormModalUiHandler } from "#ui/form-modal-ui-handler";
|
import { FormModalUiHandler } from "#ui/form-modal-ui-handler";
|
||||||
import type { ModalConfig } from "#ui/modal-ui-handler";
|
import type { ModalConfig } from "#ui/modal-ui-handler";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
interface LanguageSetting {
|
interface LanguageSetting {
|
||||||
|
@ -3,13 +3,14 @@ import { BattleType } from "#enums/battle-type";
|
|||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
import { GameModes } from "#enums/game-modes";
|
import { GameModes } from "#enums/game-modes";
|
||||||
import { PlayerGender } from "#enums/player-gender";
|
import { PlayerGender } from "#enums/player-gender";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { TrainerVariant } from "#enums/trainer-variant";
|
import { TrainerVariant } from "#enums/trainer-variant";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { RunEntry } from "#system/game-data";
|
import type { RunEntry } from "#system/game-data";
|
||||||
import type { PokemonData } from "#system/pokemon-data";
|
import type { PokemonData } from "#system/pokemon-data";
|
||||||
import { MessageUiHandler } from "#ui/message-ui-handler";
|
import { MessageUiHandler } from "#ui/message-ui-handler";
|
||||||
import { RunDisplayMode } from "#ui/run-info-ui-handler";
|
import { RunDisplayMode } from "#ui/run-info-ui-handler";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { fixedInt, formatLargeNumber } from "#utils/common";
|
import { fixedInt, formatLargeNumber } from "#utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@ -12,6 +12,7 @@ import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
|||||||
import { PlayerGender } from "#enums/player-gender";
|
import { PlayerGender } from "#enums/player-gender";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import type { SpeciesId } from "#enums/species-id";
|
import type { SpeciesId } from "#enums/species-id";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { TrainerVariant } from "#enums/trainer-variant";
|
import { TrainerVariant } from "#enums/trainer-variant";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
// biome-ignore lint/performance/noNamespaceImport: See `src/system/game-data.ts`
|
// biome-ignore lint/performance/noNamespaceImport: See `src/system/game-data.ts`
|
||||||
@ -21,7 +22,7 @@ import { getVariantTint } from "#sprites/variant";
|
|||||||
import type { SessionSaveData } from "#system/game-data";
|
import type { SessionSaveData } from "#system/game-data";
|
||||||
import type { PokemonData } from "#system/pokemon-data";
|
import type { PokemonData } from "#system/pokemon-data";
|
||||||
import { SettingKeyboard } from "#system/settings-keyboard";
|
import { SettingKeyboard } from "#system/settings-keyboard";
|
||||||
import { addBBCodeTextObject, addTextObject, getTextColor, TextStyle } from "#ui/text";
|
import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text";
|
||||||
import { UiHandler } from "#ui/ui-handler";
|
import { UiHandler } from "#ui/ui-handler";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { formatFancyLargeNumber, formatLargeNumber, formatMoney, getPlayTimeString } from "#utils/common";
|
import { formatFancyLargeNumber, formatLargeNumber, formatMoney, getPlayTimeString } from "#utils/common";
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { GameMode } from "#app/game-mode";
|
import { GameMode } from "#app/game-mode";
|
||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
// biome-ignore lint/performance/noNamespaceImport: See `src/system/game-data.ts`
|
// biome-ignore lint/performance/noNamespaceImport: See `src/system/game-data.ts`
|
||||||
import * as Modifier from "#modifiers/modifier";
|
import * as Modifier from "#modifiers/modifier";
|
||||||
@ -8,7 +9,7 @@ import type { SessionSaveData } from "#system/game-data";
|
|||||||
import type { PokemonData } from "#system/pokemon-data";
|
import type { PokemonData } from "#system/pokemon-data";
|
||||||
import { MessageUiHandler } from "#ui/message-ui-handler";
|
import { MessageUiHandler } from "#ui/message-ui-handler";
|
||||||
import { RunDisplayMode } from "#ui/run-info-ui-handler";
|
import { RunDisplayMode } from "#ui/run-info-ui-handler";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import { fixedInt, formatLargeNumber, getPlayTimeString, isNullOrUndefined } from "#utils/common";
|
import { fixedInt, formatLargeNumber, getPlayTimeString, isNullOrUndefined } from "#utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { UiMode } from "#enums/ui-mode";
|
import type { UiMode } from "#enums/ui-mode";
|
||||||
import type { ModalConfig } from "#ui/modal-ui-handler";
|
import type { ModalConfig } from "#ui/modal-ui-handler";
|
||||||
import { ModalUiHandler } from "#ui/modal-ui-handler";
|
import { ModalUiHandler } from "#ui/modal-ui-handler";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
|
|
||||||
export class SessionReloadModalUiHandler extends ModalUiHandler {
|
export class SessionReloadModalUiHandler extends ModalUiHandler {
|
||||||
constructor(mode: UiMode | null = null) {
|
constructor(mode: UiMode | null = null) {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { UiMode } from "#enums/ui-mode";
|
import type { UiMode } from "#enums/ui-mode";
|
||||||
import { NavigationManager } from "#ui/navigation-menu";
|
import { NavigationManager } from "#ui/navigation-menu";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { UiHandler } from "#ui/ui-handler";
|
import { UiHandler } from "#ui/ui-handler";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
@ -2,13 +2,15 @@ import { globalScene } from "#app/global-scene";
|
|||||||
import type { InterfaceConfig } from "#app/inputs-controller";
|
import type { InterfaceConfig } from "#app/inputs-controller";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
import type { Device } from "#enums/devices";
|
import type { Device } from "#enums/devices";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { UiMode } from "#enums/ui-mode";
|
import type { UiMode } from "#enums/ui-mode";
|
||||||
import { getIconWithSettingName } from "#inputs/config-handler";
|
import { getIconWithSettingName } from "#inputs/config-handler";
|
||||||
import { NavigationManager, NavigationMenu } from "#ui/navigation-menu";
|
import { NavigationManager, NavigationMenu } from "#ui/navigation-menu";
|
||||||
import { ScrollBar } from "#ui/scroll-bar";
|
import { ScrollBar } from "#ui/scroll-bar";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { UiHandler } from "#ui/ui-handler";
|
import { UiHandler } from "#ui/ui-handler";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
|
import { toCamelCase } from "#utils/strings";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export interface InputsIcons {
|
export interface InputsIcons {
|
||||||
@ -87,12 +89,6 @@ export abstract class AbstractControlSettingsUiHandler extends UiHandler {
|
|||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
private camelize(string: string): string {
|
|
||||||
return string
|
|
||||||
.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => (index === 0 ? word.toLowerCase() : word.toUpperCase()))
|
|
||||||
.replace(/\s+/g, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup UI elements.
|
* Setup UI elements.
|
||||||
*/
|
*/
|
||||||
@ -209,14 +205,15 @@ export abstract class AbstractControlSettingsUiHandler extends UiHandler {
|
|||||||
|
|
||||||
settingFiltered.forEach((setting, s) => {
|
settingFiltered.forEach((setting, s) => {
|
||||||
// Convert the setting key from format 'Key_Name' to 'Key name' for display.
|
// Convert the setting key from format 'Key_Name' to 'Key name' for display.
|
||||||
const settingName = setting.replace(/_/g, " ");
|
// TODO: IDK if this can be followed by both an underscore and a space, so leaving it as a regex matching both for now
|
||||||
|
const i18nKey = toCamelCase(setting.replace(/Alt(_| )/, ""));
|
||||||
|
|
||||||
// Create and add a text object for the setting name to the scene.
|
// Create and add a text object for the setting name to the scene.
|
||||||
const isLock = this.settingBlacklisted.includes(this.setting[setting]);
|
const isLock = this.settingBlacklisted.includes(this.setting[setting]);
|
||||||
const labelStyle = isLock ? TextStyle.SETTINGS_LOCKED : TextStyle.SETTINGS_LABEL;
|
const labelStyle = isLock ? TextStyle.SETTINGS_LOCKED : TextStyle.SETTINGS_LABEL;
|
||||||
|
const isAlt = setting.includes("Alt");
|
||||||
let labelText: string;
|
let labelText: string;
|
||||||
const i18nKey = this.camelize(settingName.replace("Alt ", ""));
|
if (isAlt) {
|
||||||
if (settingName.toLowerCase().includes("alt")) {
|
|
||||||
labelText = `${i18next.t(`settings:${i18nKey}`)}${i18next.t("settings:alt")}`;
|
labelText = `${i18next.t(`settings:${i18nKey}`)}${i18next.t("settings:alt")}`;
|
||||||
} else {
|
} else {
|
||||||
labelText = i18next.t(`settings:${i18nKey}`);
|
labelText = i18next.t(`settings:${i18nKey}`);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { SettingType } from "#system/settings";
|
import type { SettingType } from "#system/settings";
|
||||||
import { Setting, SettingKeys } from "#system/settings";
|
import { Setting, SettingKeys } from "#system/settings";
|
||||||
@ -7,7 +8,7 @@ import type { InputsIcons } from "#ui/abstract-control-settings-ui-handler";
|
|||||||
import { MessageUiHandler } from "#ui/message-ui-handler";
|
import { MessageUiHandler } from "#ui/message-ui-handler";
|
||||||
import { NavigationManager, NavigationMenu } from "#ui/navigation-menu";
|
import { NavigationManager, NavigationMenu } from "#ui/navigation-menu";
|
||||||
import { ScrollBar } from "#ui/scroll-bar";
|
import { ScrollBar } from "#ui/scroll-bar";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Device } from "#enums/devices";
|
import { Device } from "#enums/devices";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { UiMode } from "#enums/ui-mode";
|
import type { UiMode } from "#enums/ui-mode";
|
||||||
import { getIconWithSettingName, getKeyWithKeycode } from "#inputs/config-handler";
|
import { getIconWithSettingName, getKeyWithKeycode } from "#inputs/config-handler";
|
||||||
import { AbstractBindingUiHandler } from "#ui/abstract-binding-ui-handler";
|
import { AbstractBindingUiHandler } from "#ui/abstract-binding-ui-handler";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class GamepadBindingUiHandler extends AbstractBindingUiHandler {
|
export class GamepadBindingUiHandler extends AbstractBindingUiHandler {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Device } from "#enums/devices";
|
import { Device } from "#enums/devices";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { UiMode } from "#enums/ui-mode";
|
import type { UiMode } from "#enums/ui-mode";
|
||||||
import { getKeyWithKeycode } from "#inputs/config-handler";
|
import { getKeyWithKeycode } from "#inputs/config-handler";
|
||||||
import { AbstractBindingUiHandler } from "#ui/abstract-binding-ui-handler";
|
import { AbstractBindingUiHandler } from "#ui/abstract-binding-ui-handler";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
export class KeyboardBindingUiHandler extends AbstractBindingUiHandler {
|
export class KeyboardBindingUiHandler extends AbstractBindingUiHandler {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { Button } from "#enums/buttons";
|
import { Button } from "#enums/buttons";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { InputsIcons } from "#ui/abstract-control-settings-ui-handler";
|
import type { InputsIcons } from "#ui/abstract-control-settings-ui-handler";
|
||||||
import { addTextObject, setTextStyle, TextStyle } from "#ui/text";
|
import { addTextObject, setTextStyle } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { InterfaceConfig } from "#app/inputs-controller";
|
import type { InterfaceConfig } from "#app/inputs-controller";
|
||||||
import { Device } from "#enums/devices";
|
import { Device } from "#enums/devices";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import type { UiMode } from "#enums/ui-mode";
|
import type { UiMode } from "#enums/ui-mode";
|
||||||
import pad_dualshock from "#inputs/pad-dualshock";
|
import pad_dualshock from "#inputs/pad-dualshock";
|
||||||
import pad_unlicensedSNES from "#inputs/pad-unlicensed-snes";
|
import pad_unlicensedSNES from "#inputs/pad-unlicensed-snes";
|
||||||
@ -13,7 +14,7 @@ import {
|
|||||||
settingGamepadOptions,
|
settingGamepadOptions,
|
||||||
} from "#system/settings-gamepad";
|
} from "#system/settings-gamepad";
|
||||||
import { AbstractControlSettingsUiHandler } from "#ui/abstract-control-settings-ui-handler";
|
import { AbstractControlSettingsUiHandler } from "#ui/abstract-control-settings-ui-handler";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { truncateString } from "#utils/common";
|
import { truncateString } from "#utils/common";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { InterfaceConfig } from "#app/inputs-controller";
|
import type { InterfaceConfig } from "#app/inputs-controller";
|
||||||
import { Device } from "#enums/devices";
|
import { Device } from "#enums/devices";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import cfg_keyboard_qwerty from "#inputs/cfg-keyboard-qwerty";
|
import cfg_keyboard_qwerty from "#inputs/cfg-keyboard-qwerty";
|
||||||
import { deleteBind } from "#inputs/config-handler";
|
import { deleteBind } from "#inputs/config-handler";
|
||||||
@ -13,8 +14,9 @@ import {
|
|||||||
} from "#system/settings-keyboard";
|
} from "#system/settings-keyboard";
|
||||||
import { AbstractControlSettingsUiHandler } from "#ui/abstract-control-settings-ui-handler";
|
import { AbstractControlSettingsUiHandler } from "#ui/abstract-control-settings-ui-handler";
|
||||||
import { NavigationManager } from "#ui/navigation-menu";
|
import { NavigationManager } from "#ui/navigation-menu";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { addTextObject } from "#ui/text";
|
||||||
import { reverseValueToKeySetting, truncateString } from "#utils/common";
|
import { truncateString } from "#utils/common";
|
||||||
|
import { toPascalSnakeCase } from "#utils/strings";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -100,7 +102,7 @@ export class SettingsKeyboardUiHandler extends AbstractControlSettingsUiHandler
|
|||||||
}
|
}
|
||||||
const cursor = this.cursor + this.scrollCursor; // Calculate the absolute cursor position.
|
const cursor = this.cursor + this.scrollCursor; // Calculate the absolute cursor position.
|
||||||
const selection = this.settingLabels[cursor].text;
|
const selection = this.settingLabels[cursor].text;
|
||||||
const key = reverseValueToKeySetting(selection);
|
const key = toPascalSnakeCase(selection);
|
||||||
const settingName = SettingKeyboard[key];
|
const settingName = SettingKeyboard[key];
|
||||||
const activeConfig = this.getActiveConfig();
|
const activeConfig = this.getActiveConfig();
|
||||||
const success = deleteBind(this.getActiveConfig(), settingName);
|
const success = deleteBind(this.getActiveConfig(), settingName);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import type { PokemonSpecies } from "#data/pokemon-species";
|
import type { PokemonSpecies } from "#data/pokemon-species";
|
||||||
import { addTextObject, TextStyle } from "#ui/text";
|
import { TextStyle } from "#enums/text-style";
|
||||||
|
import { addTextObject } from "#ui/text";
|
||||||
|
|
||||||
export class StarterContainer extends Phaser.GameObjects.Container {
|
export class StarterContainer extends Phaser.GameObjects.Container {
|
||||||
public species: PokemonSpecies;
|
public species: PokemonSpecies;
|
||||||
|
@ -39,6 +39,7 @@ import type { Nature } from "#enums/nature";
|
|||||||
import { Passive as PassiveAttr } from "#enums/passive";
|
import { Passive as PassiveAttr } from "#enums/passive";
|
||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { CandyUpgradeNotificationChangedEvent } from "#events/battle-scene";
|
import type { CandyUpgradeNotificationChangedEvent } from "#events/battle-scene";
|
||||||
import { BattleSceneEventType } from "#events/battle-scene";
|
import { BattleSceneEventType } from "#events/battle-scene";
|
||||||
@ -57,7 +58,7 @@ import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/pokemon-icon-an
|
|||||||
import { ScrollBar } from "#ui/scroll-bar";
|
import { ScrollBar } from "#ui/scroll-bar";
|
||||||
import { StarterContainer } from "#ui/starter-container";
|
import { StarterContainer } from "#ui/starter-container";
|
||||||
import { StatsContainer } from "#ui/stats-container";
|
import { StatsContainer } from "#ui/stats-container";
|
||||||
import { addBBCodeTextObject, addTextObject, TextStyle } from "#ui/text";
|
import { addBBCodeTextObject, addTextObject } from "#ui/text";
|
||||||
import { addWindow } from "#ui/ui-theme";
|
import { addWindow } from "#ui/ui-theme";
|
||||||
import {
|
import {
|
||||||
BooleanHolder,
|
BooleanHolder,
|
||||||
@ -68,10 +69,10 @@ import {
|
|||||||
padInt,
|
padInt,
|
||||||
randIntRange,
|
randIntRange,
|
||||||
rgbHexToRgba,
|
rgbHexToRgba,
|
||||||
toReadableString,
|
|
||||||
} from "#utils/common";
|
} from "#utils/common";
|
||||||
import type { StarterPreferences } from "#utils/data";
|
import type { StarterPreferences } from "#utils/data";
|
||||||
import { loadStarterPreferences, saveStarterPreferences } from "#utils/data";
|
import { loadStarterPreferences, saveStarterPreferences } from "#utils/data";
|
||||||
|
import { toTitleCase } from "#utils/strings";
|
||||||
import { argbFromRgba } from "@material/material-color-utilities";
|
import { argbFromRgba } from "@material/material-color-utilities";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import type { GameObjects } from "phaser";
|
import type { GameObjects } from "phaser";
|
||||||
@ -1476,7 +1477,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
loop: -1,
|
loop: -1,
|
||||||
// Make the initial bounce a little randomly delayed
|
// Make the initial bounce a little randomly delayed
|
||||||
delay: randIntRange(0, 50) * 5,
|
delay: randIntRange(0, 50) * 5,
|
||||||
loopDelay: 1000,
|
loopDelay: fixedInt(1000),
|
||||||
tweens: [
|
tweens: [
|
||||||
{
|
{
|
||||||
targets: icon,
|
targets: icon,
|
||||||
@ -3526,7 +3527,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
|
|||||||
this.pokemonLuckLabelText.setVisible(this.pokemonLuckText.visible);
|
this.pokemonLuckLabelText.setVisible(this.pokemonLuckText.visible);
|
||||||
|
|
||||||
//Growth translate
|
//Growth translate
|
||||||
let growthReadable = toReadableString(GrowthRate[species.growthRate]);
|
let growthReadable = toTitleCase(GrowthRate[species.growthRate]);
|
||||||
const growthAux = growthReadable.replace(" ", "_");
|
const growthAux = growthReadable.replace(" ", "_");
|
||||||
if (i18next.exists("growth:" + growthAux)) {
|
if (i18next.exists("growth:" + growthAux)) {
|
||||||
growthReadable = i18next.t(("growth:" + growthAux) as any);
|
growthReadable = i18next.t(("growth:" + growthAux) as any);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { getStatKey, PERMANENT_STATS } from "#enums/stat";
|
import { getStatKey, PERMANENT_STATS } from "#enums/stat";
|
||||||
import { addBBCodeTextObject, addTextObject, getTextColor, TextStyle } from "#ui/text";
|
import { TextStyle } from "#enums/text-style";
|
||||||
|
import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import type BBCodeText from "phaser3-rex-plugins/plugins/gameobjects/tagtext/bbcodetext/BBCodeText";
|
import type BBCodeText from "phaser3-rex-plugins/plugins/gameobjects/tagtext/bbcodetext/BBCodeText";
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ import { PlayerGender } from "#enums/player-gender";
|
|||||||
import { PokemonType } from "#enums/pokemon-type";
|
import { PokemonType } from "#enums/pokemon-type";
|
||||||
import { getStatKey, PERMANENT_STATS, Stat } from "#enums/stat";
|
import { getStatKey, PERMANENT_STATS, Stat } from "#enums/stat";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
import { StatusEffect } from "#enums/status-effect";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiMode } from "#enums/ui-mode";
|
import { UiMode } from "#enums/ui-mode";
|
||||||
import type { PlayerPokemon } from "#field/pokemon";
|
import type { PlayerPokemon } from "#field/pokemon";
|
||||||
import { modifierSortFunc, PokemonHeldItemModifier } from "#modifiers/modifier";
|
import { modifierSortFunc, PokemonHeldItemModifier } from "#modifiers/modifier";
|
||||||
@ -24,7 +25,7 @@ import type { PokemonMove } from "#moves/pokemon-move";
|
|||||||
import type { Variant } from "#sprites/variant";
|
import type { Variant } from "#sprites/variant";
|
||||||
import { getVariantTint } from "#sprites/variant";
|
import { getVariantTint } from "#sprites/variant";
|
||||||
import { achvs } from "#system/achv";
|
import { achvs } from "#system/achv";
|
||||||
import { addBBCodeTextObject, addTextObject, getBBCodeFrag, TextStyle } from "#ui/text";
|
import { addBBCodeTextObject, addTextObject, getBBCodeFrag } from "#ui/text";
|
||||||
import { UiHandler } from "#ui/ui-handler";
|
import { UiHandler } from "#ui/ui-handler";
|
||||||
import {
|
import {
|
||||||
fixedInt,
|
fixedInt,
|
||||||
@ -34,9 +35,9 @@ import {
|
|||||||
isNullOrUndefined,
|
isNullOrUndefined,
|
||||||
padInt,
|
padInt,
|
||||||
rgbHexToRgba,
|
rgbHexToRgba,
|
||||||
toReadableString,
|
|
||||||
} from "#utils/common";
|
} from "#utils/common";
|
||||||
import { getEnumValues } from "#utils/enums";
|
import { getEnumValues } from "#utils/enums";
|
||||||
|
import { toTitleCase } from "#utils/strings";
|
||||||
import { argbFromRgba } from "@material/material-color-utilities";
|
import { argbFromRgba } from "@material/material-color-utilities";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
@ -354,18 +355,13 @@ export class SummaryUiHandler extends UiHandler {
|
|||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
console.error(`Failed to play animation for ${spriteKey}`, err);
|
console.error(`Failed to play animation for ${spriteKey}`, err);
|
||||||
}
|
}
|
||||||
this.pokemonSprite.setPipelineData("teraColor", getTypeRgb(this.pokemon.getTeraType()));
|
this.pokemonSprite
|
||||||
this.pokemonSprite.setPipelineData("isTerastallized", this.pokemon.isTerastallized);
|
.setPipelineData("teraColor", getTypeRgb(this.pokemon.getTeraType()))
|
||||||
this.pokemonSprite.setPipelineData("ignoreTimeTint", true);
|
.setPipelineData("isTerastallized", this.pokemon.isTerastallized)
|
||||||
this.pokemonSprite.setPipelineData("spriteKey", this.pokemon.getSpriteKey());
|
.setPipelineData("ignoreTimeTint", true)
|
||||||
this.pokemonSprite.setPipelineData(
|
.setPipelineData("spriteKey", this.pokemon.getSpriteKey())
|
||||||
"shiny",
|
.setPipelineData("shiny", this.pokemon.shiny)
|
||||||
this.pokemon.summonData.illusion?.basePokemon.shiny ?? this.pokemon.shiny,
|
.setPipelineData("variant", this.pokemon.variant);
|
||||||
);
|
|
||||||
this.pokemonSprite.setPipelineData(
|
|
||||||
"variant",
|
|
||||||
this.pokemon.summonData.illusion?.basePokemon.variant ?? this.pokemon.variant,
|
|
||||||
);
|
|
||||||
["spriteColors", "fusionSpriteColors"].map(k => {
|
["spriteColors", "fusionSpriteColors"].map(k => {
|
||||||
delete this.pokemonSprite.pipelineData[`${k}Base`];
|
delete this.pokemonSprite.pipelineData[`${k}Base`];
|
||||||
if (this.pokemon?.summonData.speciesForm) {
|
if (this.pokemon?.summonData.speciesForm) {
|
||||||
@ -463,9 +459,7 @@ export class SummaryUiHandler extends UiHandler {
|
|||||||
this.fusionShinyIcon.setPosition(this.shinyIcon.x, this.shinyIcon.y);
|
this.fusionShinyIcon.setPosition(this.shinyIcon.x, this.shinyIcon.y);
|
||||||
this.fusionShinyIcon.setVisible(doubleShiny);
|
this.fusionShinyIcon.setVisible(doubleShiny);
|
||||||
if (isFusion) {
|
if (isFusion) {
|
||||||
this.fusionShinyIcon.setTint(
|
this.fusionShinyIcon.setTint(getVariantTint(this.pokemon.fusionVariant));
|
||||||
getVariantTint(this.pokemon.summonData.illusion?.basePokemon.fusionVariant ?? this.pokemon.fusionVariant),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pokeball.setFrame(getPokeballAtlasKey(this.pokemon.pokeball));
|
this.pokeball.setFrame(getPokeballAtlasKey(this.pokemon.pokeball));
|
||||||
@ -810,24 +804,34 @@ export class SummaryUiHandler extends UiHandler {
|
|||||||
case Page.PROFILE: {
|
case Page.PROFILE: {
|
||||||
const profileContainer = globalScene.add.container(0, -pageBg.height);
|
const profileContainer = globalScene.add.container(0, -pageBg.height);
|
||||||
pageContainer.add(profileContainer);
|
pageContainer.add(profileContainer);
|
||||||
|
const otColor =
|
||||||
|
globalScene.gameData.gender === PlayerGender.FEMALE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE;
|
||||||
|
const usernameReplacement =
|
||||||
|
globalScene.gameData.gender === PlayerGender.FEMALE
|
||||||
|
? i18next.t("trainerNames:player_f")
|
||||||
|
: i18next.t("trainerNames:player_m");
|
||||||
|
|
||||||
// TODO: should add field for original trainer name to Pokemon object, to support gift/traded Pokemon from MEs
|
// TODO: should add field for original trainer name to Pokemon object, to support gift/traded Pokemon from MEs
|
||||||
const trainerText = addBBCodeTextObject(
|
const trainerText = addBBCodeTextObject(
|
||||||
7,
|
7,
|
||||||
12,
|
12,
|
||||||
`${i18next.t("pokemonSummary:ot")}/${getBBCodeFrag(loggedInUser?.username || i18next.t("pokemonSummary:unknown"), globalScene.gameData.gender === PlayerGender.FEMALE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE)}`,
|
`${i18next.t("pokemonSummary:ot")}/${getBBCodeFrag(
|
||||||
|
!globalScene.hideUsername
|
||||||
|
? loggedInUser?.username || i18next.t("pokemonSummary:unknown")
|
||||||
|
: usernameReplacement,
|
||||||
|
otColor,
|
||||||
|
)}`,
|
||||||
TextStyle.SUMMARY_ALT,
|
TextStyle.SUMMARY_ALT,
|
||||||
);
|
).setOrigin(0);
|
||||||
trainerText.setOrigin(0, 0);
|
|
||||||
profileContainer.add(trainerText);
|
profileContainer.add(trainerText);
|
||||||
|
|
||||||
|
const idToDisplay = globalScene.hideUsername ? "*****" : globalScene.gameData.trainerId.toString();
|
||||||
const trainerIdText = addTextObject(
|
const trainerIdText = addTextObject(
|
||||||
141,
|
141,
|
||||||
12,
|
12,
|
||||||
`${i18next.t("pokemonSummary:idNo")}${globalScene.gameData.trainerId.toString()}`,
|
`${i18next.t("pokemonSummary:idNo")}${idToDisplay}`,
|
||||||
TextStyle.SUMMARY_ALT,
|
TextStyle.SUMMARY_ALT,
|
||||||
);
|
).setOrigin(0);
|
||||||
trainerIdText.setOrigin(0, 0);
|
|
||||||
profileContainer.add(trainerIdText);
|
profileContainer.add(trainerIdText);
|
||||||
|
|
||||||
const typeLabel = addTextObject(7, 28, `${i18next.t("pokemonSummary:type")}/`, TextStyle.WINDOW_ALT);
|
const typeLabel = addTextObject(7, 28, `${i18next.t("pokemonSummary:type")}/`, TextStyle.WINDOW_ALT);
|
||||||
@ -958,8 +962,8 @@ export class SummaryUiHandler extends UiHandler {
|
|||||||
this.passiveContainer?.descriptionText?.setVisible(false);
|
this.passiveContainer?.descriptionText?.setVisible(false);
|
||||||
|
|
||||||
const closeFragment = getBBCodeFrag("", TextStyle.WINDOW_ALT);
|
const closeFragment = getBBCodeFrag("", TextStyle.WINDOW_ALT);
|
||||||
const rawNature = toReadableString(Nature[this.pokemon?.getNature()!]); // TODO: is this bang correct?
|
const rawNature = toTitleCase(Nature[this.pokemon?.getNature()!]); // TODO: is this bang correct?
|
||||||
const nature = `${getBBCodeFrag(toReadableString(getNatureName(this.pokemon?.getNature()!)), TextStyle.SUMMARY_RED)}${closeFragment}`; // TODO: is this bang correct?
|
const nature = `${getBBCodeFrag(toTitleCase(getNatureName(this.pokemon?.getNature()!)), TextStyle.SUMMARY_RED)}${closeFragment}`; // TODO: is this bang correct?
|
||||||
|
|
||||||
const memoString = i18next.t("pokemonSummary:memoString", {
|
const memoString = i18next.t("pokemonSummary:memoString", {
|
||||||
metFragment: i18next.t(
|
metFragment: i18next.t(
|
||||||
|
@ -1,79 +1,14 @@
|
|||||||
import { globalScene } from "#app/global-scene";
|
import { globalScene } from "#app/global-scene";
|
||||||
import { EggTier } from "#enums/egg-type";
|
import { EggTier } from "#enums/egg-type";
|
||||||
import { ModifierTier } from "#enums/modifier-tier";
|
import { ModifierTier } from "#enums/modifier-tier";
|
||||||
|
import { TextStyle } from "#enums/text-style";
|
||||||
import { UiTheme } from "#enums/ui-theme";
|
import { UiTheme } from "#enums/ui-theme";
|
||||||
import i18next from "#plugins/i18n";
|
import i18next from "#plugins/i18n";
|
||||||
|
import type { TextStyleOptions } from "#types/ui";
|
||||||
import type Phaser from "phaser";
|
import type Phaser from "phaser";
|
||||||
import BBCodeText from "phaser3-rex-plugins/plugins/gameobjects/tagtext/bbcodetext/BBCodeText";
|
import BBCodeText from "phaser3-rex-plugins/plugins/gameobjects/tagtext/bbcodetext/BBCodeText";
|
||||||
import type InputText from "phaser3-rex-plugins/plugins/inputtext";
|
import type InputText from "phaser3-rex-plugins/plugins/inputtext";
|
||||||
|
|
||||||
export enum TextStyle {
|
|
||||||
MESSAGE,
|
|
||||||
WINDOW,
|
|
||||||
WINDOW_ALT,
|
|
||||||
WINDOW_BATTLE_COMMAND,
|
|
||||||
BATTLE_INFO,
|
|
||||||
PARTY,
|
|
||||||
PARTY_RED,
|
|
||||||
PARTY_CANCEL_BUTTON,
|
|
||||||
INSTRUCTIONS_TEXT,
|
|
||||||
MOVE_LABEL,
|
|
||||||
SUMMARY,
|
|
||||||
SUMMARY_DEX_NUM,
|
|
||||||
SUMMARY_DEX_NUM_GOLD,
|
|
||||||
SUMMARY_ALT,
|
|
||||||
SUMMARY_HEADER,
|
|
||||||
SUMMARY_RED,
|
|
||||||
SUMMARY_BLUE,
|
|
||||||
SUMMARY_PINK,
|
|
||||||
SUMMARY_GOLD,
|
|
||||||
SUMMARY_GRAY,
|
|
||||||
SUMMARY_GREEN,
|
|
||||||
SUMMARY_STATS,
|
|
||||||
SUMMARY_STATS_BLUE,
|
|
||||||
SUMMARY_STATS_PINK,
|
|
||||||
SUMMARY_STATS_GOLD,
|
|
||||||
LUCK_VALUE,
|
|
||||||
STATS_HEXAGON,
|
|
||||||
GROWTH_RATE_TYPE,
|
|
||||||
MONEY, // Money default styling (pale yellow)
|
|
||||||
MONEY_WINDOW, // Money displayed in Windows (needs different colors based on theme)
|
|
||||||
HEADER_LABEL,
|
|
||||||
STATS_LABEL,
|
|
||||||
STATS_VALUE,
|
|
||||||
SETTINGS_VALUE,
|
|
||||||
SETTINGS_LABEL,
|
|
||||||
SETTINGS_LABEL_NAVBAR,
|
|
||||||
SETTINGS_SELECTED,
|
|
||||||
SETTINGS_LOCKED,
|
|
||||||
EGG_LIST,
|
|
||||||
EGG_SUMMARY_NAME,
|
|
||||||
EGG_SUMMARY_DEX,
|
|
||||||
STARTER_VALUE_LIMIT,
|
|
||||||
TOOLTIP_TITLE,
|
|
||||||
TOOLTIP_CONTENT,
|
|
||||||
FILTER_BAR_MAIN,
|
|
||||||
MOVE_INFO_CONTENT,
|
|
||||||
MOVE_PP_FULL,
|
|
||||||
MOVE_PP_HALF_FULL,
|
|
||||||
MOVE_PP_NEAR_EMPTY,
|
|
||||||
MOVE_PP_EMPTY,
|
|
||||||
SMALLER_WINDOW_ALT,
|
|
||||||
BGM_BAR,
|
|
||||||
PERFECT_IV,
|
|
||||||
ME_OPTION_DEFAULT, // Default style for choices in ME
|
|
||||||
ME_OPTION_SPECIAL, // Style for choices with special requirements in ME
|
|
||||||
SHADOW_TEXT, // To obscure unavailable options
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TextStyleOptions {
|
|
||||||
scale: number;
|
|
||||||
styleOptions: Phaser.Types.GameObjects.Text.TextStyle | InputText.IConfig;
|
|
||||||
shadowColor: string;
|
|
||||||
shadowXpos: number;
|
|
||||||
shadowYpos: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function addTextObject(
|
export function addTextObject(
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
@ -87,9 +22,10 @@ export function addTextObject(
|
|||||||
extraStyleOptions,
|
extraStyleOptions,
|
||||||
);
|
);
|
||||||
|
|
||||||
const ret = globalScene.add.text(x, y, content, styleOptions);
|
const ret = globalScene.add
|
||||||
ret.setScale(scale);
|
.text(x, y, content, styleOptions)
|
||||||
ret.setShadow(shadowXpos, shadowYpos, shadowColor);
|
.setScale(scale)
|
||||||
|
.setShadow(shadowXpos, shadowYpos, shadowColor);
|
||||||
if (!(styleOptions as Phaser.Types.GameObjects.Text.TextStyle).lineSpacing) {
|
if (!(styleOptions as Phaser.Types.GameObjects.Text.TextStyle).lineSpacing) {
|
||||||
ret.setLineSpacing(scale * 30);
|
ret.setLineSpacing(scale * 30);
|
||||||
}
|
}
|
||||||
@ -107,8 +43,7 @@ export function setTextStyle(
|
|||||||
globalScene.uiTheme,
|
globalScene.uiTheme,
|
||||||
extraStyleOptions,
|
extraStyleOptions,
|
||||||
);
|
);
|
||||||
obj.setScale(scale);
|
obj.setScale(scale).setShadow(shadowXpos, shadowYpos, shadowColor);
|
||||||
obj.setShadow(shadowXpos, shadowYpos, shadowColor);
|
|
||||||
if (!(styleOptions as Phaser.Types.GameObjects.Text.TextStyle).lineSpacing) {
|
if (!(styleOptions as Phaser.Types.GameObjects.Text.TextStyle).lineSpacing) {
|
||||||
obj.setLineSpacing(scale * 30);
|
obj.setLineSpacing(scale * 30);
|
||||||
}
|
}
|
||||||
@ -133,8 +68,7 @@ export function addBBCodeTextObject(
|
|||||||
|
|
||||||
const ret = new BBCodeText(globalScene, x, y, content, styleOptions as BBCodeText.TextStyle);
|
const ret = new BBCodeText(globalScene, x, y, content, styleOptions as BBCodeText.TextStyle);
|
||||||
globalScene.add.existing(ret);
|
globalScene.add.existing(ret);
|
||||||
ret.setScale(scale);
|
ret.setScale(scale).setShadow(shadowXpos, shadowYpos, shadowColor);
|
||||||
ret.setShadow(shadowXpos, shadowYpos, shadowColor);
|
|
||||||
if (!(styleOptions as BBCodeText.TextStyle).lineSpacing) {
|
if (!(styleOptions as BBCodeText.TextStyle).lineSpacing) {
|
||||||
ret.setLineSpacing(scale * 60);
|
ret.setLineSpacing(scale * 60);
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user