diff --git a/.dependency-cruiser.cjs b/.dependency-cruiser.cjs index 40a9785aeaf..eccec089f1e 100644 --- a/.dependency-cruiser.cjs +++ b/.dependency-cruiser.cjs @@ -218,7 +218,7 @@ module.exports = { module systems it knows of. It's the default because it's the safe option It might come at a performance penalty, though. moduleSystems: ['amd', 'cjs', 'es6', 'tsd'] - + As in practice only commonjs ('cjs') and ecmascript modules ('es6') are widely used, you can limit the moduleSystems to those. */ @@ -226,7 +226,7 @@ module.exports = { // moduleSystems: ['cjs', 'es6'], /* prefix for links in html and svg output (e.g. 'https://github.com/you/yourrepo/blob/main/' - to open it on your online repo or `vscode://file/${process.cwd()}/` to + to open it on your online repo or `vscode://file/${process.cwd()}/` to open it in visual studio code), */ // prefix: `vscode://file/${process.cwd()}/`, @@ -271,7 +271,7 @@ module.exports = { to './webpack.conf.js'. The (optional) `env` and `arguments` attributes contain the parameters - to be passed if your webpack config is a function and takes them (see + to be passed if your webpack config is a function and takes them (see webpack documentation for details) */ // webpackConfig: { @@ -322,8 +322,8 @@ module.exports = { A list of alias fields in package.jsons See [this specification](https://github.com/defunctzombie/package-browser-field-spec) and the webpack [resolve.alias](https://webpack.js.org/configuration/resolve/#resolvealiasfields) - documentation - + documentation + Defaults to an empty array (= don't use alias fields). */ // aliasFields: ["browser"], diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 79ab1bdc38a..979b94f84d6 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -8,7 +8,7 @@ # Art Team /public/**/*.png @pagefaultgames/art-team -/public/**/*.json @pagefaultgames/art-team +/public/**/*.json @pagefaultgames/art-team /public/images @pagefaultgames/art-team /public/battle-anims @pagefaultgames/art-team diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a25a2f807f3..c7d8b1e4d9c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,25 +2,28 @@ + ## What are the changes the user will see? @@ -66,11 +69,11 @@ Do the reviewers need to do something special in order to test your changes? - [ ] Have I provided a clear explanation of the changes? - [ ] Have I tested the changes manually? - [ ] Are all unit tests still passing? (`npm run test:silent`) - - [ ] Have I created new automated tests (`npm run create-test`) or updated existing tests related to the PR's changes? + - [ ] Have I created new automated tests (`npm run test:create`) or updated existing tests related to the PR's changes? - [ ] Have I provided screenshots/videos of the changes (if applicable)? - [ ] Have I made sure that any UI change works for both UI themes (default and legacy)? Are there any localization additions or changes? If so: - [ ] Has a locales PR been created on the [locales](https://github.com/pagefaultgames/pokerogue-locales) repo? - [ ] If so, please leave a link to it here: -- [ ] Has the translation team been contacted for proofreading/translation? \ No newline at end of file +- [ ] Has the translation team been contacted for proofreading/translation? diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 00190e477d5..a233a2fccab 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -35,7 +35,7 @@ jobs: ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts - name: Deploy build on server if: github.event_name == 'push' && github.ref_name == 'main' - run: | + run: | rsync --del --no-times --checksum -vrm dist/* ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DESTINATION_DIR }} ssh -t ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "~/prmanifest --inpath ${{ secrets.DESTINATION_DIR }} --outpath ${{ secrets.DESTINATION_DIR }}/manifest.json" - name: Purge Cloudflare Cache diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index d9592662998..36233248472 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -33,7 +33,7 @@ jobs: - name: Install Node.js dependencies # Step to install Node.js dependencies run: npm ci # Use 'npm ci' to install dependencies - + - name: eslint # Step to run linters run: npm run eslint-ci diff --git a/biome.jsonc b/biome.jsonc index 82ce7c308dc..f427debb198 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -47,8 +47,8 @@ "correctness": { "noUndeclaredVariables": "off", "noUnusedVariables": "error", - "noSwitchDeclarations": "warn", // TODO: refactor and make this an error - "noVoidTypeReturn": "warn", // TODO: Refactor and make this an error + "noSwitchDeclarations": "error", + "noVoidTypeReturn": "error", "noUnusedImports": "error" }, "style": { @@ -85,7 +85,7 @@ "useLiteralKeys": "off", "noForEach": "off", // Foreach vs for of is not that simple. "noUselessSwitchCase": "off", // Explicit > Implicit - "noUselessConstructor": "warn", // TODO: Refactor and make this an error + "noUselessConstructor": "error", "noBannedTypes": "warn" // TODO: Refactor and make this an error }, "nursery": { diff --git a/global.d.ts b/global.d.ts index c896a4983e4..d2ed6438c0b 100644 --- a/global.d.ts +++ b/global.d.ts @@ -7,7 +7,7 @@ declare global { * Only used in testing. * Can technically be undefined/null but for ease of use we are going to assume it is always defined. * Used to load i18n files exclusively. - * + * * To set up your own server in a test see `game_data.test.ts` */ var server: SetupServerApi; diff --git a/package.json b/package.json index 36c3c2b919f..b927542788d 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "eslint": "eslint --fix .", "eslint-ci": "eslint .", "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", "depcruise": "depcruise src", "depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg", diff --git a/src/@types/modifier-types.ts b/src/@types/modifier-types.ts index 6c0136e655e..80b92c35622 100644 --- a/src/@types/modifier-types.ts +++ b/src/@types/modifier-types.ts @@ -29,4 +29,4 @@ export type ModifierString = keyof ModifierConstructorMap; export type ModifierPool = { [tier: string]: WeightedModifierType[]; -} \ No newline at end of file +}; diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index d8743a0effe..ef4529c361e 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -9,6 +9,7 @@ import { randSeedInt, type Constructor, randSeedFloat, + coerceArray, } from "#app/utils/common"; import { getPokemonNameWithAffix } from "#app/messages"; import { GroundedTag } from "#app/data/battler-tags"; @@ -4689,7 +4690,7 @@ export class PreApplyBattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { constructor(immuneTagTypes: BattlerTagType | BattlerTagType[]) { super(true); - this.immuneTagTypes = Array.isArray(immuneTagTypes) ? immuneTagTypes : [immuneTagTypes]; + this.immuneTagTypes = coerceArray(immuneTagTypes); } override canApplyPreApplyBattlerTag( @@ -6694,7 +6695,7 @@ export class FlinchStatStageChangeAbAttr extends FlinchEffectAbAttr { constructor(stats: BattleStat[], stages: number) { super(); - this.stats = Array.isArray(stats) ? stats : [stats]; + this.stats = stats; this.stages = stages; } diff --git a/src/data/battle-anims.ts b/src/data/battle-anims.ts index 7aa419ca470..131086625df 100644 --- a/src/data/battle-anims.ts +++ b/src/data/battle-anims.ts @@ -2,7 +2,7 @@ import { globalScene } from "#app/global-scene"; import { allMoves } from "./data-lists"; import { MoveFlags } from "#enums/MoveFlags"; import type Pokemon from "../field/pokemon"; -import { type nil, getFrameMs, getEnumKeys, getEnumValues, animationFileName } from "../utils/common"; +import { type nil, getFrameMs, getEnumKeys, getEnumValues, animationFileName, coerceArray } from "../utils/common"; import type { BattlerIndex } from "#enums/battler-index"; import { MoveId } from "#enums/move-id"; import { SubstituteTag } from "./battler-tags"; @@ -520,7 +520,7 @@ function logMissingMoveAnim(move: MoveId, ...optionalParams: any[]) { * @param encounterAnim one or more animations to fetch */ export async function initEncounterAnims(encounterAnim: EncounterAnim | EncounterAnim[]): Promise { - const anims = Array.isArray(encounterAnim) ? encounterAnim : [encounterAnim]; + const anims = coerceArray(encounterAnim); const encounterAnimNames = getEnumKeys(EncounterAnim); const encounterAnimFetches: Promise>[] = []; for (const anim of anims) { diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 0daf1913737..98cefb78bd5 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -21,7 +21,7 @@ import type { MoveEffectPhase } from "#app/phases/move-effect-phase"; import type { MovePhase } from "#app/phases/move-phase"; import type { StatStageChangeCallback } from "#app/phases/stat-stage-change-phase"; import i18next from "#app/plugins/i18n"; -import { BooleanHolder, getFrameMs, NumberHolder, toDmgValue } from "#app/utils/common"; +import { BooleanHolder, coerceArray, getFrameMs, NumberHolder, toDmgValue } from "#app/utils/common"; import { AbilityId } from "#enums/ability-id"; import { BattlerTagType } from "#enums/battler-tag-type"; import { MoveId } from "#enums/move-id"; @@ -50,7 +50,7 @@ export class BattlerTag { isBatonPassable = false, ) { this.tagType = tagType; - this.lapseTypes = Array.isArray(lapseType) ? lapseType : [lapseType]; + this.lapseTypes = coerceArray(lapseType); this.turnCount = turnCount; this.sourceMove = sourceMove!; // TODO: is this bang correct? this.sourceId = sourceId; @@ -125,16 +125,6 @@ export interface TerrainBattlerTag { * Players and enemies should not be allowed to select restricted moves. */ 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 lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { if (lapseType === BattlerTagLapseType.PRE_MOVE) { @@ -1470,16 +1460,6 @@ export class WrapTag 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 { return i18next.t("battlerTags:vortexOnTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index f1a45f265fa..853a3d8e64c 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -2173,6 +2173,7 @@ export class PlantHealAttr extends WeatherHealAttr { case WeatherType.SANDSTORM: case WeatherType.HAIL: case WeatherType.SNOW: + case WeatherType.FOG: case WeatherType.HEAVY_RAIN: return 0.25; default: @@ -4174,6 +4175,7 @@ export class AntiSunlightPowerDecreaseAttr extends VariablePowerAttr { case WeatherType.SANDSTORM: case WeatherType.HAIL: case WeatherType.SNOW: + case WeatherType.FOG: case WeatherType.HEAVY_RAIN: power.value *= 0.5; return true; diff --git a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts index f925452e143..c53ff610c48 100644 --- a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts +++ b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts @@ -11,10 +11,7 @@ import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requir import type Pokemon from "#app/field/pokemon"; import { ModifierTier } from "#enums/modifier-tier"; import type { ModifierTypeOption } from "#app/modifier/modifier-type"; -import { - getPlayerModifierTypeOptions, - regenerateModifierPoolThresholds, -} from "#app/modifier/modifier-type"; +import { getPlayerModifierTypeOptions, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type"; import { ModifierPoolType } from "#enums/modifier-pool-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { globalScene } from "#app/global-scene"; diff --git a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts index 1b188915de7..0393bcdaa62 100644 --- a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts +++ b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts @@ -7,10 +7,7 @@ import { TrainerSlot } from "#enums/trainer-slot"; import { ModifierTier } from "#enums/modifier-tier"; import { MusicPreference } from "#app/system/settings/settings"; import type { ModifierTypeOption } from "#app/modifier/modifier-type"; -import { - getPlayerModifierTypeOptions, - regenerateModifierPoolThresholds, -} from "#app/modifier/modifier-type"; +import { getPlayerModifierTypeOptions, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type"; import { ModifierPoolType } from "#enums/modifier-pool-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { globalScene } from "#app/global-scene"; diff --git a/src/data/mystery-encounters/mystery-encounter-requirements.ts b/src/data/mystery-encounters/mystery-encounter-requirements.ts index bca34be723b..a6e6e84846f 100644 --- a/src/data/mystery-encounters/mystery-encounter-requirements.ts +++ b/src/data/mystery-encounters/mystery-encounter-requirements.ts @@ -11,7 +11,7 @@ import { WeatherType } from "#enums/weather-type"; import type { PlayerPokemon } from "#app/field/pokemon"; import { AttackTypeBoosterModifier } from "#app/modifier/modifier"; import type { AttackTypeBoosterModifierType } from "#app/modifier/modifier-type"; -import { isNullOrUndefined } from "#app/utils/common"; +import { coerceArray, isNullOrUndefined } from "#app/utils/common"; import type { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; @@ -272,7 +272,7 @@ export class TimeOfDayRequirement extends EncounterSceneRequirement { constructor(timeOfDay: TimeOfDay | TimeOfDay[]) { super(); - this.requiredTimeOfDay = Array.isArray(timeOfDay) ? timeOfDay : [timeOfDay]; + this.requiredTimeOfDay = coerceArray(timeOfDay); } override meetsRequirement(): boolean { @@ -294,7 +294,7 @@ export class WeatherRequirement extends EncounterSceneRequirement { constructor(weather: WeatherType | WeatherType[]) { super(); - this.requiredWeather = Array.isArray(weather) ? weather : [weather]; + this.requiredWeather = coerceArray(weather); } override meetsRequirement(): boolean { @@ -360,7 +360,7 @@ export class PersistentModifierRequirement extends EncounterSceneRequirement { constructor(heldItem: string | string[], minNumberOfItems = 1) { super(); this.minNumberOfItems = minNumberOfItems; - this.requiredHeldItemModifiers = Array.isArray(heldItem) ? heldItem : [heldItem]; + this.requiredHeldItemModifiers = coerceArray(heldItem); } override meetsRequirement(): boolean { @@ -426,7 +426,7 @@ export class SpeciesRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredSpecies = Array.isArray(species) ? species : [species]; + this.requiredSpecies = coerceArray(species); } override meetsRequirement(): boolean { @@ -466,7 +466,7 @@ export class NatureRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredNature = Array.isArray(nature) ? nature : [nature]; + this.requiredNature = coerceArray(nature); } override meetsRequirement(): boolean { @@ -504,7 +504,7 @@ export class TypeRequirement extends EncounterPokemonRequirement { this.excludeFainted = excludeFainted; this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredType = Array.isArray(type) ? type : [type]; + this.requiredType = coerceArray(type); } override meetsRequirement(): boolean { @@ -558,7 +558,7 @@ export class MoveRequirement extends EncounterPokemonRequirement { this.excludeDisallowedPokemon = excludeDisallowedPokemon; this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredMoves = Array.isArray(moves) ? moves : [moves]; + this.requiredMoves = coerceArray(moves); } override meetsRequirement(): boolean { @@ -609,7 +609,7 @@ export class CompatibleMoveRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredMoves = Array.isArray(learnableMove) ? learnableMove : [learnableMove]; + this.requiredMoves = coerceArray(learnableMove); } override meetsRequirement(): boolean { @@ -665,7 +665,7 @@ export class AbilityRequirement extends EncounterPokemonRequirement { this.excludeDisallowedPokemon = excludeDisallowedPokemon; this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredAbilities = Array.isArray(abilities) ? abilities : [abilities]; + this.requiredAbilities = coerceArray(abilities); } override meetsRequirement(): boolean { @@ -710,7 +710,7 @@ export class StatusEffectRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredStatusEffect = Array.isArray(statusEffect) ? statusEffect : [statusEffect]; + this.requiredStatusEffect = coerceArray(statusEffect); } override meetsRequirement(): boolean { @@ -785,7 +785,7 @@ export class CanFormChangeWithItemRequirement extends EncounterPokemonRequiremen super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredFormChangeItem = Array.isArray(formChangeItem) ? formChangeItem : [formChangeItem]; + this.requiredFormChangeItem = coerceArray(formChangeItem); } override meetsRequirement(): boolean { @@ -843,7 +843,7 @@ export class CanEvolveWithItemRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredEvolutionItem = Array.isArray(evolutionItems) ? evolutionItems : [evolutionItems]; + this.requiredEvolutionItem = coerceArray(evolutionItems); } override meetsRequirement(): boolean { @@ -908,7 +908,7 @@ export class HeldItemRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredHeldItemModifiers = Array.isArray(heldItem) ? heldItem : [heldItem]; + this.requiredHeldItemModifiers = coerceArray(heldItem); this.requireTransferable = requireTransferable; } @@ -972,7 +972,7 @@ export class AttackTypeBoosterHeldItemTypeRequirement extends EncounterPokemonRe super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredHeldItemTypes = Array.isArray(heldItemTypes) ? heldItemTypes : [heldItemTypes]; + this.requiredHeldItemTypes = coerceArray(heldItemTypes); this.requireTransferable = requireTransferable; } diff --git a/src/data/mystery-encounters/mystery-encounter.ts b/src/data/mystery-encounters/mystery-encounter.ts index 6510e32fe76..bd3082afe19 100644 --- a/src/data/mystery-encounters/mystery-encounter.ts +++ b/src/data/mystery-encounters/mystery-encounter.ts @@ -2,7 +2,7 @@ import type { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encoun import type { PlayerPokemon } from "#app/field/pokemon"; import type { PokemonMove } from "../moves/pokemon-move"; import type Pokemon from "#app/field/pokemon"; -import { capitalizeFirstLetter, isNullOrUndefined } from "#app/utils/common"; +import { capitalizeFirstLetter, coerceArray, isNullOrUndefined } from "#app/utils/common"; import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; import type { MysteryEncounterSpriteConfig } from "#app/field/mystery-encounter-intro"; import MysteryEncounterIntroVisuals from "#app/field/mystery-encounter-intro"; @@ -717,7 +717,7 @@ export class MysteryEncounterBuilder implements Partial { withAnimations( ...encounterAnimations: EncounterAnim[] ): this & Required> { - const animations = Array.isArray(encounterAnimations) ? encounterAnimations : [encounterAnimations]; + const animations = coerceArray(encounterAnimations); return Object.assign(this, { encounterAnimations: animations }); } @@ -729,7 +729,7 @@ export class MysteryEncounterBuilder implements Partial { withDisallowedGameModes( ...disallowedGameModes: GameModes[] ): this & Required> { - const gameModes = Array.isArray(disallowedGameModes) ? disallowedGameModes : [disallowedGameModes]; + const gameModes = coerceArray(disallowedGameModes); return Object.assign(this, { disallowedGameModes: gameModes }); } @@ -741,7 +741,7 @@ export class MysteryEncounterBuilder implements Partial { withDisallowedChallenges( ...disallowedChallenges: Challenges[] ): this & Required> { - const challenges = Array.isArray(disallowedChallenges) ? disallowedChallenges : [disallowedChallenges]; + const challenges = coerceArray(disallowedChallenges); return Object.assign(this, { disallowedChallenges: challenges }); } diff --git a/src/data/mystery-encounters/requirements/can-learn-move-requirement.ts b/src/data/mystery-encounters/requirements/can-learn-move-requirement.ts index c0e45d5401c..0123ea7d6ba 100644 --- a/src/data/mystery-encounters/requirements/can-learn-move-requirement.ts +++ b/src/data/mystery-encounters/requirements/can-learn-move-requirement.ts @@ -1,7 +1,7 @@ import type { MoveId } from "#enums/move-id"; import type { PlayerPokemon } from "#app/field/pokemon"; import { PokemonMove } from "#app/data/moves/pokemon-move"; -import { isNullOrUndefined } from "#app/utils/common"; +import { coerceArray, isNullOrUndefined } from "#app/utils/common"; import { EncounterPokemonRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { globalScene } from "#app/global-scene"; @@ -29,7 +29,7 @@ export class CanLearnMoveRequirement extends EncounterPokemonRequirement { constructor(requiredMoves: MoveId | MoveId[], options: CanLearnMoveRequirementOptions = {}) { super(); - this.requiredMoves = Array.isArray(requiredMoves) ? requiredMoves : [requiredMoves]; + this.requiredMoves = coerceArray(requiredMoves); this.excludeLevelMoves = options.excludeLevelMoves ?? false; this.excludeTmMoves = options.excludeTmMoves ?? false; diff --git a/src/data/mystery-encounters/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index 599edb11628..e2b92230985 100644 --- a/src/data/mystery-encounters/utils/encounter-phase-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-phase-utils.ts @@ -25,7 +25,7 @@ import type { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-optio import type { PartyOption, PokemonSelectFilter } from "#app/ui/party-ui-handler"; import { PartyUiMode } from "#app/ui/party-ui-handler"; import { UiMode } from "#enums/ui-mode"; -import { isNullOrUndefined, randSeedInt, randomString, randSeedItem } from "#app/utils/common"; +import { isNullOrUndefined, randSeedInt, randomString, randSeedItem, coerceArray } from "#app/utils/common"; import type { BattlerTagType } from "#enums/battler-tag-type"; import { BiomeId } from "#enums/biome-id"; import type { TrainerType } from "#enums/trainer-type"; @@ -449,7 +449,7 @@ export async function initBattleWithEnemyConfig(partyConfig: EnemyPartyConfig): * @param moves */ export function loadCustomMovesForEncounter(moves: MoveId | MoveId[]) { - moves = Array.isArray(moves) ? moves : [moves]; + moves = coerceArray(moves); return Promise.all(moves.map(move => initMoveAnim(move))).then(() => loadMoveAnimAssets(moves)); } @@ -792,7 +792,7 @@ export function setEncounterRewards( * @param useWaveIndex - set to false when directly passing the the full exp value instead of baseExpValue */ export function setEncounterExp(participantId: number | number[], baseExpValue: number, useWaveIndex = true) { - const participantIds = Array.isArray(participantId) ? participantId : [participantId]; + const participantIds = coerceArray(participantId); globalScene.currentBattle.mysteryEncounter!.doEncounterExp = () => { globalScene.phaseManager.unshiftNew("PartyExpPhase", baseExpValue, useWaveIndex, new Set(participantIds)); diff --git a/src/data/pokemon-forms/form-change-triggers.ts b/src/data/pokemon-forms/form-change-triggers.ts index eb2c0a557c2..3726781d9e3 100644 --- a/src/data/pokemon-forms/form-change-triggers.ts +++ b/src/data/pokemon-forms/form-change-triggers.ts @@ -1,5 +1,5 @@ import i18next from "i18next"; -import type { Constructor } from "#app/utils/common"; +import { coerceArray, type Constructor } from "#app/utils/common"; import type { TimeOfDay } from "#enums/time-of-day"; import type Pokemon from "#app/field/pokemon"; import type { SpeciesFormChange } from "#app/data/pokemon-forms"; @@ -125,10 +125,7 @@ export class SpeciesFormChangeStatusEffectTrigger extends SpeciesFormChangeTrigg constructor(statusEffects: StatusEffect | StatusEffect[], invert = false) { super(); - if (!Array.isArray(statusEffects)) { - statusEffects = [statusEffects]; - } - this.statusEffects = statusEffects; + this.statusEffects = coerceArray(statusEffects); this.invert = invert; // this.description = i18next.t("pokemonEvolutions:Forms.statusEffect"); } diff --git a/src/data/trainers/trainer-config.ts b/src/data/trainers/trainer-config.ts index 8c065666202..063dddafee8 100644 --- a/src/data/trainers/trainer-config.ts +++ b/src/data/trainers/trainer-config.ts @@ -1,7 +1,14 @@ import { globalScene } from "#app/global-scene"; import { modifierTypes } from "../data-lists"; import { PokemonMove } from "../moves/pokemon-move"; -import { toReadableString, isNullOrUndefined, randSeedItem, randSeedInt, randSeedIntRange } from "#app/utils/common"; +import { + toReadableString, + isNullOrUndefined, + randSeedItem, + randSeedInt, + coerceArray, + randSeedIntRange, +} from "#app/utils/common"; import { pokemonEvolutions, pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { getPokemonSpecies } from "#app/data/pokemon-species"; import { tmSpecies } from "#app/data/balance/tms"; @@ -554,10 +561,7 @@ export class TrainerConfig { this.speciesPools = evilAdminTrainerPools[poolName]; signatureSpecies.forEach((speciesPool, s) => { - if (!Array.isArray(speciesPool)) { - speciesPool = [speciesPool]; - } - this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); + this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(coerceArray(speciesPool))); }); const nameForCall = this.name.toLowerCase().replace(/\s/g, "_"); @@ -620,10 +624,7 @@ export class TrainerConfig { this.setPartyTemplates(trainerPartyTemplates.RIVAL_5); } signatureSpecies.forEach((speciesPool, s) => { - if (!Array.isArray(speciesPool)) { - speciesPool = [speciesPool]; - } - this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); + this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(coerceArray(speciesPool))); }); if (!isNullOrUndefined(specialtyType)) { this.setSpeciesFilter(p => p.isOfType(specialtyType)); @@ -668,12 +669,8 @@ export class TrainerConfig { // Set up party members with their corresponding species. signatureSpecies.forEach((speciesPool, s) => { - // Ensure speciesPool is an array. - if (!Array.isArray(speciesPool)) { - speciesPool = [speciesPool]; - } // Set a function to get a random party member from the species pool. - this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); + this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(coerceArray(speciesPool))); }); // If specialty type is provided, set species filter and specialty type. @@ -729,12 +726,8 @@ export class TrainerConfig { // Set up party members with their corresponding species. signatureSpecies.forEach((speciesPool, s) => { - // Ensure speciesPool is an array. - if (!Array.isArray(speciesPool)) { - speciesPool = [speciesPool]; - } // Set a function to get a random party member from the species pool. - this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); + this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(coerceArray(speciesPool))); }); // Set species filter and specialty type if provided, otherwise filter by base total. diff --git a/src/field/arena.ts b/src/field/arena.ts index c77c9a5b3ce..22cb9e32863 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -262,7 +262,7 @@ export class Arena { return 5; } break; - case SpeciesId.LYCANROC: + case SpeciesId.LYCANROC: { const timeOfDay = this.getTimeOfDay(); switch (timeOfDay) { case TimeOfDay.DAY: @@ -274,6 +274,7 @@ export class Arena { return 1; } break; + } } return 0; diff --git a/src/field/pokemon-sprite-sparkle-handler.ts b/src/field/pokemon-sprite-sparkle-handler.ts index cceb0bd7717..bda9414bb92 100644 --- a/src/field/pokemon-sprite-sparkle-handler.ts +++ b/src/field/pokemon-sprite-sparkle-handler.ts @@ -1,6 +1,6 @@ import { globalScene } from "#app/global-scene"; import Pokemon from "./pokemon"; -import { fixedInt, randInt } from "#app/utils/common"; +import { fixedInt, coerceArray, randInt } from "#app/utils/common"; export default class PokemonSpriteSparkleHandler { private sprites: Set; @@ -57,9 +57,7 @@ export default class PokemonSpriteSparkleHandler { } add(sprites: Phaser.GameObjects.Sprite | Phaser.GameObjects.Sprite[]): void { - if (!Array.isArray(sprites)) { - sprites = [sprites]; - } + sprites = coerceArray(sprites); for (const s of sprites) { if (this.sprites.has(s)) { continue; @@ -69,9 +67,7 @@ export default class PokemonSpriteSparkleHandler { } remove(sprites: Phaser.GameObjects.Sprite | Phaser.GameObjects.Sprite[]): void { - if (!Array.isArray(sprites)) { - sprites = [sprites]; - } + sprites = coerceArray(sprites); for (const s of sprites) { this.sprites.delete(s); } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 964d66d352e..0205b5bf4b2 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -41,6 +41,7 @@ import { type nil, type Constructor, randSeedIntRange, + coerceArray, } from "#app/utils/common"; import type { TypeDamageMultiplier } from "#app/data/type"; import { getTypeDamageMultiplier, getTypeRgb } from "#app/data/type"; @@ -1774,9 +1775,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { let overrideArray: MoveId | Array = this.isPlayer() ? Overrides.MOVESET_OVERRIDE : Overrides.OPP_MOVESET_OVERRIDE; - if (!Array.isArray(overrideArray)) { - overrideArray = [overrideArray]; - } + overrideArray = coerceArray(overrideArray); if (overrideArray.length > 0) { if (!this.isPlayer()) { this.moveset = []; @@ -4386,14 +4385,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // biome-ignore lint: there are a ton of issues.. faintCry(callback: Function): void { if (this.fusionSpecies && this.getSpeciesForm() !== this.getFusionSpeciesForm()) { - return this.fusionFaintCry(callback); + this.fusionFaintCry(callback); + return; } const key = this.species.getCryKey(this.formIndex); let rate = 0.85; const cry = globalScene.playSound(key, { rate: rate }) as AnySound; if (!cry || globalScene.fieldVolume === 0) { - return callback(); + callback(); + return; } const sprite = this.getSprite(); const tintSprite = this.getTintSprite(); @@ -4461,7 +4462,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { rate: rate, }) as AnySound; if (!cry || !fusionCry || globalScene.fieldVolume === 0) { - return callback(); + callback(); + return; } fusionCry.stop(); duration = Math.min(duration, fusionCry.totalDuration * 1000); diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 2c848c69e18..cf373e6441a 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -2393,8 +2393,6 @@ export interface ModifierPool { [tier: string]: WeightedModifierType[]; } -const modifierPool: ModifierPool = {}; - let modifierPoolThresholds = {}; let ignoredPoolIndexes = {}; @@ -2859,7 +2857,7 @@ function getNewModifierTypeOption( } tier += upgradeCount; - while (tier && (!modifierPool.hasOwnProperty(tier) || !modifierPool[tier].length)) { + while (tier && (!pool.hasOwnProperty(tier) || !pool[tier].length)) { tier--; if (upgradeCount) { upgradeCount--; @@ -2870,7 +2868,7 @@ function getNewModifierTypeOption( if (tier < ModifierTier.MASTER && allowLuckUpgrades) { const partyLuckValue = getPartyLuckValue(party); 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) { upgradeCount++; } else { @@ -2920,6 +2918,7 @@ function getNewModifierTypeOption( } export function getDefaultModifierTypeForTier(tier: ModifierTier): ModifierType { + const modifierPool = getModifierPoolForType(ModifierPoolType.PLAYER); let modifierType: ModifierType | WeightedModifierType = modifierPool[tier || ModifierTier.COMMON][0]; if (modifierType instanceof WeightedModifierType) { modifierType = (modifierType as WeightedModifierType).modifierType; diff --git a/src/overrides.ts b/src/overrides.ts index b5df1073c28..6086f75a58e 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -272,7 +272,7 @@ class DefaultOverrides { /** * Set all non-scripted waves to use the selected battle type. - * + * * Ignored if set to {@linkcode BattleType.TRAINER} and `DISABLE_STANDARD_TRAINERS_OVERRIDE` is `true`. */ readonly BATTLE_TYPE_OVERRIDE: Exclude | null = null; @@ -298,4 +298,4 @@ export type RandomTrainerOverride = { } /** The type of the {@linkcode DefaultOverrides} class */ -export type OverridesType = typeof DefaultOverrides; \ No newline at end of file +export type OverridesType = typeof DefaultOverrides; diff --git a/src/phase-manager.ts b/src/phase-manager.ts index b4fefe3f2d6..8c22a45758c 100644 --- a/src/phase-manager.ts +++ b/src/phase-manager.ts @@ -12,7 +12,7 @@ import { CheckStatusEffectPhase } from "#app/phases/check-status-effect-phase"; import { CheckSwitchPhase } from "#app/phases/check-switch-phase"; import { CommandPhase } from "#app/phases/command-phase"; import { CommonAnimPhase } from "#app/phases/common-anim-phase"; -import type { Constructor } from "#app/utils/common"; +import { coerceArray, type Constructor } from "#app/utils/common"; import { DamageAnimPhase } from "#app/phases/damage-anim-phase"; import type { DynamicPhaseType } from "#enums/dynamic-phase-type"; import { EggHatchPhase } from "#app/phases/egg-hatch-phase"; @@ -438,9 +438,7 @@ export class PhaseManager { * @returns boolean if a targetPhase was found and added */ prependToPhase(phase: Phase | Phase[], targetPhase: PhaseString): boolean { - if (!Array.isArray(phase)) { - phase = [phase]; - } + phase = coerceArray(phase); const target = PHASES[targetPhase]; const targetIndex = this.phaseQueue.findIndex(ph => ph instanceof target); @@ -460,9 +458,7 @@ export class PhaseManager { * @returns `true` if a `targetPhase` was found to append to */ appendToPhase(phase: Phase | Phase[], targetPhase: PhaseString, condition?: (p: Phase) => boolean): boolean { - if (!Array.isArray(phase)) { - phase = [phase]; - } + phase = coerceArray(phase); const target = PHASES[targetPhase]; const targetIndex = this.phaseQueue.findIndex(ph => ph instanceof target && (!condition || condition(ph))); diff --git a/src/phases/add-enemy-buff-modifier-phase.ts b/src/phases/add-enemy-buff-modifier-phase.ts index 185464670d3..218a3a653ff 100644 --- a/src/phases/add-enemy-buff-modifier-phase.ts +++ b/src/phases/add-enemy-buff-modifier-phase.ts @@ -1,8 +1,5 @@ import { ModifierTier } from "#enums/modifier-tier"; -import { - regenerateModifierPoolThresholds, - getEnemyBuffModifierForWave, -} from "#app/modifier/modifier-type"; +import { regenerateModifierPoolThresholds, getEnemyBuffModifierForWave } from "#app/modifier/modifier-type"; import { ModifierPoolType } from "#enums/modifier-pool-type"; import { EnemyPersistentModifier } from "#app/modifier/modifier"; import { Phase } from "#app/phase"; diff --git a/src/phases/command-phase.ts b/src/phases/command-phase.ts index d7264b4aff2..e796f22921c 100644 --- a/src/phases/command-phase.ts +++ b/src/phases/command-phase.ts @@ -149,7 +149,7 @@ export class CommandPhase extends FieldPhase { switch (command) { case Command.TERA: - case Command.FIGHT: + case Command.FIGHT: { let useStruggle = false; const turnMove: TurnMove | undefined = args.length === 2 ? (args[1] as TurnMove) : undefined; if ( @@ -233,7 +233,8 @@ export class CommandPhase extends FieldPhase { ); } break; - case Command.BALL: + } + case Command.BALL: { const notInDex = globalScene .getEnemyField() @@ -337,8 +338,9 @@ export class CommandPhase extends FieldPhase { } } break; + } case Command.POKEMON: - case Command.RUN: + case Command.RUN: { const isSwitch = command === Command.POKEMON; const { currentBattle, arena } = globalScene; const mysteryEncounterFleeAllowed = currentBattle.mysteryEncounter?.fleeAllowed; @@ -445,6 +447,7 @@ export class CommandPhase extends FieldPhase { } } break; + } } if (success) { diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index 5b3b86fec2f..4a61bc736d6 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -135,7 +135,8 @@ export class MovePhase extends BattlePhase { this.showMoveText(); this.showFailedText(); } - return this.end(); + this.end(); + return; } this.pokemon.turnData.acted = true; @@ -310,7 +311,8 @@ export class MovePhase extends BattlePhase { if (fail) { this.showMoveText(); this.showFailedText(); - return this.end(); + this.end(); + return; } } diff --git a/src/phases/pokemon-anim-phase.ts b/src/phases/pokemon-anim-phase.ts index b1a21446996..314bddb981d 100644 --- a/src/phases/pokemon-anim-phase.ts +++ b/src/phases/pokemon-anim-phase.ts @@ -53,7 +53,8 @@ export class PokemonAnimPhase extends BattlePhase { private doSubstituteAddAnim(): void { const substitute = this.pokemon.getTag(SubstituteTag); if (isNullOrUndefined(substitute)) { - return this.end(); + this.end(); + return; } const getSprite = () => { @@ -116,12 +117,14 @@ export class PokemonAnimPhase extends BattlePhase { private doSubstitutePreMoveAnim(): void { if (this.fieldAssets.length !== 1) { - return this.end(); + this.end(); + return; } const subSprite = this.fieldAssets[0]; if (subSprite === undefined) { - return this.end(); + this.end(); + return; } globalScene.tweens.add({ @@ -145,12 +148,14 @@ export class PokemonAnimPhase extends BattlePhase { private doSubstitutePostMoveAnim(): void { if (this.fieldAssets.length !== 1) { - return this.end(); + this.end(); + return; } const subSprite = this.fieldAssets[0]; if (subSprite === undefined) { - return this.end(); + this.end(); + return; } globalScene.tweens.add({ @@ -174,12 +179,14 @@ export class PokemonAnimPhase extends BattlePhase { private doSubstituteRemoveAnim(): void { if (this.fieldAssets.length !== 1) { - return this.end(); + this.end(); + return; } const subSprite = this.fieldAssets[0]; if (subSprite === undefined) { - return this.end(); + this.end(); + return; } const getSprite = () => { @@ -244,12 +251,14 @@ export class PokemonAnimPhase extends BattlePhase { private doCommanderApplyAnim(): void { if (!globalScene.currentBattle?.double) { - return this.end(); + this.end(); + return; } const dondozo = this.pokemon.getAlly(); if (dondozo?.species?.speciesId !== SpeciesId.DONDOZO) { - return this.end(); + this.end(); + return; } const tatsugiriX = this.pokemon.x + this.pokemon.getSprite().x; @@ -329,7 +338,8 @@ export class PokemonAnimPhase extends BattlePhase { const tatsugiri = this.pokemon.getAlly(); if (isNullOrUndefined(tatsugiri)) { console.warn("Aborting COMMANDER_REMOVE anim: Tatsugiri is undefined"); - return this.end(); + this.end(); + return; } const tatsuSprite = globalScene.addPokemonSprite( diff --git a/src/phases/pokemon-transform-phase.ts b/src/phases/pokemon-transform-phase.ts index ab0949c42b9..65fccb24d99 100644 --- a/src/phases/pokemon-transform-phase.ts +++ b/src/phases/pokemon-transform-phase.ts @@ -29,7 +29,8 @@ export class PokemonTransformPhase extends PokemonPhase { const target = globalScene.getField(true).find(p => p.getBattlerIndex() === this.targetIndex); if (!target) { - return this.end(); + this.end(); + return; } user.summonData.speciesForm = target.getSpeciesForm(); diff --git a/src/phases/quiet-form-change-phase.ts b/src/phases/quiet-form-change-phase.ts index e6a00c73756..41b691844bf 100644 --- a/src/phases/quiet-form-change-phase.ts +++ b/src/phases/quiet-form-change-phase.ts @@ -29,7 +29,8 @@ export class QuietFormChangePhase extends BattlePhase { super.start(); 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); diff --git a/src/pipelines/glsl/fieldSpriteFragShader.frag b/src/pipelines/glsl/fieldSpriteFragShader.frag index e79dea86fe9..0eb95ece5e3 100644 --- a/src/pipelines/glsl/fieldSpriteFragShader.frag +++ b/src/pipelines/glsl/fieldSpriteFragShader.frag @@ -51,7 +51,7 @@ float hue2rgb(float f1, float f2, float hue) { vec3 rgb2hsl(vec3 color) { vec3 hsl; - + float fmin = min(min(color.r, color.g), color.b); float fmax = max(max(color.r, color.g), color.b); float delta = fmax - fmin; @@ -66,7 +66,7 @@ vec3 rgb2hsl(vec3 color) { hsl.y = delta / (fmax + fmin); else hsl.y = delta / (2.0 - fmax - fmin); - + float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta; float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta; float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta; @@ -89,24 +89,24 @@ vec3 rgb2hsl(vec3 color) { vec3 hsl2rgb(vec3 hsl) { vec3 rgb; - + if (hsl.y == 0.0) rgb = vec3(hsl.z); else { float f2; - + if (hsl.z < 0.5) f2 = hsl.z * (1.0 + hsl.y); else f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z); - + float f1 = 2.0 * hsl.z - f2; - + rgb.r = hue2rgb(f1, f2, hsl.x + (1.0/3.0)); rgb.g = hue2rgb(f1, f2, hsl.x); rgb.b = hue2rgb(f1, f2, hsl.x - (1.0/3.0)); } - + return rgb; } diff --git a/src/pipelines/glsl/spriteFragShader.frag b/src/pipelines/glsl/spriteFragShader.frag index 03f8c8c27bc..9328cc4d96d 100644 --- a/src/pipelines/glsl/spriteFragShader.frag +++ b/src/pipelines/glsl/spriteFragShader.frag @@ -83,7 +83,7 @@ vec3 rgb2hsl(vec3 color) { hsl.y = delta / (fmax + fmin); else hsl.y = delta / (2.0 - fmax - fmin); - + float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta; float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta; float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta; @@ -106,24 +106,24 @@ vec3 rgb2hsl(vec3 color) { vec3 hsl2rgb(vec3 hsl) { vec3 rgb; - + if (hsl.y == 0.0) rgb = vec3(hsl.z); else { float f2; - + if (hsl.z < 0.5) f2 = hsl.z * (1.0 + hsl.y); else f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z); - + float f1 = 2.0 * hsl.z - f2; - + rgb.r = hue2rgb(f1, f2, hsl.x + (1.0/3.0)); rgb.g = hue2rgb(f1, f2, hsl.x); rgb.b= hue2rgb(f1, f2, hsl.x - (1.0/3.0)); } - + return rgb; } diff --git a/src/plugins/cache-busted-loader-plugin.ts b/src/plugins/cache-busted-loader-plugin.ts index e5b1abb5903..4ae9b352ae3 100644 --- a/src/plugins/cache-busted-loader-plugin.ts +++ b/src/plugins/cache-busted-loader-plugin.ts @@ -1,10 +1,8 @@ +import { coerceArray } from "#app/utils/common"; + let manifest: object; export default class CacheBustedLoaderPlugin extends Phaser.Loader.LoaderPlugin { - constructor(scene: Phaser.Scene) { - super(scene); - } - get manifest() { return manifest; } @@ -14,9 +12,7 @@ export default class CacheBustedLoaderPlugin extends Phaser.Loader.LoaderPlugin } addFile(file): void { - if (!Array.isArray(file)) { - file = [file]; - } + file = coerceArray(file); file.forEach(item => { if (manifest) { diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 515d9aec528..8ca9005096f 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -174,7 +174,24 @@ export async function initI18n(): Promise { "es-MX": ["es-ES", "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: { loadPath(lng: string, [ns]: string[]) { let fileName: string; diff --git a/src/plugins/vite/vite-minify-json-plugin.ts b/src/plugins/vite/vite-minify-json-plugin.ts index f14fdf7042d..38f299eea50 100644 --- a/src/plugins/vite/vite-minify-json-plugin.ts +++ b/src/plugins/vite/vite-minify-json-plugin.ts @@ -41,9 +41,9 @@ export function minifyJsonPlugin(basePath: string | string[], recursive?: boolea }, async closeBundle() { console.log("Minifying JSON files..."); - const basePathes = Array.isArray(basePath) ? basePath : [basePath]; + const basePaths = Array.isArray(basePath) ? basePath : [basePath]; - basePathes.forEach(basePath => { + basePaths.forEach(basePath => { const baseDir = path.resolve(buildDir, basePath); if (fs.existsSync(baseDir)) { applyToDir(baseDir, recursive); diff --git a/src/scene-base.ts b/src/scene-base.ts index 430a9bc8aac..ccea373fca0 100644 --- a/src/scene-base.ts +++ b/src/scene-base.ts @@ -1,3 +1,5 @@ +import { coerceArray } from "#app/utils/common"; + export const legacyCompatibleImages: string[] = []; export class SceneBase extends Phaser.Scene { @@ -88,9 +90,7 @@ export class SceneBase extends Phaser.Scene { } else { folder += "/"; } - if (!Array.isArray(filenames)) { - filenames = [filenames]; - } + filenames = coerceArray(filenames); for (const f of filenames as string[]) { this.load.audio(folder + key, this.getCachedUrl(`audio/${folder}${f}`)); } diff --git a/src/system/settings/settings-gamepad.ts b/src/system/settings/settings-gamepad.ts index d39d5cf5a41..8a28e9fbf14 100644 --- a/src/system/settings/settings-gamepad.ts +++ b/src/system/settings/settings-gamepad.ts @@ -32,7 +32,10 @@ const pressAction = i18next.t("settings:pressActionToAssign"); export const settingGamepadOptions = { [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_Down]: [`KEY ${Button.DOWN.toString()}`, pressAction], [SettingGamepad.Button_Left]: [`KEY ${Button.LEFT.toString()}`, pressAction], diff --git a/src/system/settings/settings.ts b/src/system/settings/settings.ts index 69abc669870..ca5395a5af7 100644 --- a/src/system/settings/settings.ts +++ b/src/system/settings/settings.ts @@ -959,7 +959,7 @@ export function setSetting(setting: string, value: number): boolean { }, { label: "Türkçe (Needs Help)", - handler: () => changeLocaleHandler("tr") + handler: () => changeLocaleHandler("tr"), }, { label: "Русский (Needs Help)", @@ -967,11 +967,11 @@ export function setSetting(setting: string, value: number): boolean { }, { label: "Dansk (Needs Help)", - handler: () => changeLocaleHandler("da") + handler: () => changeLocaleHandler("da"), }, { label: "Română (Needs Help)", - handler: () => changeLocaleHandler("ro") + handler: () => changeLocaleHandler("ro"), }, { label: i18next.t("settings:back"), diff --git a/src/ui/abstact-option-select-ui-handler.ts b/src/ui/abstact-option-select-ui-handler.ts index 07609648a4e..e1263bc088c 100644 --- a/src/ui/abstact-option-select-ui-handler.ts +++ b/src/ui/abstact-option-select-ui-handler.ts @@ -56,10 +56,6 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { protected defaultTextStyle: TextStyle = TextStyle.WINDOW; protected textContent: string; - constructor(mode: UiMode | null) { - super(mode); - } - abstract getWindowWidth(): number; getWindowHeight(): number { diff --git a/src/ui/admin-ui-handler.ts b/src/ui/admin-ui-handler.ts index 67ae3118863..c8c8e43802b 100644 --- a/src/ui/admin-ui-handler.ts +++ b/src/ui/admin-ui-handler.ts @@ -69,7 +69,7 @@ export default class AdminUiHandler extends FormModalUiHandler { case AdminMode.SEARCH: inputFieldConfigs.push({ label: "Username" }); break; - case AdminMode.ADMIN: + case AdminMode.ADMIN: { const adminResult = this.adminResult ?? { username: "", discordId: "", @@ -90,6 +90,7 @@ export default class AdminUiHandler extends FormModalUiHandler { inputFieldConfigs.push({ label: "Last played", isReadOnly: true }); inputFieldConfigs.push({ label: "Registered", isReadOnly: true }); break; + } } return inputFieldConfigs; } diff --git a/src/ui/daily-run-scoreboard.ts b/src/ui/daily-run-scoreboard.ts index 076a782908b..e19882b09cc 100644 --- a/src/ui/daily-run-scoreboard.ts +++ b/src/ui/daily-run-scoreboard.ts @@ -169,12 +169,13 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container { entryContainer.add(scoreLabel); switch (this.category) { - case ScoreboardCategory.DAILY: + case ScoreboardCategory.DAILY: { const waveLabel = addTextObject(68, 0, wave, TextStyle.WINDOW, { fontSize: "54px", }); entryContainer.add(waveLabel); break; + } case ScoreboardCategory.WEEKLY: scoreLabel.x -= 16; break; diff --git a/src/ui/egg-gacha-ui-handler.ts b/src/ui/egg-gacha-ui-handler.ts index d6b1b630a05..1b1aed91203 100644 --- a/src/ui/egg-gacha-ui-handler.ts +++ b/src/ui/egg-gacha-ui-handler.ts @@ -131,7 +131,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { gachaInfoContainer.add(gachaUpLabel); switch (gachaType as GachaType) { - case GachaType.LEGENDARY: + case GachaType.LEGENDARY: { if (["de", "es-ES"].includes(currentLanguage)) { gachaUpLabel.setAlign("center"); gachaUpLabel.setY(0); @@ -152,6 +152,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { gachaInfoContainer.add(pokemonIcon); break; + } case GachaType.MOVE: if (["de", "es-ES", "fr", "pt-BR", "ru"].includes(currentLanguage)) { gachaUpLabel.setAlign("center"); @@ -623,11 +624,12 @@ export default class EggGachaUiHandler extends MessageUiHandler { updateGachaInfo(gachaType: GachaType): void { const infoContainer = this.gachaInfoContainers[gachaType]; switch (gachaType as GachaType) { - case GachaType.LEGENDARY: + case GachaType.LEGENDARY: { const species = getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(new Date().getTime())); const pokemonIcon = infoContainer.getAt(1) as Phaser.GameObjects.Sprite; pokemonIcon.setTexture(species.getIconAtlasKey(), species.getIconId(false)); break; + } } } diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index e68cc706aba..5ab1d4f9e96 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -686,7 +686,7 @@ export default class MenuUiHandler extends MessageUiHandler { error = true; } break; - case MenuOptions.LOG_OUT: + case MenuOptions.LOG_OUT: { success = true; const doLogout = () => { ui.setMode(UiMode.LOADING, { @@ -718,6 +718,7 @@ export default class MenuUiHandler extends MessageUiHandler { doLogout(); } break; + } } } else if (button === Button.CANCEL) { success = true; diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index a2dfe83e996..8e197c08ef3 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -1385,7 +1385,7 @@ export default class PartyUiHandler extends MessageUiHandler { case PartyOption.MOVE_1: case PartyOption.MOVE_2: case PartyOption.MOVE_3: - case PartyOption.MOVE_4: + case PartyOption.MOVE_4: { const move = pokemon.moveset[option - PartyOption.MOVE_1]; if (this.showMovePp) { const maxPP = move.getMovePp(); @@ -1395,7 +1395,8 @@ export default class PartyUiHandler extends MessageUiHandler { optionName = move.getName(); } break; - default: + } + default: { const formChangeItemModifiers = this.getFormChangeItemsModifiers(pokemon); if (formChangeItemModifiers && option >= PartyOption.FORM_CHANGE_ITEM) { const modifier = formChangeItemModifiers[option - PartyOption.FORM_CHANGE_ITEM]; @@ -1410,6 +1411,7 @@ export default class PartyUiHandler extends MessageUiHandler { } } break; + } } } else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER) { const learnableLevelMoves = pokemon.getLearnableLevelMoves(); diff --git a/src/ui/pokemon-icon-anim-handler.ts b/src/ui/pokemon-icon-anim-handler.ts index 253ccbe3623..8a206167a94 100644 --- a/src/ui/pokemon-icon-anim-handler.ts +++ b/src/ui/pokemon-icon-anim-handler.ts @@ -1,5 +1,5 @@ import { globalScene } from "#app/global-scene"; -import { fixedInt } from "#app/utils/common"; +import { fixedInt, coerceArray } from "#app/utils/common"; export enum PokemonIconAnimMode { NONE, @@ -49,9 +49,7 @@ export default class PokemonIconAnimHandler { } addOrUpdate(icons: PokemonIcon | PokemonIcon[], mode: PokemonIconAnimMode): void { - if (!Array.isArray(icons)) { - icons = [icons]; - } + icons = coerceArray(icons); for (const i of icons) { if (this.icons.has(i) && this.icons.get(i) === mode) { continue; @@ -66,9 +64,7 @@ export default class PokemonIconAnimHandler { } remove(icons: PokemonIcon | PokemonIcon[]): void { - if (!Array.isArray(icons)) { - icons = [icons]; - } + icons = coerceArray(icons); for (const i of icons) { if (this.toggled) { const icon = this.icons.get(i); diff --git a/src/ui/run-info-ui-handler.ts b/src/ui/run-info-ui-handler.ts index a4de2215fa4..78ab4a40407 100644 --- a/src/ui/run-info-ui-handler.ts +++ b/src/ui/run-info-ui-handler.ts @@ -567,7 +567,7 @@ export default class RunInfoUiHandler extends UiHandler { case GameModes.SPLICED_ENDLESS: modeText.appendText(`${i18next.t("gameMode:endlessSpliced")}`, false); break; - case GameModes.CHALLENGE: + case GameModes.CHALLENGE: { modeText.appendText(`${i18next.t("gameMode:challenge")}`, false); modeText.appendText(`${i18next.t("runHistory:challengeRules")}: `); modeText.setWrapMode(1); // wrap by word @@ -582,6 +582,7 @@ export default class RunInfoUiHandler extends UiHandler { } } break; + } case GameModes.ENDLESS: modeText.appendText(`${i18next.t("gameMode:endless")}`, false); break; @@ -687,7 +688,7 @@ export default class RunInfoUiHandler extends UiHandler { case Challenges.SINGLE_GENERATION: rules.push(i18next.t(`runHistory:challengeMonoGen${this.runInfo.challenges[i].value}`)); break; - case Challenges.SINGLE_TYPE: + case Challenges.SINGLE_TYPE: { const typeRule = PokemonType[this.runInfo.challenges[i].value - 1]; const typeTextColor = `[color=${TypeColor[typeRule]}]`; const typeShadowColor = `[shadow=${TypeShadow[typeRule]}]`; @@ -695,16 +696,18 @@ export default class RunInfoUiHandler extends UiHandler { typeTextColor + typeShadowColor + i18next.t(`pokemonInfo:Type.${typeRule}`)! + "[/color]" + "[/shadow]"; rules.push(typeText); break; + } case Challenges.INVERSE_BATTLE: rules.push(i18next.t("challenges:inverseBattle.shortName")); break; - default: + default: { const localisationKey = Challenges[this.runInfo.challenges[i].id] .split("_") .map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase())) .join(""); rules.push(i18next.t(`challenges:${localisationKey}.name`)); break; + } } } } diff --git a/src/ui/settings/abstract-control-settings-ui-handler.ts b/src/ui/settings/abstract-control-settings-ui-handler.ts index 495a0f68540..e3631c062df 100644 --- a/src/ui/settings/abstract-control-settings-ui-handler.ts +++ b/src/ui/settings/abstract-control-settings-ui-handler.ts @@ -126,6 +126,11 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler ); 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"); iconAction.setOrigin(0, -0.1); 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"); 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; 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"); 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; const resetText = addTextObject(0, 0, i18next.t("settings:reset"), TextStyle.SETTINGS_LABEL); diff --git a/src/ui/settings/abstract-settings-ui-handler.ts b/src/ui/settings/abstract-settings-ui-handler.ts index 1fb4b6d34dc..6db9840a818 100644 --- a/src/ui/settings/abstract-settings-ui-handler.ts +++ b/src/ui/settings/abstract-settings-ui-handler.ts @@ -94,7 +94,7 @@ export default class AbstractSettingsUiHandler extends MessageUiHandler { const iconCancel = globalScene.add.sprite(0, 0, "keyboard"); 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; const cancelText = addTextObject(0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL); @@ -332,12 +332,13 @@ export default class AbstractSettingsUiHandler extends MessageUiHandler { case Button.CYCLE_SHINY: success = this.navigationContainer.navigate(button); break; - case Button.ACTION: + case Button.ACTION: { const setting: Setting = this.settings[cursor]; if (setting?.activatable) { success = this.activateSetting(setting); } break; + } } } diff --git a/src/ui/settings/move-touch-controls-handler.ts b/src/ui/settings/move-touch-controls-handler.ts index 44377c8c2ab..f684d27f748 100644 --- a/src/ui/settings/move-touch-controls-handler.ts +++ b/src/ui/settings/move-touch-controls-handler.ts @@ -98,7 +98,7 @@ export default class MoveTouchControlsHandler {
${i18next.t("settings:touchCancel")}
-
+
${i18next.t("settings:orientation")} ${this.isLandscapeMode ? i18next.t("settings:landscape") : i18next.t("settings:portrait")} diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 88f881746bb..7c8b05b6f76 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -1763,7 +1763,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } else if (this.randomCursorObj.visible) { switch (button) { - case Button.ACTION: + case Button.ACTION: { if (this.starterSpecies.length >= 6) { error = true; break; @@ -1815,6 +1815,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } }); break; + } case Button.UP: this.randomCursorObj.setVisible(false); this.filterBarCursor = this.filterBar.numFilters - 1; diff --git a/src/ui/test-dialogue-ui-handler.ts b/src/ui/test-dialogue-ui-handler.ts index 9ecf1641e7b..b1e5047955a 100644 --- a/src/ui/test-dialogue-ui-handler.ts +++ b/src/ui/test-dialogue-ui-handler.ts @@ -10,10 +10,6 @@ import { UiMode } from "#enums/ui-mode"; export default class TestDialogueUiHandler extends FormModalUiHandler { keys: string[]; - constructor(mode) { - super(mode); - } - setup() { super.setup(); diff --git a/src/utils/common.ts b/src/utils/common.ts index 56fa3b5c698..c8b37c4e3fd 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -611,3 +611,12 @@ export function getShinyDescriptor(variant: Variant): string { return i18next.t("common:commonShiny"); } } + +/** + * If the input isn't already an array, turns it into one. + * @returns An array with the same type as the type of the input + */ +export function coerceArray(input: T): T extends any[] ? T : [T]; +export function coerceArray(input: T): T | [T] { + return Array.isArray(input) ? input : [input]; +} diff --git a/test/moves/last_respects.test.ts b/test/moves/last_respects.test.ts index b2eb4c6695b..08256d3ebfb 100644 --- a/test/moves/last_respects.test.ts +++ b/test/moves/last_respects.test.ts @@ -164,15 +164,13 @@ describe("Moves - Last Respects", () => { await game.toNextWave(); expect(game.scene.currentBattle.enemyFaints).toBe(0); + game.removeEnemyHeldItems(); + game.move.select(MoveId.LAST_RESPECTS); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); await game.phaseInterceptor.to("MoveEndPhase"); - const enemy = game.field.getEnemyPokemon(); - const player = game.field.getPlayerPokemon(); - const items = `Player items: ${player.getHeldItems()} | Enemy Items: ${enemy.getHeldItems()} |`; - - expect(move.calculateBattlePower, items).toHaveLastReturnedWith(50); + expect(move.calculateBattlePower).toHaveLastReturnedWith(50); }); it("should reset playerFaints count if we enter new trainer battle", async () => { diff --git a/test/testUtils/helpers/moveHelper.ts b/test/testUtils/helpers/moveHelper.ts index 1b799e12da7..0f87fa9a4c1 100644 --- a/test/testUtils/helpers/moveHelper.ts +++ b/test/testUtils/helpers/moveHelper.ts @@ -12,6 +12,7 @@ import { UiMode } from "#enums/ui-mode"; import { getMovePosition } from "#test/testUtils/gameManagerUtils"; import { GameManagerHelper } from "#test/testUtils/helpers/gameManagerHelper"; import { vi } from "vitest"; +import { coerceArray } from "#app/utils/common"; /** * Helper to handle a Pokemon's move @@ -157,9 +158,7 @@ export class MoveHelper extends GameManagerHelper { * @param moveset - The {@linkcode MoveId} (single or array) to change the Pokemon's moveset to. */ public changeMoveset(pokemon: Pokemon, moveset: MoveId | MoveId[]): void { - if (!Array.isArray(moveset)) { - moveset = [moveset]; - } + moveset = coerceArray(moveset); pokemon.moveset = []; moveset.forEach(move => { pokemon.moveset.push(new PokemonMove(move)); diff --git a/test/testUtils/helpers/overridesHelper.ts b/test/testUtils/helpers/overridesHelper.ts index c01acbe0f2e..9869c7450e2 100644 --- a/test/testUtils/helpers/overridesHelper.ts +++ b/test/testUtils/helpers/overridesHelper.ts @@ -14,7 +14,7 @@ import { StatusEffect } from "#enums/status-effect"; import type { WeatherType } from "#enums/weather-type"; import { expect, vi } from "vitest"; import { GameManagerHelper } from "./gameManagerHelper"; -import { shiftCharCodes } from "#app/utils/common"; +import { coerceArray, shiftCharCodes } from "#app/utils/common"; import type { RandomTrainerOverride } from "#app/overrides"; import type { BattleType } from "#enums/battle-type"; @@ -202,9 +202,7 @@ export class OverridesHelper extends GameManagerHelper { */ public moveset(moveset: MoveId | MoveId[]): this { vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue(moveset); - if (!Array.isArray(moveset)) { - moveset = [moveset]; - } + moveset = coerceArray(moveset); const movesetStr = moveset.map(moveId => MoveId[moveId]).join(", "); this.log(`Player Pokemon moveset set to ${movesetStr} (=[${moveset.join(", ")}])!`); return this; @@ -382,9 +380,7 @@ export class OverridesHelper extends GameManagerHelper { */ public enemyMoveset(moveset: MoveId | MoveId[]): this { vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(moveset); - if (!Array.isArray(moveset)) { - moveset = [moveset]; - } + moveset = coerceArray(moveset); const movesetStr = moveset.map(moveId => MoveId[moveId]).join(", "); this.log(`Enemy Pokemon moveset set to ${movesetStr} (=[${moveset.join(", ")}])!`); return this; diff --git a/test/testUtils/mocks/mocksContainer/mockContainer.ts b/test/testUtils/mocks/mocksContainer/mockContainer.ts index f1371643ce3..d31165bb847 100644 --- a/test/testUtils/mocks/mocksContainer/mockContainer.ts +++ b/test/testUtils/mocks/mocksContainer/mockContainer.ts @@ -1,3 +1,4 @@ +import { coerceArray } from "#app/utils/common"; import type MockTextureManager from "#test/testUtils/mocks/mockTextureManager"; import type { MockGameObject } from "../mockGameObject"; @@ -216,11 +217,7 @@ export default class MockContainer implements MockGameObject { } add(obj: MockGameObject | MockGameObject[]): this { - if (Array.isArray(obj)) { - this.list.push(...obj); - } else { - this.list.push(obj); - } + this.list.push(...coerceArray(obj)); return this; } @@ -232,18 +229,12 @@ export default class MockContainer implements MockGameObject { addAt(obj: MockGameObject | MockGameObject[], index = 0): this { // Adds a Game Object to this Container at the given index. - if (!Array.isArray(obj)) { - obj = [obj]; - } - this.list.splice(index, 0, ...obj); + this.list.splice(index, 0, ...coerceArray(obj)); return this; } remove(obj: MockGameObject | MockGameObject[], destroyChild = false): this { - if (!Array.isArray(obj)) { - obj = [obj]; - } - for (const item of obj) { + for (const item of coerceArray(obj)) { const index = this.list.indexOf(item); if (index !== -1) { this.list.splice(index, 1); diff --git a/test/testUtils/mocks/mocksContainer/mockRectangle.ts b/test/testUtils/mocks/mocksContainer/mockRectangle.ts index 7f54a0e255f..a8eeb370115 100644 --- a/test/testUtils/mocks/mocksContainer/mockRectangle.ts +++ b/test/testUtils/mocks/mocksContainer/mockRectangle.ts @@ -1,3 +1,4 @@ +import { coerceArray } from "#app/utils/common"; import type { MockGameObject } from "../mockGameObject"; export default class MockRectangle implements MockGameObject { @@ -50,11 +51,7 @@ export default class MockRectangle implements MockGameObject { add(obj: MockGameObject | MockGameObject[]): this { // Adds a child to this Game Object. - if (Array.isArray(obj)) { - this.list.push(...obj); - } else { - this.list.push(obj); - } + this.list.push(...coerceArray(obj)); return this; } diff --git a/test/testUtils/mocks/mocksContainer/mockSprite.ts b/test/testUtils/mocks/mocksContainer/mockSprite.ts index df36b3a29fd..ed1f1df6609 100644 --- a/test/testUtils/mocks/mocksContainer/mockSprite.ts +++ b/test/testUtils/mocks/mocksContainer/mockSprite.ts @@ -1,6 +1,8 @@ +import { coerceArray } from "#app/utils/common"; import Phaser from "phaser"; import type { MockGameObject } from "../mockGameObject"; -import Frame = Phaser.Textures.Frame; + +type Frame = Phaser.Textures.Frame; export default class MockSprite implements MockGameObject { private phaserSprite; @@ -204,11 +206,7 @@ export default class MockSprite implements MockGameObject { add(obj: MockGameObject | MockGameObject[]): this { // Adds a child to this Game Object. - if (Array.isArray(obj)) { - this.list.push(...obj); - } else { - this.list.push(obj); - } + this.list.push(...coerceArray(obj)); return this; }