Compare commits

..

1 Commits

Author SHA1 Message Date
Bertie690
f5c79c96a6
Merge d776df4b21 into 076ef81691 2025-08-13 20:50:45 -05:00
12 changed files with 74 additions and 77 deletions

View File

@ -104,7 +104,6 @@ import {
getLuckString,
getLuckTextTint,
getPartyLuckValue,
type ModifierType,
PokemonHeldItemModifierType,
} from "#modifiers/modifier-type";
import { MysteryEncounter } from "#mystery-encounters/mystery-encounter";
@ -1204,9 +1203,7 @@ export class BattleScene extends SceneBase {
this.updateScoreText();
this.scoreText.setVisible(false);
[this.luckLabelText, this.luckText].forEach(t => {
t.setVisible(false);
});
[this.luckLabelText, this.luckText].map(t => t.setVisible(false));
this.newArena(Overrides.STARTING_BIOME_OVERRIDE || BiomeId.TOWN);
@ -1240,7 +1237,8 @@ export class BattleScene extends SceneBase {
Object.values(mp)
.flat()
.map(mt => mt.modifierType)
.filter((mt): mt is ModifierType & Localizable => "localize" in mt && typeof mt.localize === "function"),
.filter(mt => "localize" in mt)
.map(lpb => lpb as unknown as Localizable),
),
];
for (const item of localizable) {
@ -1515,8 +1513,8 @@ export class BattleScene extends SceneBase {
return this.currentBattle;
}
newArena(biome: BiomeId, playerFaints = 0): Arena {
this.arena = new Arena(biome, playerFaints);
newArena(biome: BiomeId, playerFaints?: number): Arena {
this.arena = new Arena(biome, BiomeId[biome].toLowerCase(), playerFaints);
this.eventTarget.dispatchEvent(new NewArenaEvent());
this.arenaBg.pipelineData = {
@ -2713,9 +2711,7 @@ export class BattleScene extends SceneBase {
}
}
this.party.forEach(p => {
p.updateInfo(instant);
});
this.party.map(p => p.updateInfo(instant));
} else {
const args = [this];
if (modifier.shouldApply(...args)) {

View File

@ -74,7 +74,6 @@ import {
randSeedItem,
toDmgValue,
} from "#utils/common";
import { toCamelCase } from "#utils/strings";
import i18next from "i18next";
export class Ability implements Localizable {
@ -110,9 +109,13 @@ export class Ability implements Localizable {
}
localize(): void {
const i18nKey = toCamelCase(AbilityId[this.id]);
const i18nKey = AbilityId[this.id]
.split("_")
.filter(f => f)
.map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()))
.join("") as string;
this.name = this.id ? `${i18next.t(`ability:${i18nKey}.name`)}${this.nameAppend}` : "";
this.name = this.id ? `${i18next.t(`ability:${i18nKey}.name`) as string}${this.nameAppend}` : "";
this.description = this.id ? (i18next.t(`ability:${i18nKey}.description`) as string) : "";
}

View File

@ -1866,16 +1866,17 @@ interface PokemonPrevolutions {
export const pokemonPrevolutions: PokemonPrevolutions = {};
export function initPokemonPrevolutions(): void {
// TODO: Why do we have empty strings in our array?
const megaFormKeys = [ SpeciesFormKey.MEGA, "", SpeciesFormKey.MEGA_X, "", SpeciesFormKey.MEGA_Y ];
for (const [pk, evolutions] of Object.entries(pokemonEvolutions)) {
const megaFormKeys = [ SpeciesFormKey.MEGA, "", SpeciesFormKey.MEGA_X, "", SpeciesFormKey.MEGA_Y ].map(sfk => sfk as string);
const prevolutionKeys = Object.keys(pokemonEvolutions);
prevolutionKeys.forEach(pk => {
const evolutions = pokemonEvolutions[pk];
for (const ev of evolutions) {
if (ev.evoFormKey && megaFormKeys.indexOf(ev.evoFormKey) > -1) {
continue;
}
pokemonPrevolutions[ev.speciesId] = Number.parseInt(pk) as SpeciesId;
}
}
});
}

View File

@ -90,7 +90,7 @@ import type { ChargingMove, MoveAttrMap, MoveAttrString, MoveClassMap, MoveKindS
import type { TurnMove } from "#types/turn-move";
import { BooleanHolder, coerceArray, type Constructor, isNullOrUndefined, NumberHolder, randSeedFloat, randSeedInt, randSeedItem, toDmgValue } from "#utils/common";
import { getEnumValues } from "#utils/enums";
import { toCamelCase, toTitleCase } from "#utils/strings";
import { toTitleCase } from "#utils/strings";
import i18next from "i18next";
import { applyChallenges } from "#utils/challenge-utils";
@ -162,16 +162,10 @@ export abstract class Move implements Localizable {
}
localize(): void {
const i18nKey = toCamelCase(MoveId[this.id])
const i18nKey = MoveId[this.id].split("_").filter(f => f).map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join("") as unknown as string;
if (this.id === MoveId.NONE) {
this.name = "";
this.effect = ""
return;
}
this.name = `${i18next.t(`move:${i18nKey}.name`)}${this.nameAppend}`;
this.effect = `${i18next.t(`move:${i18nKey}.effect`)}${this.nameAppend}`;
this.name = this.id ? `${i18next.t(`move:${i18nKey}.name`)}${this.nameAppend}` : "";
this.effect = this.id ? `${i18next.t(`move:${i18nKey}.effect`)}${this.nameAppend}` : "";
}
/**
@ -5997,8 +5991,8 @@ export class ProtectAttr extends AddBattlerTagAttr {
for (const turnMove of user.getLastXMoves(-1).slice()) {
if (
// Quick & Wide guard increment the Protect counter without using it for fail chance
!(allMoves[turnMove.move].hasAttr("ProtectAttr") ||
[MoveId.QUICK_GUARD, MoveId.WIDE_GUARD].includes(turnMove.move)) ||
!(allMoves[turnMove.move].hasAttr("ProtectAttr") ||
[MoveId.QUICK_GUARD, MoveId.WIDE_GUARD].includes(turnMove.move)) ||
turnMove.result !== MoveResult.SUCCESS
) {
break;

View File

@ -12,7 +12,6 @@ import { WeatherType } from "#enums/weather-type";
import type { Pokemon } from "#field/pokemon";
import type { PokemonFormChangeItemModifier } from "#modifiers/modifier";
import { type Constructor, coerceArray } from "#utils/common";
import { toCamelCase } from "#utils/strings";
import i18next from "i18next";
export abstract class SpeciesFormChangeTrigger {
@ -144,7 +143,11 @@ export class SpeciesFormChangeMoveLearnedTrigger extends SpeciesFormChangeTrigge
super();
this.move = move;
this.known = known;
const moveKey = toCamelCase(MoveId[this.move]);
const moveKey = MoveId[this.move]
.split("_")
.filter(f => f)
.map((f, i) => (i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()))
.join("") as unknown as string;
this.description = known
? i18next.t("pokemonEvolutions:Forms.moveLearned", {
move: i18next.t(`move:${moveKey}.name`),

View File

@ -54,7 +54,7 @@ export class Arena {
public bgm: string;
public ignoreAbilities: boolean;
public ignoringEffectSource: BattlerIndex | null;
public playerTerasUsed = 0;
public playerTerasUsed: number;
/**
* Saves the number of times a party pokemon faints during a arena encounter.
* {@linkcode globalScene.currentBattle.enemyFaints} is the corresponding faint counter for the enemy (this resets every wave).
@ -68,11 +68,12 @@ export class Arena {
public readonly eventTarget: EventTarget = new EventTarget();
constructor(biome: BiomeId, playerFaints = 0) {
constructor(biome: BiomeId, bgm: string, playerFaints = 0) {
this.biomeType = biome;
this.bgm = BiomeId[biome].toLowerCase();
this.bgm = bgm;
this.trainerPool = biomeTrainerPools[biome];
this.updatePoolsForTimeOfDay();
this.playerTerasUsed = 0;
this.playerFaints = playerFaints;
}

View File

@ -447,9 +447,7 @@ export class LoadingScene extends SceneBase {
);
if (!mobile) {
loadingGraphics.forEach(g => {
g.setVisible(false);
});
loadingGraphics.map(g => g.setVisible(false));
}
const intro = this.add.video(0, 0);

View File

@ -121,8 +121,8 @@ export class ModifierBar extends Phaser.GameObjects.Container {
}
updateModifierOverflowVisibility(ignoreLimit: boolean) {
const modifierIcons = this.getAll().reverse() as Phaser.GameObjects.Container[];
for (const modifier of modifierIcons.slice(iconOverflowIndex)) {
const modifierIcons = this.getAll().reverse();
for (const modifier of modifierIcons.map(m => m as Phaser.GameObjects.Container).slice(iconOverflowIndex)) {
modifier.setVisible(ignoreLimit);
}
}

View File

@ -207,12 +207,10 @@ export interface StarterData {
[key: number]: StarterDataEntry;
}
// TODO: Rework into a bitmask
export type TutorialFlags = {
[key in Tutorial]: boolean;
};
export interface TutorialFlags {
[key: string]: boolean;
}
// TODO: Rework into a bitmask
export interface SeenDialogues {
[key: string]: boolean;
}
@ -825,51 +823,52 @@ export class GameData {
return true; // TODO: is `true` the correct return value?
}
private loadGamepadSettings(): void {
Object.values(SettingGamepad).forEach(setting => {
setSettingGamepad(setting, settingGamepadDefaults[setting]);
});
private loadGamepadSettings(): boolean {
Object.values(SettingGamepad)
.map(setting => setting as SettingGamepad)
.forEach(setting => setSettingGamepad(setting, settingGamepadDefaults[setting]));
if (!localStorage.hasOwnProperty("settingsGamepad")) {
return;
return false;
}
const settingsGamepad = JSON.parse(localStorage.getItem("settingsGamepad")!); // TODO: is this bang correct?
for (const setting of Object.keys(settingsGamepad)) {
setSettingGamepad(setting as SettingGamepad, settingsGamepad[setting]);
}
return true; // TODO: is `true` the correct return value?
}
/**
* Save the specified tutorial as having the specified completion status.
* @param tutorial - The {@linkcode Tutorial} whose completion status is being saved
* @param status - The completion status to set
*/
public saveTutorialFlag(tutorial: Tutorial, status: boolean): void {
// Grab the prior save data tutorial
const saveDataKey = getDataTypeKey(GameDataType.TUTORIALS);
const tutorials: TutorialFlags = localStorage.hasOwnProperty(saveDataKey)
? JSON.parse(localStorage.getItem(saveDataKey)!)
: {};
// TODO: We shouldn't be storing this like that
for (const key of Object.values(Tutorial)) {
if (key === tutorial) {
tutorials[key] = status;
} else {
tutorials[key] ??= false;
}
public saveTutorialFlag(tutorial: Tutorial, flag: boolean): boolean {
const key = getDataTypeKey(GameDataType.TUTORIALS);
let tutorials: object = {};
if (localStorage.hasOwnProperty(key)) {
tutorials = JSON.parse(localStorage.getItem(key)!); // TODO: is this bang correct?
}
localStorage.setItem(saveDataKey, JSON.stringify(tutorials));
Object.keys(Tutorial)
.map(t => t as Tutorial)
.forEach(t => {
const key = Tutorial[t];
if (key === tutorial) {
tutorials[key] = flag;
} else {
tutorials[key] ??= false;
}
});
localStorage.setItem(key, JSON.stringify(tutorials));
return true;
}
public getTutorialFlags(): TutorialFlags {
const key = getDataTypeKey(GameDataType.TUTORIALS);
const ret: TutorialFlags = Object.values(Tutorial).reduce((acc, tutorial) => {
acc[Tutorial[tutorial]] = false;
return acc;
}, {} as TutorialFlags);
const ret: TutorialFlags = {};
Object.values(Tutorial)
.map(tutorial => tutorial as Tutorial)
.forEach(tutorial => (ret[Tutorial[tutorial]] = false));
if (!localStorage.hasOwnProperty(key)) {
return ret;

View File

@ -26,7 +26,6 @@ import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text";
import { UiHandler } from "#ui/ui-handler";
import { addWindow } from "#ui/ui-theme";
import { formatFancyLargeNumber, formatLargeNumber, formatMoney, getPlayTimeString } from "#utils/common";
import { toCamelCase } from "#utils/strings";
import i18next from "i18next";
import RoundRectangle from "phaser3-rex-plugins/plugins/roundrectangle";
@ -707,7 +706,10 @@ export class RunInfoUiHandler extends UiHandler {
rules.push(i18next.t("challenges:inverseBattle.shortName"));
break;
default: {
const localizationKey = toCamelCase(Challenges[this.runInfo.challenges[i].id]);
const localizationKey = 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:${localizationKey}.name`));
break;
}

View File

@ -31,7 +31,7 @@ export class TestDialogueUiHandler extends FormModalUiHandler {
// we check for null or undefined here as per above - the typeof is still an object but the value is null so we need to exit out of this and pass the null key
// Return in the format expected by i18next
return middleKey ? `${topKey}:${middleKey.join(".")}.${t}` : `${topKey}:${t}`;
return middleKey ? `${topKey}:${middleKey.map(m => m).join(".")}.${t}` : `${topKey}:${t}`;
}
})
.filter(t => t);

View File

@ -112,7 +112,7 @@ describe("Weird Dream - Mystery Encounter", () => {
it("should transform the new party into new species, 2 at +90/+110, the rest at +40/50 BST", async () => {
await game.runToMysteryEncounter(MysteryEncounterType.WEIRD_DREAM, defaultParty);
const pokemonPrior = scene.getPlayerParty().slice();
const pokemonPrior = scene.getPlayerParty().map(pokemon => pokemon);
const bstsPrior = pokemonPrior.map(species => species.getSpeciesForm().getBaseStatTotal());
await runMysteryEncounterToEnd(game, 1);