[Dev] Add more Biome rules (#6604)

* Added `noBannedTypes` as a biome rule

* Added `useShorthandAssign` rule

* Added `useConsistentArrayType`

* Update src/field/pokemon.ts

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* Update src/data/pokeball.ts

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>

* Apply Biome after merge

---------

Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
This commit is contained in:
Bertie690 2025-11-01 23:38:04 -04:00 committed by GitHub
parent b2089012c1
commit d3088c1729
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
44 changed files with 162 additions and 125 deletions

View File

@ -116,7 +116,17 @@
},
"useCollapsedIf": "error",
"useCollapsedElseIf": "error",
"useDeprecatedReason": "error",
"useConsistentArrayType": {
"level": "error",
"fix": "safe",
"options": {}
},
"useShorthandAssign": {
"level": "error",
"fix": "safe",
"options": {}
},
"noSubstr": "error",
"noYodaExpression": "error",
"useForOf": "error",
@ -205,7 +215,7 @@
"noForEach": "off", // Foreach vs for of is not that simple.
"noUselessSwitchCase": "off", // Explicit > Implicit
"noUselessConstructor": "error",
"noBannedTypes": "warn", // TODO: Refactor and make this an error
"noBannedTypes": "error",
"noThisInStatic": "error",
"noUselessThisAlias": "error",
"noUselessTernary": "error",

View File

