Merge branch 'beta' into enemy_ai

This commit is contained in:
damocleas 2025-06-14 17:40:44 -04:00 committed by GitHub
commit ba8126c86d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 139 additions and 155 deletions

View File

@ -47,8 +47,8 @@
"correctness": { "correctness": {
"noUndeclaredVariables": "off", "noUndeclaredVariables": "off",
"noUnusedVariables": "error", "noUnusedVariables": "error",
"noSwitchDeclarations": "warn", // TODO: refactor and make this an error "noSwitchDeclarations": "error",
"noVoidTypeReturn": "warn", // TODO: Refactor and make this an error "noVoidTypeReturn": "error",
"noUnusedImports": "error" "noUnusedImports": "error"
}, },
"style": { "style": {
@ -85,7 +85,7 @@
"useLiteralKeys": "off", "useLiteralKeys": "off",
"noForEach": "off", // Foreach vs for of is not that simple. "noForEach": "off", // Foreach vs for of is not that simple.
"noUselessSwitchCase": "off", // Explicit > Implicit "noUselessSwitchCase": "off", // Explicit > Implicit
"noUselessConstructor": "warn", // TODO: Refactor and make this an error "noUselessConstructor": "error",
"noBannedTypes": "warn" // TODO: Refactor and make this an error "noBannedTypes": "warn" // TODO: Refactor and make this an error
}, },
"nursery": { "nursery": {

View File

@ -18,7 +18,7 @@
"eslint": "eslint --fix .", "eslint": "eslint --fix .",
"eslint-ci": "eslint .", "eslint-ci": "eslint .",
"biome": "biome check --write --changed --no-errors-on-unmatched", "biome": "biome check --write --changed --no-errors-on-unmatched",
"biome-ci": "biome ci --diagnostic-level=error --reporter=github --changed --no-errors-on-unmatched", "biome-ci": "biome ci --diagnostic-level=error --reporter=github --no-errors-on-unmatched",
"docs": "typedoc", "docs": "typedoc",
"depcruise": "depcruise src", "depcruise": "depcruise src",
"depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg", "depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg",

View File

@ -29,4 +29,4 @@ export type ModifierString = keyof ModifierConstructorMap;
export type ModifierPool = { export type ModifierPool = {
[tier: string]: WeightedModifierType[]; [tier: string]: WeightedModifierType[];
} };

View File

@ -125,16 +125,6 @@ export interface TerrainBattlerTag {
* Players and enemies should not be allowed to select restricted moves. * Players and enemies should not be allowed to select restricted moves.
*/ */
export abstract class MoveRestrictionBattlerTag extends BattlerTag { export abstract class MoveRestrictionBattlerTag extends BattlerTag {
constructor(
tagType: BattlerTagType,
lapseType: BattlerTagLapseType | BattlerTagLapseType[],
turnCount: number,
sourceMove?: MoveId,
sourceId?: number,
) {
super(tagType, lapseType, turnCount, sourceMove, sourceId);
}
/** @override */ /** @override */
override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
if (lapseType === BattlerTagLapseType.PRE_MOVE) { if (lapseType === BattlerTagLapseType.PRE_MOVE) {
@ -1470,16 +1460,6 @@ export class WrapTag extends DamagingTrapTag {
} }
export abstract class VortexTrapTag extends DamagingTrapTag { export abstract class VortexTrapTag extends DamagingTrapTag {
constructor(
tagType: BattlerTagType,
commonAnim: CommonAnim,
turnCount: number,
sourceMove: MoveId,
sourceId: number,
) {
super(tagType, commonAnim, turnCount, sourceMove, sourceId);
}
getTrapMessage(pokemon: Pokemon): string { getTrapMessage(pokemon: Pokemon): string {
return i18next.t("battlerTags:vortexOnTrap", { return i18next.t("battlerTags:vortexOnTrap", {
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),

View File

@ -11,10 +11,7 @@ import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requir
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import { ModifierTier } from "#enums/modifier-tier"; import { ModifierTier } from "#enums/modifier-tier";
import type { ModifierTypeOption } from "#app/modifier/modifier-type"; import type { ModifierTypeOption } from "#app/modifier/modifier-type";
import { import { getPlayerModifierTypeOptions, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
getPlayerModifierTypeOptions,
regenerateModifierPoolThresholds,
} from "#app/modifier/modifier-type";
import { ModifierPoolType } from "#enums/modifier-pool-type"; import { ModifierPoolType } from "#enums/modifier-pool-type";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";

View File

@ -7,10 +7,7 @@ import { TrainerSlot } from "#enums/trainer-slot";
import { ModifierTier } from "#enums/modifier-tier"; import { ModifierTier } from "#enums/modifier-tier";
import { MusicPreference } from "#app/system/settings/settings"; import { MusicPreference } from "#app/system/settings/settings";
import type { ModifierTypeOption } from "#app/modifier/modifier-type"; import type { ModifierTypeOption } from "#app/modifier/modifier-type";
import { import { getPlayerModifierTypeOptions, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
getPlayerModifierTypeOptions,
regenerateModifierPoolThresholds,
} from "#app/modifier/modifier-type";
import { ModifierPoolType } from "#enums/modifier-pool-type"; import { ModifierPoolType } from "#enums/modifier-pool-type";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";

View File

@ -1,13 +0,0 @@
// biome-ignore lint/correctness/noUnusedImports: Used in tsdoc
import type ConfirmUiHandler from "#app/ui/confirm-ui-handler";
/**
* Used by {@linkcode ConfirmUiHandler} to determine whether the cursor should start on Yes or No
*/
export const ConfirmUiMode = Object.freeze({
/** Start cursor on Yes */
DEFAULT_YES: 1,
/** Start cursor on No */
DEFAULT_NO: 2
});
export type ConfirmUiMode = typeof ConfirmUiMode[keyof typeof ConfirmUiMode];

View File

@ -262,7 +262,7 @@ export class Arena {
return 5; return 5;
} }
break; break;
case SpeciesId.LYCANROC: case SpeciesId.LYCANROC: {
const timeOfDay = this.getTimeOfDay(); const timeOfDay = this.getTimeOfDay();
switch (timeOfDay) { switch (timeOfDay) {
case TimeOfDay.DAY: case TimeOfDay.DAY:
@ -275,6 +275,7 @@ export class Arena {
} }
break; break;
} }
}
return 0; return 0;
} }

View File

@ -4410,14 +4410,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
// biome-ignore lint: there are a ton of issues.. // biome-ignore lint: there are a ton of issues..
faintCry(callback: Function): void { faintCry(callback: Function): void {
if (this.fusionSpecies && this.getSpeciesForm() !== this.getFusionSpeciesForm()) { if (this.fusionSpecies && this.getSpeciesForm() !== this.getFusionSpeciesForm()) {
return this.fusionFaintCry(callback); this.fusionFaintCry(callback);
return;
} }
const key = this.species.getCryKey(this.formIndex); const key = this.species.getCryKey(this.formIndex);
let rate = 0.85; let rate = 0.85;
const cry = globalScene.playSound(key, { rate: rate }) as AnySound; const cry = globalScene.playSound(key, { rate: rate }) as AnySound;
if (!cry || globalScene.fieldVolume === 0) { if (!cry || globalScene.fieldVolume === 0) {
return callback(); callback();
return;
} }
const sprite = this.getSprite(); const sprite = this.getSprite();
const tintSprite = this.getTintSprite(); const tintSprite = this.getTintSprite();
@ -4485,7 +4487,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
rate: rate, rate: rate,
}) as AnySound; }) as AnySound;
if (!cry || !fusionCry || globalScene.fieldVolume === 0) { if (!cry || !fusionCry || globalScene.fieldVolume === 0) {
return callback(); callback();
return;
} }
fusionCry.stop(); fusionCry.stop();
duration = Math.min(duration, fusionCry.totalDuration * 1000); duration = Math.min(duration, fusionCry.totalDuration * 1000);

View File

@ -2393,8 +2393,6 @@ export interface ModifierPool {
[tier: string]: WeightedModifierType[]; [tier: string]: WeightedModifierType[];
} }
const modifierPool: ModifierPool = {};
let modifierPoolThresholds = {}; let modifierPoolThresholds = {};
let ignoredPoolIndexes = {}; let ignoredPoolIndexes = {};
@ -2859,7 +2857,7 @@ function getNewModifierTypeOption(
} }
tier += upgradeCount; tier += upgradeCount;
while (tier && (!modifierPool.hasOwnProperty(tier) || !modifierPool[tier].length)) { while (tier && (!pool.hasOwnProperty(tier) || !pool[tier].length)) {
tier--; tier--;
if (upgradeCount) { if (upgradeCount) {
upgradeCount--; upgradeCount--;
@ -2870,7 +2868,7 @@ function getNewModifierTypeOption(
if (tier < ModifierTier.MASTER && allowLuckUpgrades) { if (tier < ModifierTier.MASTER && allowLuckUpgrades) {
const partyLuckValue = getPartyLuckValue(party); const partyLuckValue = getPartyLuckValue(party);
const upgradeOdds = Math.floor(128 / ((partyLuckValue + 4) / 4)); const upgradeOdds = Math.floor(128 / ((partyLuckValue + 4) / 4));
while (modifierPool.hasOwnProperty(tier + upgradeCount + 1) && modifierPool[tier + upgradeCount + 1].length) { while (pool.hasOwnProperty(tier + upgradeCount + 1) && pool[tier + upgradeCount + 1].length) {
if (randSeedInt(upgradeOdds) < 4) { if (randSeedInt(upgradeOdds) < 4) {
upgradeCount++; upgradeCount++;
} else { } else {
@ -2920,6 +2918,7 @@ function getNewModifierTypeOption(
} }
export function getDefaultModifierTypeForTier(tier: ModifierTier): ModifierType { export function getDefaultModifierTypeForTier(tier: ModifierTier): ModifierType {
const modifierPool = getModifierPoolForType(ModifierPoolType.PLAYER);
let modifierType: ModifierType | WeightedModifierType = modifierPool[tier || ModifierTier.COMMON][0]; let modifierType: ModifierType | WeightedModifierType = modifierPool[tier || ModifierTier.COMMON][0];
if (modifierType instanceof WeightedModifierType) { if (modifierType instanceof WeightedModifierType) {
modifierType = (modifierType as WeightedModifierType).modifierType; modifierType = (modifierType as WeightedModifierType).modifierType;

View File

@ -1,8 +1,5 @@
import { ModifierTier } from "#enums/modifier-tier"; import { ModifierTier } from "#enums/modifier-tier";
import { import { regenerateModifierPoolThresholds, getEnemyBuffModifierForWave } from "#app/modifier/modifier-type";
regenerateModifierPoolThresholds,
getEnemyBuffModifierForWave,
} from "#app/modifier/modifier-type";
import { ModifierPoolType } from "#enums/modifier-pool-type"; import { ModifierPoolType } from "#enums/modifier-pool-type";
import { EnemyPersistentModifier } from "#app/modifier/modifier"; import { EnemyPersistentModifier } from "#app/modifier/modifier";
import { Phase } from "#app/phase"; import { Phase } from "#app/phase";

View File

@ -149,7 +149,7 @@ export class CommandPhase extends FieldPhase {
switch (command) { switch (command) {
case Command.TERA: case Command.TERA:
case Command.FIGHT: case Command.FIGHT: {
let useStruggle = false; let useStruggle = false;
const turnMove: TurnMove | undefined = args.length === 2 ? (args[1] as TurnMove) : undefined; const turnMove: TurnMove | undefined = args.length === 2 ? (args[1] as TurnMove) : undefined;
if ( if (
@ -233,7 +233,8 @@ export class CommandPhase extends FieldPhase {
); );
} }
break; break;
case Command.BALL: }
case Command.BALL: {
const notInDex = const notInDex =
globalScene globalScene
.getEnemyField() .getEnemyField()
@ -337,8 +338,9 @@ export class CommandPhase extends FieldPhase {
} }
} }
break; break;
}
case Command.POKEMON: case Command.POKEMON:
case Command.RUN: case Command.RUN: {
const isSwitch = command === Command.POKEMON; const isSwitch = command === Command.POKEMON;
const { currentBattle, arena } = globalScene; const { currentBattle, arena } = globalScene;
const mysteryEncounterFleeAllowed = currentBattle.mysteryEncounter?.fleeAllowed; const mysteryEncounterFleeAllowed = currentBattle.mysteryEncounter?.fleeAllowed;
@ -446,6 +448,7 @@ export class CommandPhase extends FieldPhase {
} }
break; break;
} }
}
if (success) { if (success) {
this.end(); this.end();

View File

@ -12,7 +12,6 @@ import { UiMode } from "#enums/ui-mode";
import i18next from "i18next"; import i18next from "i18next";
import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase"; import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import { ConfirmUiMode } from "#enums/confirm-ui-mode";
import { LearnMoveType } from "#enums/learn-move-type"; import { LearnMoveType } from "#enums/learn-move-type";
export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
@ -164,10 +163,6 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
globalScene.ui.setMode(this.messageMode); globalScene.ui.setMode(this.messageMode);
this.replaceMoveCheck(move, pokemon); this.replaceMoveCheck(move, pokemon);
}, },
false,
0,
0,
ConfirmUiMode.DEFAULT_NO,
); );
} }

View File

@ -135,7 +135,8 @@ export class MovePhase extends BattlePhase {
this.showMoveText(); this.showMoveText();
this.showFailedText(); this.showFailedText();
} }
return this.end(); this.end();
return;
} }
this.pokemon.turnData.acted = true; this.pokemon.turnData.acted = true;
@ -310,7 +311,8 @@ export class MovePhase extends BattlePhase {
if (fail) { if (fail) {
this.showMoveText(); this.showMoveText();
this.showFailedText(); this.showFailedText();
return this.end(); this.end();
return;
} }
} }

View File

@ -53,7 +53,8 @@ export class PokemonAnimPhase extends BattlePhase {
private doSubstituteAddAnim(): void { private doSubstituteAddAnim(): void {
const substitute = this.pokemon.getTag(SubstituteTag); const substitute = this.pokemon.getTag(SubstituteTag);
if (isNullOrUndefined(substitute)) { if (isNullOrUndefined(substitute)) {
return this.end(); this.end();
return;
} }
const getSprite = () => { const getSprite = () => {
@ -116,12 +117,14 @@ export class PokemonAnimPhase extends BattlePhase {
private doSubstitutePreMoveAnim(): void { private doSubstitutePreMoveAnim(): void {
if (this.fieldAssets.length !== 1) { if (this.fieldAssets.length !== 1) {
return this.end(); this.end();
return;
} }
const subSprite = this.fieldAssets[0]; const subSprite = this.fieldAssets[0];
if (subSprite === undefined) { if (subSprite === undefined) {
return this.end(); this.end();
return;
} }
globalScene.tweens.add({ globalScene.tweens.add({
@ -145,12 +148,14 @@ export class PokemonAnimPhase extends BattlePhase {
private doSubstitutePostMoveAnim(): void { private doSubstitutePostMoveAnim(): void {
if (this.fieldAssets.length !== 1) { if (this.fieldAssets.length !== 1) {
return this.end(); this.end();
return;
} }
const subSprite = this.fieldAssets[0]; const subSprite = this.fieldAssets[0];
if (subSprite === undefined) { if (subSprite === undefined) {
return this.end(); this.end();
return;
} }
globalScene.tweens.add({ globalScene.tweens.add({
@ -174,12 +179,14 @@ export class PokemonAnimPhase extends BattlePhase {
private doSubstituteRemoveAnim(): void { private doSubstituteRemoveAnim(): void {
if (this.fieldAssets.length !== 1) { if (this.fieldAssets.length !== 1) {
return this.end(); this.end();
return;
} }
const subSprite = this.fieldAssets[0]; const subSprite = this.fieldAssets[0];
if (subSprite === undefined) { if (subSprite === undefined) {
return this.end(); this.end();
return;
} }
const getSprite = () => { const getSprite = () => {
@ -244,12 +251,14 @@ export class PokemonAnimPhase extends BattlePhase {
private doCommanderApplyAnim(): void { private doCommanderApplyAnim(): void {
if (!globalScene.currentBattle?.double) { if (!globalScene.currentBattle?.double) {
return this.end(); this.end();
return;
} }
const dondozo = this.pokemon.getAlly(); const dondozo = this.pokemon.getAlly();
if (dondozo?.species?.speciesId !== SpeciesId.DONDOZO) { if (dondozo?.species?.speciesId !== SpeciesId.DONDOZO) {
return this.end(); this.end();
return;
} }
const tatsugiriX = this.pokemon.x + this.pokemon.getSprite().x; const tatsugiriX = this.pokemon.x + this.pokemon.getSprite().x;
@ -329,7 +338,8 @@ export class PokemonAnimPhase extends BattlePhase {
const tatsugiri = this.pokemon.getAlly(); const tatsugiri = this.pokemon.getAlly();
if (isNullOrUndefined(tatsugiri)) { if (isNullOrUndefined(tatsugiri)) {
console.warn("Aborting COMMANDER_REMOVE anim: Tatsugiri is undefined"); console.warn("Aborting COMMANDER_REMOVE anim: Tatsugiri is undefined");
return this.end(); this.end();
return;
} }
const tatsuSprite = globalScene.addPokemonSprite( const tatsuSprite = globalScene.addPokemonSprite(

View File

@ -29,7 +29,8 @@ export class PokemonTransformPhase extends PokemonPhase {
const target = globalScene.getField(true).find(p => p.getBattlerIndex() === this.targetIndex); const target = globalScene.getField(true).find(p => p.getBattlerIndex() === this.targetIndex);
if (!target) { if (!target) {
return this.end(); this.end();
return;
} }
user.summonData.speciesForm = target.getSpeciesForm(); user.summonData.speciesForm = target.getSpeciesForm();

View File

@ -29,7 +29,8 @@ export class QuietFormChangePhase extends BattlePhase {
super.start(); super.start();
if (this.pokemon.formIndex === this.pokemon.species.forms.findIndex(f => f.formKey === this.formChange.formKey)) { if (this.pokemon.formIndex === this.pokemon.species.forms.findIndex(f => f.formKey === this.formChange.formKey)) {
return this.end(); this.end();
return;
} }
const preName = getPokemonNameWithAffix(this.pokemon); const preName = getPokemonNameWithAffix(this.pokemon);

View File

@ -174,7 +174,24 @@ export async function initI18n(): Promise<void> {
"es-MX": ["es-ES", "en"], "es-MX": ["es-ES", "en"],
default: ["en"], default: ["en"],
}, },
supportedLngs: ["en", "es-ES", "es-MX", "fr", "it", "de", "zh-CN", "zh-TW", "pt-BR", "ko", "ja", "ca", "da", "tr", "ro", "ru"], supportedLngs: [
"en",
"es-ES",
"es-MX",
"fr",
"it",
"de",
"zh-CN",
"zh-TW",
"pt-BR",
"ko",
"ja",
"ca",
"da",
"tr",
"ro",
"ru",
],
backend: { backend: {
loadPath(lng: string, [ns]: string[]) { loadPath(lng: string, [ns]: string[]) {
let fileName: string; let fileName: string;

View File

@ -32,7 +32,10 @@ const pressAction = i18next.t("settings:pressActionToAssign");
export const settingGamepadOptions = { export const settingGamepadOptions = {
[SettingGamepad.Controller]: [i18next.t("settings:controllerDefault"), i18next.t("settings:controllerChange")], [SettingGamepad.Controller]: [i18next.t("settings:controllerDefault"), i18next.t("settings:controllerChange")],
[SettingGamepad.Gamepad_Support]: [i18next.t("settings:gamepadSupportAuto"), i18next.t("settings:gamepadSupportDisabled")], [SettingGamepad.Gamepad_Support]: [
i18next.t("settings:gamepadSupportAuto"),
i18next.t("settings:gamepadSupportDisabled"),
],
[SettingGamepad.Button_Up]: [`KEY ${Button.UP.toString()}`, pressAction], [SettingGamepad.Button_Up]: [`KEY ${Button.UP.toString()}`, pressAction],
[SettingGamepad.Button_Down]: [`KEY ${Button.DOWN.toString()}`, pressAction], [SettingGamepad.Button_Down]: [`KEY ${Button.DOWN.toString()}`, pressAction],
[SettingGamepad.Button_Left]: [`KEY ${Button.LEFT.toString()}`, pressAction], [SettingGamepad.Button_Left]: [`KEY ${Button.LEFT.toString()}`, pressAction],

View File

@ -959,7 +959,7 @@ export function setSetting(setting: string, value: number): boolean {
}, },
{ {
label: "Türkçe (Needs Help)", label: "Türkçe (Needs Help)",
handler: () => changeLocaleHandler("tr") handler: () => changeLocaleHandler("tr"),
}, },
{ {
label: "Русский (Needs Help)", label: "Русский (Needs Help)",
@ -967,11 +967,11 @@ export function setSetting(setting: string, value: number): boolean {
}, },
{ {
label: "Dansk (Needs Help)", label: "Dansk (Needs Help)",
handler: () => changeLocaleHandler("da") handler: () => changeLocaleHandler("da"),
}, },
{ {
label: "Română (Needs Help)", label: "Română (Needs Help)",
handler: () => changeLocaleHandler("ro") handler: () => changeLocaleHandler("ro"),
}, },
{ {
label: i18next.t("settings:back"), label: i18next.t("settings:back"),

View File

@ -56,10 +56,6 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
protected defaultTextStyle: TextStyle = TextStyle.WINDOW; protected defaultTextStyle: TextStyle = TextStyle.WINDOW;
protected textContent: string; protected textContent: string;
constructor(mode: UiMode | null) {
super(mode);
}
abstract getWindowWidth(): number; abstract getWindowWidth(): number;
getWindowHeight(): number { getWindowHeight(): number {

View File

@ -69,7 +69,7 @@ export default class AdminUiHandler extends FormModalUiHandler {
case AdminMode.SEARCH: case AdminMode.SEARCH:
inputFieldConfigs.push({ label: "Username" }); inputFieldConfigs.push({ label: "Username" });
break; break;
case AdminMode.ADMIN: case AdminMode.ADMIN: {
const adminResult = this.adminResult ?? { const adminResult = this.adminResult ?? {
username: "", username: "",
discordId: "", discordId: "",
@ -91,6 +91,7 @@ export default class AdminUiHandler extends FormModalUiHandler {
inputFieldConfigs.push({ label: "Registered", isReadOnly: true }); inputFieldConfigs.push({ label: "Registered", isReadOnly: true });
break; break;
} }
}
return inputFieldConfigs; return inputFieldConfigs;
} }

View File

@ -4,11 +4,8 @@ import { UiMode } from "#enums/ui-mode";
import i18next from "i18next"; import i18next from "i18next";
import { Button } from "#enums/buttons"; import { Button } from "#enums/buttons";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { ConfirmUiMode } from "#enums/confirm-ui-mode";
export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler { export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler {
private confirmUiMode: ConfirmUiMode;
public static readonly windowWidth: number = 48; public static readonly windowWidth: number = 48;
private switchCheck: boolean; private switchCheck: boolean;
@ -108,16 +105,7 @@ export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler {
this.optionSelectContainer.setPosition(globalScene.game.canvas.width / 6 - 1 + xOffset, -48 + yOffset); this.optionSelectContainer.setPosition(globalScene.game.canvas.width / 6 - 1 + xOffset, -48 + yOffset);
this.confirmUiMode = args.length >= 6 ? (args[5] as ConfirmUiMode) : ConfirmUiMode.DEFAULT_YES;
switch (this.confirmUiMode) {
case ConfirmUiMode.DEFAULT_YES:
this.setCursor(this.switchCheck ? this.switchCheckCursor : 0); this.setCursor(this.switchCheck ? this.switchCheckCursor : 0);
break;
case ConfirmUiMode.DEFAULT_NO:
this.setCursor(this.switchCheck ? this.switchCheckCursor : 1);
break;
}
return true; return true;
} }

View File

@ -169,12 +169,13 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container {
entryContainer.add(scoreLabel); entryContainer.add(scoreLabel);
switch (this.category) { switch (this.category) {
case ScoreboardCategory.DAILY: case ScoreboardCategory.DAILY: {
const waveLabel = addTextObject(68, 0, wave, TextStyle.WINDOW, { const waveLabel = addTextObject(68, 0, wave, TextStyle.WINDOW, {
fontSize: "54px", fontSize: "54px",
}); });
entryContainer.add(waveLabel); entryContainer.add(waveLabel);
break; break;
}
case ScoreboardCategory.WEEKLY: case ScoreboardCategory.WEEKLY:
scoreLabel.x -= 16; scoreLabel.x -= 16;
break; break;

View File

@ -131,7 +131,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
gachaInfoContainer.add(gachaUpLabel); gachaInfoContainer.add(gachaUpLabel);
switch (gachaType as GachaType) { switch (gachaType as GachaType) {
case GachaType.LEGENDARY: case GachaType.LEGENDARY: {
if (["de", "es-ES"].includes(currentLanguage)) { if (["de", "es-ES"].includes(currentLanguage)) {
gachaUpLabel.setAlign("center"); gachaUpLabel.setAlign("center");
gachaUpLabel.setY(0); gachaUpLabel.setY(0);
@ -152,6 +152,7 @@ export default class EggGachaUiHandler extends MessageUiHandler {
gachaInfoContainer.add(pokemonIcon); gachaInfoContainer.add(pokemonIcon);
break; break;
}
case GachaType.MOVE: case GachaType.MOVE:
if (["de", "es-ES", "fr", "pt-BR", "ru"].includes(currentLanguage)) { if (["de", "es-ES", "fr", "pt-BR", "ru"].includes(currentLanguage)) {
gachaUpLabel.setAlign("center"); gachaUpLabel.setAlign("center");
@ -623,13 +624,14 @@ export default class EggGachaUiHandler extends MessageUiHandler {
updateGachaInfo(gachaType: GachaType): void { updateGachaInfo(gachaType: GachaType): void {
const infoContainer = this.gachaInfoContainers[gachaType]; const infoContainer = this.gachaInfoContainers[gachaType];
switch (gachaType as GachaType) { switch (gachaType as GachaType) {
case GachaType.LEGENDARY: case GachaType.LEGENDARY: {
const species = getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(new Date().getTime())); const species = getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(new Date().getTime()));
const pokemonIcon = infoContainer.getAt(1) as Phaser.GameObjects.Sprite; const pokemonIcon = infoContainer.getAt(1) as Phaser.GameObjects.Sprite;
pokemonIcon.setTexture(species.getIconAtlasKey(), species.getIconId(false)); pokemonIcon.setTexture(species.getIconAtlasKey(), species.getIconId(false));
break; break;
} }
} }
}
consumeVouchers(voucherType: VoucherType, count: number): void { consumeVouchers(voucherType: VoucherType, count: number): void {
globalScene.gameData.voucherCounts[voucherType] = Math.max( globalScene.gameData.voucherCounts[voucherType] = Math.max(

View File

@ -686,7 +686,7 @@ export default class MenuUiHandler extends MessageUiHandler {
error = true; error = true;
} }
break; break;
case MenuOptions.LOG_OUT: case MenuOptions.LOG_OUT: {
success = true; success = true;
const doLogout = () => { const doLogout = () => {
ui.setMode(UiMode.LOADING, { ui.setMode(UiMode.LOADING, {
@ -719,6 +719,7 @@ export default class MenuUiHandler extends MessageUiHandler {
} }
break; break;
} }
}
} else if (button === Button.CANCEL) { } else if (button === Button.CANCEL) {
success = true; success = true;
ui.revertMode().then(result => { ui.revertMode().then(result => {

View File

@ -1385,7 +1385,7 @@ export default class PartyUiHandler extends MessageUiHandler {
case PartyOption.MOVE_1: case PartyOption.MOVE_1:
case PartyOption.MOVE_2: case PartyOption.MOVE_2:
case PartyOption.MOVE_3: case PartyOption.MOVE_3:
case PartyOption.MOVE_4: case PartyOption.MOVE_4: {
const move = pokemon.moveset[option - PartyOption.MOVE_1]; const move = pokemon.moveset[option - PartyOption.MOVE_1];
if (this.showMovePp) { if (this.showMovePp) {
const maxPP = move.getMovePp(); const maxPP = move.getMovePp();
@ -1395,7 +1395,8 @@ export default class PartyUiHandler extends MessageUiHandler {
optionName = move.getName(); optionName = move.getName();
} }
break; break;
default: }
default: {
const formChangeItemModifiers = this.getFormChangeItemsModifiers(pokemon); const formChangeItemModifiers = this.getFormChangeItemsModifiers(pokemon);
if (formChangeItemModifiers && option >= PartyOption.FORM_CHANGE_ITEM) { if (formChangeItemModifiers && option >= PartyOption.FORM_CHANGE_ITEM) {
const modifier = formChangeItemModifiers[option - PartyOption.FORM_CHANGE_ITEM]; const modifier = formChangeItemModifiers[option - PartyOption.FORM_CHANGE_ITEM];
@ -1411,6 +1412,7 @@ export default class PartyUiHandler extends MessageUiHandler {
} }
break; break;
} }
}
} else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER) { } else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER) {
const learnableLevelMoves = pokemon.getLearnableLevelMoves(); const learnableLevelMoves = pokemon.getLearnableLevelMoves();
const move = learnableLevelMoves[option]; const move = learnableLevelMoves[option];

View File

@ -567,7 +567,7 @@ export default class RunInfoUiHandler extends UiHandler {
case GameModes.SPLICED_ENDLESS: case GameModes.SPLICED_ENDLESS:
modeText.appendText(`${i18next.t("gameMode:endlessSpliced")}`, false); modeText.appendText(`${i18next.t("gameMode:endlessSpliced")}`, false);
break; break;
case GameModes.CHALLENGE: case GameModes.CHALLENGE: {
modeText.appendText(`${i18next.t("gameMode:challenge")}`, false); modeText.appendText(`${i18next.t("gameMode:challenge")}`, false);
modeText.appendText(`${i18next.t("runHistory:challengeRules")}: `); modeText.appendText(`${i18next.t("runHistory:challengeRules")}: `);
modeText.setWrapMode(1); // wrap by word modeText.setWrapMode(1); // wrap by word
@ -582,6 +582,7 @@ export default class RunInfoUiHandler extends UiHandler {
} }
} }
break; break;
}
case GameModes.ENDLESS: case GameModes.ENDLESS:
modeText.appendText(`${i18next.t("gameMode:endless")}`, false); modeText.appendText(`${i18next.t("gameMode:endless")}`, false);
break; break;
@ -687,7 +688,7 @@ export default class RunInfoUiHandler extends UiHandler {
case Challenges.SINGLE_GENERATION: case Challenges.SINGLE_GENERATION:
rules.push(i18next.t(`runHistory:challengeMonoGen${this.runInfo.challenges[i].value}`)); rules.push(i18next.t(`runHistory:challengeMonoGen${this.runInfo.challenges[i].value}`));
break; break;
case Challenges.SINGLE_TYPE: case Challenges.SINGLE_TYPE: {
const typeRule = PokemonType[this.runInfo.challenges[i].value - 1]; const typeRule = PokemonType[this.runInfo.challenges[i].value - 1];
const typeTextColor = `[color=${TypeColor[typeRule]}]`; const typeTextColor = `[color=${TypeColor[typeRule]}]`;
const typeShadowColor = `[shadow=${TypeShadow[typeRule]}]`; const typeShadowColor = `[shadow=${TypeShadow[typeRule]}]`;
@ -695,10 +696,11 @@ export default class RunInfoUiHandler extends UiHandler {
typeTextColor + typeShadowColor + i18next.t(`pokemonInfo:Type.${typeRule}`)! + "[/color]" + "[/shadow]"; typeTextColor + typeShadowColor + i18next.t(`pokemonInfo:Type.${typeRule}`)! + "[/color]" + "[/shadow]";
rules.push(typeText); rules.push(typeText);
break; break;
}
case Challenges.INVERSE_BATTLE: case Challenges.INVERSE_BATTLE:
rules.push(i18next.t("challenges:inverseBattle.shortName")); rules.push(i18next.t("challenges:inverseBattle.shortName"));
break; break;
default: default: {
const localisationKey = Challenges[this.runInfo.challenges[i].id] const localisationKey = Challenges[this.runInfo.challenges[i].id]
.split("_") .split("_")
.map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase())) .map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()))
@ -708,6 +710,7 @@ export default class RunInfoUiHandler extends UiHandler {
} }
} }
} }
}
return rules; return rules;
} }

View File

@ -126,6 +126,11 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler
); );
this.actionsBg.setOrigin(0, 0); this.actionsBg.setOrigin(0, 0);
/*
* If there isn't enough space to fit all the icons and texts, there will be an overlap
* This currently doesn't happen, but it's something to keep in mind.
*/
const iconAction = globalScene.add.sprite(0, 0, "keyboard"); const iconAction = globalScene.add.sprite(0, 0, "keyboard");
iconAction.setOrigin(0, -0.1); iconAction.setOrigin(0, -0.1);
iconAction.setPositionRelative(this.actionsBg, this.navigationContainer.width - 32, 4); iconAction.setPositionRelative(this.actionsBg, this.navigationContainer.width - 32, 4);
@ -137,7 +142,7 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler
const iconCancel = globalScene.add.sprite(0, 0, "keyboard"); const iconCancel = globalScene.add.sprite(0, 0, "keyboard");
iconCancel.setOrigin(0, -0.1); iconCancel.setOrigin(0, -0.1);
iconCancel.setPositionRelative(this.actionsBg, this.navigationContainer.width - 100, 4); iconCancel.setPositionRelative(this.actionsBg, actionText.x - 28, 4);
this.navigationIcons["BUTTON_CANCEL"] = iconCancel; this.navigationIcons["BUTTON_CANCEL"] = iconCancel;
const cancelText = addTextObject(0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL); const cancelText = addTextObject(0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL);
@ -146,7 +151,7 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler
const iconReset = globalScene.add.sprite(0, 0, "keyboard"); const iconReset = globalScene.add.sprite(0, 0, "keyboard");
iconReset.setOrigin(0, -0.1); iconReset.setOrigin(0, -0.1);
iconReset.setPositionRelative(this.actionsBg, this.navigationContainer.width - 180, 4); iconReset.setPositionRelative(this.actionsBg, cancelText.x - 28, 4);
this.navigationIcons["BUTTON_HOME"] = iconReset; this.navigationIcons["BUTTON_HOME"] = iconReset;
const resetText = addTextObject(0, 0, i18next.t("settings:reset"), TextStyle.SETTINGS_LABEL); const resetText = addTextObject(0, 0, i18next.t("settings:reset"), TextStyle.SETTINGS_LABEL);

View File

@ -94,7 +94,7 @@ export default class AbstractSettingsUiHandler extends MessageUiHandler {
const iconCancel = globalScene.add.sprite(0, 0, "keyboard"); const iconCancel = globalScene.add.sprite(0, 0, "keyboard");
iconCancel.setOrigin(0, -0.1); iconCancel.setOrigin(0, -0.1);
iconCancel.setPositionRelative(actionsBg, this.navigationContainer.width - 100, 4); iconCancel.setPositionRelative(actionsBg, actionText.x - 28, 4);
this.navigationIcons["BUTTON_CANCEL"] = iconCancel; this.navigationIcons["BUTTON_CANCEL"] = iconCancel;
const cancelText = addTextObject(0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL); const cancelText = addTextObject(0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL);
@ -332,7 +332,7 @@ export default class AbstractSettingsUiHandler extends MessageUiHandler {
case Button.CYCLE_SHINY: case Button.CYCLE_SHINY:
success = this.navigationContainer.navigate(button); success = this.navigationContainer.navigate(button);
break; break;
case Button.ACTION: case Button.ACTION: {
const setting: Setting = this.settings[cursor]; const setting: Setting = this.settings[cursor];
if (setting?.activatable) { if (setting?.activatable) {
success = this.activateSetting(setting); success = this.activateSetting(setting);
@ -340,6 +340,7 @@ export default class AbstractSettingsUiHandler extends MessageUiHandler {
break; break;
} }
} }
}
// Plays a select sound effect if an action was successfully processed. // Plays a select sound effect if an action was successfully processed.
if (success) { if (success) {

View File

@ -1763,7 +1763,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
} }
} else if (this.randomCursorObj.visible) { } else if (this.randomCursorObj.visible) {
switch (button) { switch (button) {
case Button.ACTION: case Button.ACTION: {
if (this.starterSpecies.length >= 6) { if (this.starterSpecies.length >= 6) {
error = true; error = true;
break; break;
@ -1815,6 +1815,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
} }
}); });
break; break;
}
case Button.UP: case Button.UP:
this.randomCursorObj.setVisible(false); this.randomCursorObj.setVisible(false);
this.filterBarCursor = this.filterBar.numFilters - 1; this.filterBarCursor = this.filterBar.numFilters - 1;

View File

@ -10,10 +10,6 @@ import { UiMode } from "#enums/ui-mode";
export default class TestDialogueUiHandler extends FormModalUiHandler { export default class TestDialogueUiHandler extends FormModalUiHandler {
keys: string[]; keys: string[];
constructor(mode) {
super(mode);
}
setup() { setup() {
super.setup(); super.setup();

View File

@ -164,15 +164,13 @@ describe("Moves - Last Respects", () => {
await game.toNextWave(); await game.toNextWave();
expect(game.scene.currentBattle.enemyFaints).toBe(0); expect(game.scene.currentBattle.enemyFaints).toBe(0);
game.removeEnemyHeldItems();
game.move.select(MoveId.LAST_RESPECTS); game.move.select(MoveId.LAST_RESPECTS);
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.phaseInterceptor.to("MoveEndPhase"); await game.phaseInterceptor.to("MoveEndPhase");
const enemy = game.field.getEnemyPokemon(); expect(move.calculateBattlePower).toHaveLastReturnedWith(50);
const player = game.field.getPlayerPokemon();
const items = `Player items: ${player.getHeldItems()} | Enemy Items: ${enemy.getHeldItems()} |`;
expect(move.calculateBattlePower, items).toHaveLastReturnedWith(50);
}); });
it("should reset playerFaints count if we enter new trainer battle", async () => { it("should reset playerFaints count if we enter new trainer battle", async () => {

View File

@ -92,10 +92,6 @@ describe("Learn Move Phase", () => {
game.onNextPrompt("LearnMovePhase", UiMode.CONFIRM, () => { game.onNextPrompt("LearnMovePhase", UiMode.CONFIRM, () => {
game.scene.ui.processInput(Button.ACTION); game.scene.ui.processInput(Button.ACTION);
}); });
game.onNextPrompt("LearnMovePhase", UiMode.CONFIRM, () => {
game.scene.ui.setCursor(0);
game.scene.ui.processInput(Button.ACTION);
});
await game.phaseInterceptor.to(LearnMovePhase); await game.phaseInterceptor.to(LearnMovePhase);
const levelReq = bulbasaur.getLevelMoves(5)[0][0]; const levelReq = bulbasaur.getLevelMoves(5)[0][0];