@ -3625,9 +3625,9 @@ export class BattleScene extends SceneBase {
// biome-ignore format: biome sucks at formatting this line
for (const seenEncounterData of this.mysteryEncounterSaveData.encounteredEvents) {
if (seenEncounterData.tier === MysteryEncounterTier.COMMON) {
tierWeights[0] = tierWeights[0] - 6;
tierWeights[0] -= 6;
} else if (seenEncounterData.tier === MysteryEncounterTier.GREAT) {
tierWeights[1] = tierWeights[1] - 4;
tierWeights[1] -= 4;
}
}

View File

@ -821,7 +821,7 @@ export abstract class BattleAnim {
frame.target === AnimFrameTarget.GRAPHIC
&& isReversed(this.srcLine[0], this.srcLine[2], this.dstLine[0], this.dstLine[2])
) {
scaleX = scaleX * -1;
scaleX *= -1;
}
}
break;
@ -835,7 +835,7 @@ export abstract class BattleAnim {
}
// biome-ignore lint/complexity/noBannedTypes: callback is used liberally
play(onSubstitute?: boolean, callback?: Function) {
play(onSubstitute?: boolean, callback?: () => void) {
const isOppAnim = this.isOppAnim();
const user = isOppAnim ? this.target! : this.user!;
const target = isOppAnim ? this.user! : this.target!; // TODO: These bangs are LITERALLY not correct at all
@ -1179,7 +1179,7 @@ export abstract class BattleAnim {
frameTimeMult: number,
frameTimedEventPriority?: 0 | 1 | 3 | 5,
// biome-ignore lint/complexity/noBannedTypes: callback is used liberally
callback?: Function,
callback?: () => void,
) {
const spriteCache: SpriteCache = {
[AnimFrameTarget.GRAPHIC]: [],

View File

@ -933,7 +933,7 @@ export class FreshStartChallenge extends Challenge {
}
applyStarterModify(pokemon: Pokemon): boolean {
pokemon.abilityIndex = pokemon.abilityIndex % 2; // Always base ability, if you set it to hidden it wraps to first ability
pokemon.abilityIndex %= 2; // Always base ability, if you set it to hidden it wraps to first ability
pokemon.passive = false; // Passive isn't unlocked
let validMoves = pokemon.species
.getLevelMoves()

View File

@ -10,7 +10,7 @@ export interface TrainerTypeMessages {
}
export interface TrainerTypeDialogue {
[key: number]: TrainerTypeMessages | Array<TrainerTypeMessages>;
[key: number]: TrainerTypeMessages | TrainerTypeMessages[];
}
export function getTrainerTypeDialogue(): TrainerTypeDialogue {

View File

@ -567,7 +567,7 @@ function doBerryBounce(berrySprites: Phaser.GameObjects.Sprite[], yd: number, ba
bouncePower = bouncePower > 0.01 ? bouncePower * 0.5 : 0;
if (bouncePower) {
bounceYOffset = bounceYOffset * bouncePower;
bounceYOffset *= bouncePower;
globalScene.tweens.add({
targets: berrySprites,

View File

@ -739,7 +739,7 @@ export function selectOptionThenPokemon(
export function setEncounterRewards(
customShopRewards?: CustomModifierSettings,
eggRewards?: IEggOptions[],
preRewardsCallback?: Function,
preRewardsCallback?: () => void,
): void {
globalScene.currentBattle.mysteryEncounter!.doEncounterRewards = () => {
if (preRewardsCallback) {
@ -1172,8 +1172,8 @@ export function calculateMEAggregateStats(baseSpawnWeight: number): void {
const tierWeights = [66, 40, 19, 3];
// Adjust tier weights by currently encountered events (pity system that lowers odds of multiple Common/Great)
tierWeights[0] = tierWeights[0] - 6 * numEncounters[0];
tierWeights[1] = tierWeights[1] - 4 * numEncounters[1];
tierWeights[0] -= 6 * numEncounters[0];
tierWeights[1] -= 4 * numEncounters[1];
const totalWeight = tierWeights.reduce((a, b) => a + b);
const tierValue = randSeedInt(totalWeight);

View File

@ -115,8 +115,7 @@ export function doPokeballBounceAnim(
y1: number,
y2: number,
baseBounceDuration: number,
// biome-ignore lint/complexity/noBannedTypes: TODO
callback: Function,
callback: () => void,
isCritical = false,
) {
let bouncePower = 1;

View File

@ -421,7 +421,7 @@ export abstract class PokemonSpeciesForm {
case SpeciesId.BLOODMOON_URSALUNA:
break;
default:
speciesId = speciesId % 2000;
speciesId %= 2000;
break;
}
}

View File

@ -158,7 +158,7 @@ export function getRandomStatus(statusA: Status | null, statusB: Status | null):
* Gets all non volatile status effects
* @returns A list containing all non volatile status effects
*/
export function getNonVolatileStatusEffects(): Array<StatusEffect> {
export function getNonVolatileStatusEffects(): StatusEffect[] {
return [
StatusEffect.POISON,
StatusEffect.TOXIC,

View File

@ -134,7 +134,7 @@ function doFanOutParticle(
}
particle.x = x + sin(trigIndex, f * xSpeed);
particle.y = y + cos(trigIndex, f * ySpeed);
trigIndex = trigIndex + angle;
trigIndex += angle;
f++;
};

View File

@ -1847,21 +1847,21 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
* @returns An array of {@linkcode PokemonMove}, as described above.
*/
getMoveset(ignoreOverride = false): PokemonMove[] {
// Overrides moveset based on arrays specified in overrides.ts
let overrideArray: MoveId | Array<MoveId> = this.isPlayer()
? Overrides.MOVESET_OVERRIDE
: Overrides.ENEMY_MOVESET_OVERRIDE;
overrideArray = coerceArray(overrideArray);
if (overrideArray.length > 0) {
if (!this.isPlayer()) {
this.moveset = [];
}
overrideArray.forEach((move: MoveId, index: number) => {
const ppUsed = this.moveset[index]?.ppUsed ?? 0;
this.moveset[index] = new PokemonMove(move, Math.min(ppUsed, allMoves[move].pp));
});
// Override moveset based on arrays specified in overrides.ts
const overrideArray = coerceArray(this.isPlayer() ? Overrides.MOVESET_OVERRIDE : Overrides.ENEMY_MOVESET_OVERRIDE);
if (overrideArray.length === 0) {
return !ignoreOverride && this.summonData.moveset ? this.summonData.moveset : this.moveset;
}
if (!this.isPlayer()) {
this.moveset = [];
}
// TODO: Preserve PP used while the moveset override is active
overrideArray.forEach((move: MoveId, index: number) => {
const ppUsed = this.moveset[index]?.ppUsed ?? 0;
this.moveset[index] = new PokemonMove(move, Math.min(ppUsed, allMoves[move].pp));
});
return !ignoreOverride && this.summonData.moveset ? this.summonData.moveset : this.moveset;
}
@ -2658,10 +2658,10 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
hpDiffRatio = 1 - hpRatio + (outspeed ? 0.2 : 0.1);
}
} else if (outspeed) {
hpDiffRatio = hpDiffRatio * 1.25;
hpDiffRatio *= 1.25;
} else if (hpRatio > 0.2 && hpRatio <= 0.4) {
// Might be considered to be switched because it's not in low enough health
hpDiffRatio = hpDiffRatio * 0.5;
hpDiffRatio *= 0.5;
}
return (atkScore + defScore) * Math.min(hpDiffRatio, 1);
}
@ -3909,7 +3909,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
}
damage = Math.min(damage, this.hp);
this.hp = this.hp - damage;
this.hp -= damage;
if (this.isFainted() && !ignoreFaintPhase) {
globalScene.phaseManager.queueFaintPhase(this.getBattlerIndex(), preventEndure);
this.destroySubstitute();

View File

@ -70,7 +70,7 @@ const repeatInputDelayMillis = 250;
* providing a unified interface for all input-related interactions.
*/
export class InputsController {
private gamepads: Array<Phaser.Input.Gamepad.Gamepad> = [];
private gamepads: Phaser.Input.Gamepad.Gamepad[] = [];
public events: Phaser.Events.EventEmitter;
private buttonLock: Button[] = [];
@ -80,7 +80,7 @@ export class InputsController {
public gamepadSupport = true;
public selectedDevice;
private disconnectedGamepads: Array<string> = [];
private disconnectedGamepads: string[] = [];
public lastSource = "keyboard";
private inputInterval: NodeJS.Timeout[] = [];
@ -223,7 +223,7 @@ export class InputsController {
* Retrieves the identifiers of all connected gamepads, excluding any that are currently marked as disconnected.
* @returns Array<String> An array of strings representing the IDs of the connected gamepads.
*/
getGamepadsName(): Array<string> {
getGamepadsName(): string[] {
return this.gamepads.filter(g => !this.disconnectedGamepads.includes(g.id)).map(g => g.id);
}

View File

@ -479,7 +479,7 @@ export class DoubleBattleChanceBoosterModifier extends LapsingPersistentModifier
override apply(doubleBattleChance: NumberHolder): boolean {
// This is divided because the chance is generated as a number from 0 to doubleBattleChance.value using randSeedInt
// A double battle will initiate if the generated number is 0
doubleBattleChance.value = doubleBattleChance.value / 4;
doubleBattleChance.value /= 4;
return true;
}
@ -2684,7 +2684,7 @@ export class PokemonMoveAccuracyBoosterModifier extends PokemonHeldItemModifier
* @returns always `true`
*/
override apply(_pokemon: Pokemon, moveAccuracy: NumberHolder): boolean {
moveAccuracy.value = moveAccuracy.value + this.accuracyAmount * this.getStackCount();
moveAccuracy.value += this.accuracyAmount * this.getStackCount();
return true;
}

View File

@ -159,7 +159,7 @@ class DefaultOverrides {
readonly HAS_PASSIVE_ABILITY_OVERRIDE: boolean | null = null;
readonly STATUS_OVERRIDE: StatusEffect = StatusEffect.NONE;
readonly GENDER_OVERRIDE: Gender | null = null;
readonly MOVESET_OVERRIDE: MoveId | Array<MoveId> = [];
readonly MOVESET_OVERRIDE: MoveId | MoveId[] = [];
readonly SHINY_OVERRIDE: boolean | null = null;
readonly VARIANT_OVERRIDE: Variant | null = null;
/**
@ -186,7 +186,7 @@ class DefaultOverrides {
readonly ENEMY_HAS_PASSIVE_ABILITY_OVERRIDE: boolean | null = null;
readonly ENEMY_STATUS_OVERRIDE: StatusEffect = StatusEffect.NONE;
readonly ENEMY_GENDER_OVERRIDE: Gender | null = null;
readonly ENEMY_MOVESET_OVERRIDE: MoveId | Array<MoveId> = [];
readonly ENEMY_MOVESET_OVERRIDE: MoveId | MoveId[] = [];
readonly ENEMY_SHINY_OVERRIDE: boolean | null = null;
readonly ENEMY_VARIANT_OVERRIDE: Variant | null = null;

View File

@ -11,7 +11,7 @@ import { namespaceMap } from "./utils-plugins";
interface LoadingFontFaceProperty {
face: FontFace;
extraOptions?: { [key: string]: any };
only?: Array<string>;
only?: string[];
}
//#region Constants
@ -35,7 +35,7 @@ const rangesByLanguage = {
),
};
const fonts: Array<LoadingFontFaceProperty> = [
const fonts: LoadingFontFaceProperty[] = [
// unicode (special character from PokePT)
{
face: new FontFace("emerald", "url(./fonts/PokePT_Wansung.woff2)", {

View File

@ -199,7 +199,7 @@ for (let i = 0; i < 5; i++) {
/**
* All Settings not related to controls
*/
export const Setting: Array<Setting> = [
export const Setting: Setting[] = [
{
key: SettingKeys.Game_Speed,
label: i18next.t("settings:gameSpeed"),

View File

@ -1,11 +1,14 @@
import { globalScene } from "#app/global-scene";
import { Button } from "#enums/buttons";
import type { UiMode } from "#enums/ui-mode";
import type { AnyFn } from "#types/type-helpers";
import { UiHandler } from "#ui/ui-handler";
// TODO: Why does this class exist?
export abstract class AwaitableUiHandler extends UiHandler {
protected awaitingActionInput: boolean;
protected onActionInput: Function | null;
// TODO: Add strong typing for subclasses rather than using `AnyFn`
protected onActionInput: AnyFn | null;
public tutorialActive = false;
public tutorialOverlay: Phaser.GameObjects.Rectangle;

View File

@ -171,7 +171,7 @@ export class BattleMessageUiHandler extends MessageUiHandler {
showText(
text: string,
delay?: number | null,
callback?: Function | null,
callback?: (() => void) | null,
callbackDelay?: number | null,
prompt?: boolean | null,
promptDelay?: number | null,
@ -184,7 +184,7 @@ export class BattleMessageUiHandler extends MessageUiHandler {
text: string,
name?: string,
delay?: number | null,
callback?: Function,
callback?: () => void,
callbackDelay?: number,
prompt?: boolean,
promptDelay?: number,

View File

@ -660,7 +660,7 @@ export class EggGachaUiHandler extends MessageUiHandler {
showText(
text: string,
delay?: number,
callback?: Function,
callback?: () => void,
callbackDelay?: number,
prompt?: boolean,
promptDelay?: number,

View File

@ -1,7 +1,6 @@
import { globalScene } from "#app/global-scene";
import { Button } from "#enums/buttons";
import { TextStyle } from "#enums/text-style";
import type { AnyFn } from "#types/type-helpers";
import type { ModalConfig } from "#ui/modal-ui-handler";
import { ModalUiHandler } from "#ui/modal-ui-handler";
import { addTextInputObject, addTextObject, getTextColor } from "#ui/text";
@ -18,7 +17,7 @@ export abstract class FormModalUiHandler extends ModalUiHandler {
protected inputContainers: Phaser.GameObjects.Container[] = [];
protected inputs: InputText[] = [];
protected errorMessage: Phaser.GameObjects.Text;
protected submitAction: AnyFn | undefined;
protected submitAction: (() => void) | undefined;
protected cancelAction: (() => void) | undefined;
protected tween: Phaser.Tweens.Tween | undefined;
protected formLabels: Phaser.GameObjects.Text[] = [];

View File

@ -7,7 +7,6 @@ import { PlayerGender } from "#enums/player-gender";
import { TextStyle } from "#enums/text-style";
import { UiTheme } from "#enums/ui-theme";
import type { GameData } from "#system/game-data";
import type { AnyFn } from "#types/type-helpers";
import { addTextObject } from "#ui/text";
import { UiHandler } from "#ui/ui-handler";
import { addWindow } from "#ui/ui-theme";
@ -244,7 +243,7 @@ export class GameStatsUiHandler extends UiHandler {
private gameData: GameData;
/** A callback invoked when {@linkcode clear} is called */
private exitCallback?: AnyFn | undefined;
private exitCallback?: (() => void) | undefined;
/** Whether the UI is single column mode */
private get singleCol(): boolean {
@ -402,7 +401,7 @@ export class GameStatsUiHandler extends UiHandler {
this.gameStatsContainer.setVisible(false);
}
show([username, data, callback]: [] | [username: string, data: GameData, callback?: AnyFn]): boolean {
show([username, data, callback]: [] | [username: string, data: GameData, callback?: () => void]): boolean {
super.show([]);
if (username != null && data != null) {

View File

@ -165,35 +165,36 @@ export class LoginFormUiHandler extends FormModalUiHandler {
const config = args[0] as ModalConfig;
this.processExternalProvider(config);
const originalLoginAction = this.submitAction;
this.submitAction = _ => {
if (globalScene.tweens.getTweensOf(this.modalContainer).length === 0) {
// Prevent overlapping overrides on action modification
this.submitAction = originalLoginAction;
this.sanitizeInputs();
globalScene.ui.setMode(UiMode.LOADING, { buttonActions: [] });
const onFail = error => {
globalScene.ui.setMode(UiMode.LOGIN_FORM, Object.assign(config, { errorMessage: error?.trim() }));
globalScene.ui.playError();
};
if (!this.inputs[0].text) {
return onFail(i18next.t("menu:emptyUsername"));
}
const [usernameInput, passwordInput] = this.inputs;
pokerogueApi.account
.login({
username: usernameInput.text,
password: passwordInput.text,
})
.then(error => {
if (!error && originalLoginAction) {
originalLoginAction();
} else {
onFail(error);
}
});
this.submitAction = () => {
if (globalScene.tweens.getTweensOf(this.modalContainer).length > 0) {
return;
}
// Prevent overlapping overrides on action modification
this.submitAction = originalLoginAction;
this.sanitizeInputs();
globalScene.ui.setMode(UiMode.LOADING, { buttonActions: [] });
const onFail = error => {
globalScene.ui.setMode(UiMode.LOGIN_FORM, Object.assign(config, { errorMessage: error?.trim() }));
globalScene.ui.playError();
};
if (!this.inputs[0].text) {
return onFail(i18next.t("menu:emptyUsername"));
}
const [usernameInput, passwordInput] = this.inputs;
pokerogueApi.account
.login({
username: usernameInput.text,
password: passwordInput.text,
})
.then(error => {
if (!error && originalLoginAction) {
originalLoginAction();
} else {
onFail(error);
}
});
};
return true;

View File

@ -781,7 +781,7 @@ export class MenuUiHandler extends MessageUiHandler {
showText(
text: string,
delay?: number,
callback?: Function,
callback?: () => void,
callbackDelay?: number,
prompt?: boolean,
promptDelay?: number,

View File

@ -37,7 +37,7 @@ export abstract class MessageUiHandler extends AwaitableUiHandler {
showText(
text: string,
delay?: number | null,
callback?: Function | null,
callback?: (() => void) | null,
callbackDelay?: number | null,
prompt?: boolean | null,
promptDelay?: number | null,
@ -49,7 +49,7 @@ export abstract class MessageUiHandler extends AwaitableUiHandler {
text: string,
_name?: string,
delay?: number | null,
callback?: Function | null,
callback?: (() => void) | null,
callbackDelay?: number | null,
prompt?: boolean | null,
promptDelay?: number | null,
@ -60,7 +60,7 @@ export abstract class MessageUiHandler extends AwaitableUiHandler {
private showTextInternal(
text: string,
delay?: number | null,
callback?: Function | null,
callback?: (() => void) | null,
callbackDelay?: number | null,
prompt?: boolean | null,
promptDelay?: number | null,
@ -219,7 +219,7 @@ export abstract class MessageUiHandler extends AwaitableUiHandler {
}
}
showPrompt(callback?: Function | null, callbackDelay?: number | null) {
showPrompt(callback?: (() => void) | null, callbackDelay?: number | null) {
const wrappedTextLines = this.message.runWordWrap(this.message.text).split(/\n/g);
const textLinesCount = wrappedTextLines.length;
const lastTextLine = wrappedTextLines.at(-1) ?? "";

View File

@ -11,6 +11,7 @@ import { UiMode } from "#enums/ui-mode";
import { HealShopCostModifier, LockModifierTiersModifier, PokemonHeldItemModifier } from "#modifiers/modifier";
import type { ModifierTypeOption } from "#modifiers/modifier-type";
import { getPlayerShopModifierTypeOptionsForWave, TmModifierType } from "#modifiers/modifier-type";
import type { ModifierSelectCallback } from "#phases/select-modifier-phase";
import { AwaitableUiHandler } from "#ui/awaitable-ui-handler";
import { MoveInfoOverlay } from "#ui/move-info-overlay";
import { addTextObject, getModifierTierTextTint, getTextColor, getTextStyleOptions } from "#ui/text";
@ -34,6 +35,7 @@ export class ModifierSelectUiHandler extends AwaitableUiHandler {
private lockRarityButtonText: Phaser.GameObjects.Text;
private moveInfoOverlay: MoveInfoOverlay;
private moveInfoOverlayActive = false;
protected declare onActionInput: ModifierSelectCallback | null;
private rowCursor = 0;
private player: boolean;
@ -424,7 +426,8 @@ export class ModifierSelectUiHandler extends AwaitableUiHandler {
const originalOnActionInput = this.onActionInput;
this.awaitingActionInput = false;
this.onActionInput = null;
originalOnActionInput(-1);
// TODO: What is a good fallback to pass to this?
originalOnActionInput(-1, -1);
this.moveInfoOverlayActive = this.moveInfoOverlay.active;
this.moveInfoOverlay.setVisible(false);
this.moveInfoOverlay.active = false; // don't clear here as we might need to restore the UI in case the user cancels the action

View File

@ -1289,7 +1289,7 @@ export class PartyUiHandler extends MessageUiHandler {
showText(
text: string,
delay?: number | null,
callback?: Function | null,
callback?: (() => void) | null,
callbackDelay?: number | null,
prompt?: boolean | null,
promptDelay?: number | null,

View File

@ -1085,7 +1085,7 @@ export class PokedexPageUiHandler extends MessageUiHandler {
showText(
text: string,
delay?: number,
callback?: Function,
callback?: () => void,
callbackDelay?: number,
prompt?: boolean,
promptDelay?: number,

View File

@ -165,7 +165,7 @@ export class PokedexScanUiHandler extends FormModalUiHandler {
} else {
this.inputs[0].text = args[1];
}
this.submitAction = _ => {
this.submitAction = () => {
if (ui.getMode() === UiMode.POKEDEX_SCAN) {
this.sanitizeInputs();
const outputName = this.reducedKeys.includes(this.inputs[0].text) ? this.inputs[0].text : "";

View File

@ -34,7 +34,6 @@ import type { GameData } from "#system/game-data";
import { SettingKeyboard } from "#system/settings-keyboard";
import type { DexEntry } from "#types/dex-data";
import type { DexAttrProps, StarterAttributes } from "#types/save-data";
import type { AnyFn } from "#types/type-helpers";
import type { OptionSelectConfig } from "#ui/abstract-option-select-ui-handler";
import { DropDown, DropDownLabel, DropDownOption, DropDownState, DropDownType, SortCriteria } from "#ui/dropdown";
import { FilterBar } from "#ui/filter-bar";
@ -239,7 +238,7 @@ export class PokedexUiHandler extends MessageUiHandler {
private filteredIndices: SpeciesId[];
private gameData: GameData;
private exitCallback?: AnyFn;
private exitCallback?: () => void;
private blockOpenPage = false;
constructor() {
@ -793,7 +792,7 @@ export class PokedexUiHandler extends MessageUiHandler {
showText(
text: string,
delay?: number,
callback?: Function,
callback?: () => void,
callbackDelay?: number,
prompt?: boolean,
promptDelay?: number,

View File

@ -76,7 +76,7 @@ export class RegistrationFormUiHandler extends FormModalUiHandler {
const config = args[0] as ModalConfig;
const originalRegistrationAction = this.submitAction;
this.submitAction = _ => {
this.submitAction = () => {
if (globalScene.tweens.getTweensOf(this.modalContainer).length === 0) {
// Prevent overlapping overrides on action modification
this.submitAction = originalRegistrationAction;

View File

@ -42,7 +42,7 @@ export class RenameFormUiHandler extends FormModalUiHandler {
} else {
this.inputs[0].text = args[1];
}
this.submitAction = _ => {
this.submitAction = () => {
this.sanitizeInputs();
const sanitizedName = btoa(unescape(encodeURIComponent(this.inputs[0].text)));
config.buttonActions[0](sanitizedName);

View File

@ -42,7 +42,7 @@ export class RenameRunFormUiHandler extends FormModalUiHandler {
});
}
const config = args[0] as ModalConfig;
this.submitAction = _ => {
this.submitAction = () => {
this.sanitizeInputs();
const sanitizedName = btoa(encodeURIComponent(this.inputs[0].text));
config.buttonActions[0](sanitizedName);

View File

@ -343,7 +343,7 @@ export class SaveSlotSelectUiHandler extends MessageUiHandler {
showText(
text: string,
delay?: number,
callback?: Function,
callback?: () => void,
callbackDelay?: number,
prompt?: boolean,
promptDelay?: number,

View File

@ -1334,7 +1334,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
showText(
text: string,
delay?: number,
callback?: Function,
callback?: () => void,
callbackDelay?: number,
prompt?: boolean,
promptDelay?: number,

View File

@ -126,7 +126,7 @@ export class SummaryUiHandler extends UiHandler {
private playerParty: boolean;
/**This is set to false when checking the summary of a freshly caught Pokemon as it is not part of a player's party yet but still needs to display its items*/
private newMove: Move | null;
private moveSelectFunction: Function | null;
private moveSelectFunction: ((cursor: number) => void) | null;
private transitioning: boolean;
private statusVisible: boolean;
private moveEffectsVisible: boolean;
@ -134,7 +134,7 @@ export class SummaryUiHandler extends UiHandler {
private moveSelect: boolean;
private moveCursor: number;
private selectedMoveIndex: number;
private selectCallback: Function | null;
private selectCallback: ((cursor: number) => void) | null;
constructor() {
super(UiMode.SUMMARY);
@ -335,18 +335,44 @@ export class SummaryUiHandler extends UiHandler {
return `summary_${Page[page].toLowerCase()}`;
}
show(args: any[]): boolean {
show(
args: [
pokemon: PlayerPokemon,
uiMode?: SummaryUiMode.DEFAULT,
startPage?: Page,
selectCallback?: (cursor: number) => void,
player?: boolean,
],
): boolean;
show(
args: [
pokemon: PlayerPokemon,
uiMode: SummaryUiMode.LEARN_MOVE,
move?: Move,
moveSelectCallback?: (cursor: number) => void,
player?: boolean,
],
): boolean;
show(
args: [
pokemon: PlayerPokemon,
uiMode?: SummaryUiMode,
startPage?: Page | Move,
callback?: (cursor: number) => void,
player?: boolean,
],
): boolean {
super.show(args);
/* args[] information
* args[0] : the Pokemon displayed in the Summary-UI
* args[1] : the summaryUiMode (defaults to 0)
* args[2] : the start page (defaults to Page.PROFILE)
* args[2] : the start page (defaults to Page.PROFILE), or the move being selected
* args[3] : contains the function executed when the user exits out of Summary UI
* args[4] : optional boolean used to determine if the Pokemon is part of the player's party or not (defaults to true, necessary for PR #2921 to display all relevant information)
*/
this.pokemon = args[0] as PlayerPokemon;
this.summaryUiMode = args.length > 1 ? (args[1] as SummaryUiMode) : SummaryUiMode.DEFAULT;
this.summaryUiMode = (args[1] as SummaryUiMode) ?? SummaryUiMode.DEFAULT;
this.playerParty = args[4] ?? true;
globalScene.ui.bringToTop(this.summaryContainer);
@ -486,17 +512,15 @@ export class SummaryUiHandler extends UiHandler {
switch (this.summaryUiMode) {
case SummaryUiMode.DEFAULT: {
const page = args.length < 2 ? Page.PROFILE : (args[2] as Page);
const page = (args[2] as Page) ?? Page.PROFILE;
this.hideMoveEffect(true);
this.setCursor(page);
if (args.length > 3) {
this.selectCallback = args[3];
}
this.selectCallback = args[3] ?? null;
break;
}
case SummaryUiMode.LEARN_MOVE:
this.newMove = args[2] as Move;
this.moveSelectFunction = args[3] as Function;
this.moveSelectFunction = args[3] ?? null;
this.showMoveEffect(true);
this.setCursor(Page.MOVES);
@ -615,7 +639,7 @@ export class SummaryUiHandler extends UiHandler {
if (this.selectCallback instanceof Function) {
const selectCallback = this.selectCallback;
this.selectCallback = null;
selectCallback();
selectCallback(-1);
}
if (!fromPartyMode) {

View File

@ -12,7 +12,7 @@ export class TestDialogueUiHandler extends FormModalUiHandler {
setup() {
super.setup();
const flattenKeys = (object?: any, topKey?: string, middleKey?: string[]): Array<any> => {
const flattenKeys = (object?: any, topKey?: string, middleKey?: string[]): any[] => {
return Object.keys(object ?? {})
.map((t, i) => {
const value = Object.values(object)[i];
@ -141,7 +141,7 @@ export class TestDialogueUiHandler extends FormModalUiHandler {
} else {
this.inputs[0].text = args[1];
}
this.submitAction = _ => {
this.submitAction = () => {
if (ui.getMode() === UiMode.TEST_DIALOGUE) {
this.sanitizeInputs();
const sanitizedName = btoa(unescape(encodeURIComponent(this.inputs[0].text)));

View File

@ -24,7 +24,7 @@ export interface LayoutConfig {
optionValueLabels: Phaser.GameObjects.Text[][];
optionCursors: number[];
keys: string[];
bindingSettings: Array<string>;
bindingSettings: string[];
}
/**
* Abstract class for handling UI elements related to control settings.
@ -51,10 +51,10 @@ export abstract class AbstractControlSettingsUiHandler extends UiHandler {
protected inputsIcons: InputsIcons;
protected navigationIcons: InputsIcons;
// list all the setting keys used in the selected layout (because dualshock has more buttons than xbox)
protected keys: Array<string>;
protected keys: string[];
// Store the specific settings related to key bindings for the current gamepad configuration.
protected bindingSettings: Array<string>;
protected bindingSettings: string[];
protected setting;
protected settingBlacklisted;

View File

@ -4,7 +4,6 @@ import { TextStyle } from "#enums/text-style";
import { UiMode } from "#enums/ui-mode";
import type { SettingType } from "#system/settings";
import { Setting, SettingKeys } from "#system/settings";
import type { AnyFn } from "#types/type-helpers";
import type { InputsIcons } from "#ui/abstract-control-settings-ui-handler";
import { MessageUiHandler } from "#ui/message-ui-handler";
import { NavigationManager, NavigationMenu } from "#ui/navigation-menu";
@ -40,7 +39,7 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
protected rowsToDisplay: number;
protected title: string;
protected settings: Array<Setting>;
protected settings: Setting[];
protected localStorageKey: string;
constructor(type: SettingType, mode: UiMode | null = null) {
@ -518,7 +517,7 @@ export class AbstractSettingsUiHandler extends MessageUiHandler {
override showText(
text: string,
delay?: number,
callback?: AnyFn,
callback?: () => void,
callbackDelay?: number,
prompt?: boolean,
promptDelay?: number,

View File

@ -277,7 +277,7 @@ export class UI extends Phaser.GameObjects.Container {
showText(
text: string,
delay?: number | null,
callback?: Function | null,
callback?: (() => void) | null,
callbackDelay?: number | null,
prompt?: boolean | null,
promptDelay?: number | null,
@ -316,7 +316,7 @@ export class UI extends Phaser.GameObjects.Container {
keyOrText: string,
name: string | undefined,
delay: number | null = 0,
callback: Function,
callback: () => void,
callbackDelay?: number,
promptDelay?: number,
): void {

View File

@ -148,7 +148,7 @@ describe("Abilities - Dry Skin", () => {
const enemy = game.field.getEnemyPokemon();
game.move.select(MoveId.WATER_GUN);
enemy.hp = enemy.hp - 1;
enemy.hp -= 1;
await game.phaseInterceptor.to("MoveEffectPhase");
await game.move.forceMiss();

View File

@ -65,7 +65,7 @@ describe("Abilities - Volt Absorb", () => {
const enemyPokemon = game.field.getEnemyPokemon();
game.move.select(MoveId.THUNDERBOLT);
enemyPokemon.hp = enemyPokemon.hp - 1;
enemyPokemon.hp -= 1;
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.phaseInterceptor.to("MoveEffectPhase");
@ -86,7 +86,7 @@ describe("Abilities - Volt Absorb", () => {
const enemyPokemon = game.field.getEnemyPokemon();
game.move.select(MoveId.THUNDERBOLT);
enemyPokemon.hp = enemyPokemon.hp - 1;
enemyPokemon.hp -= 1;
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
await game.phaseInterceptor.to("BerryPhase", false);

View File

@ -2,6 +2,7 @@ import type { MockGameObject } from "#test/test-utils/mocks/mock-game-object";
import type { MockTextureManager } from "#test/test-utils/mocks/mock-texture-manager";
import { coerceArray } from "#utils/array";
// TODO: Make this implement Phaser.GameObjects.Container
export class MockContainer implements MockGameObject {
protected x: number;
protected y: number;

View File

@ -82,7 +82,7 @@ export class MockText implements MockGameObject {
showText(
text: string,
_delay?: number | null,
callback?: Function | null,
callback?: (() => void) | null,
_callbackDelay?: number | null,
_prompt?: boolean | null,
_promptDelay?: number | null,
@ -98,7 +98,7 @@ export class MockText implements MockGameObject {
keyOrText: string,
name: string,
_delay: number | null,
callback: Function,
callback: () => void,
_callbackDelay?: number,
_promptDelay?: number,
) {
@ -354,7 +354,7 @@ export class MockText implements MockGameObject {
}
// biome-ignore lint/complexity/noBannedTypes: This matches the signature of the class this mocks
on(_event: string | symbol, _fn: Function, _context?: any) {}
on(_event: string | symbol, _fn: () => void, _context?: any) {}
setActive(_active: boolean): this {
return this;