Merge branch 'beta' into damo-MysteryEncounterCollection

This commit is contained in:
damocleas 2025-04-30 16:36:05 -04:00 committed by GitHub
commit 204acaaf05
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 109 additions and 34 deletions

View File

@ -65,7 +65,7 @@ Do the reviewers need to do something special in order to test your changes?
- [ ] The PR is self-contained and cannot be split into smaller PRs?
- [ ] Have I provided a clear explanation of the changes?
- [ ] Have I tested the changes manually?
- [ ] Are all unit tests still passing? (`npm run test`)
- [ ] 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 provided screenshots/videos of the changes (if applicable)?
- [ ] Have I made sure that any UI change works for both UI themes (default and legacy)?

View File

@ -38,6 +38,9 @@
"src/data/balance/tms.ts"
]
},
// While it'd be nice to enable consistent sorting, enabling this causes issues due to circular import resolution order
// TODO: Remove if we ever get down to 0 circular imports
"organizeImports": { "enabled": false },
"linter": {
"ignore": [
@ -55,13 +58,13 @@
},
"style": {
"noVar": "error",
"useEnumInitializers": "off",
"useEnumInitializers": "off", // large enums like Moves/Species would make this cumbersome
"useBlockStatements": "error",
"useConst": "error",
"useImportType": "error",
"noNonNullAssertion": "off", // TODO: Turn this on ASAP and fix all non-null assertions
"noNonNullAssertion": "off", // TODO: Turn this on ASAP and fix all non-null assertions in non-test files
"noParameterAssign": "off",
"useExponentiationOperator": "off",
"useExponentiationOperator": "off", // Too typo-prone and easy to mixup with standard multiplication (* vs **)
"useDefaultParameterLast": "off", // TODO: Fix spots in the codebase where this flag would be triggered, and then enable
"useSingleVarDeclarator": "off",
"useNodejsImportProtocol": "off",
@ -70,17 +73,20 @@
},
"suspicious": {
"noDoubleEquals": "error",
// While this would be a nice rule to enable, the current structure of the codebase makes this infeasible
// due to being used for move/ability `args` params and save data-related code.
// This can likely be enabled for all non-utils files once these are eventually reworked, but until then we leave it off.
"noExplicitAny": "off",
"noAssignInExpressions": "off",
"noPrototypeBuiltins": "off",
"noFallthroughSwitchClause": "off",
"noImplicitAnyLet": "info", // TODO: Refactor and make this an error
"noRedeclare": "off", // TODO: Refactor and make this an error
"noFallthroughSwitchClause": "error", // Prevents accidental automatic fallthroughs in switch cases (use disable comment if needed)
"noImplicitAnyLet": "warn", // TODO: Refactor and make this an error
"noRedeclare": "info", // TODO: Refactor and make this an error
"noGlobalIsNan": "off",
"noAsyncPromiseExecutor": "warn" // TODO: Refactor and make this an error
},
"complexity": {
"noExcessiveCognitiveComplexity": "warn",
"noExcessiveCognitiveComplexity": "warn", // TODO: Refactor and make this an error
"useLiteralKeys": "off",
"noForEach": "off", // Foreach vs for of is not that simple.
"noUselessSwitchCase": "off", // Explicit > Implicit

View File

@ -1,9 +1,10 @@
import tseslint from "@typescript-eslint/eslint-plugin";
/** @ts-check */
import tseslint from "typescript-eslint";
import stylisticTs from "@stylistic/eslint-plugin-ts";
import parser from "@typescript-eslint/parser";
import importX from "eslint-plugin-import-x";
export default [
export default tseslint.config(
{
name: "eslint-config",
files: ["src/**/*.{ts,tsx,js,jsx}", "test/**/*.{ts,tsx,js,jsx}"],
@ -14,12 +15,11 @@ export default [
plugins: {
"import-x": importX,
"@stylistic/ts": stylisticTs,
"@typescript-eslint": tseslint,
"@typescript-eslint": tseslint.plugin,
},
rules: {
"prefer-const": "error", // Enforces the use of `const` for variables that are never reassigned
"no-undef": "off", // Disables the rule that disallows the use of undeclared variables (TypeScript handles this)
"no-extra-semi": ["error"], // Disallows unnecessary semicolons for TypeScript-specific syntax
"no-extra-semi": "error", // Disallows unnecessary semicolons for TypeScript-specific syntax
"import-x/extensions": ["error", "never", { json: "always" }], // Enforces no extension for imports unless json
},
},
@ -33,11 +33,11 @@ export default [
},
},
plugins: {
"@typescript-eslint": tseslint,
"@typescript-eslint": tseslint.plugin,
},
rules: {
"@typescript-eslint/no-floating-promises": "error", // Require Promise-like statements to be handled appropriately. - https://typescript-eslint.io/rules/no-floating-promises/
"@typescript-eslint/no-misused-promises": "error", // Disallow Promises in places not designed to handle them. - https://typescript-eslint.io/rules/no-misused-promises/
},
},
];
);

@ -1 +1 @@
Subproject commit 18c1963ef309612a5a7fef76f9879709a7202189
Subproject commit e98f0eb9c2022bc78b53f0444424c636498e725a

View File

@ -19383,6 +19383,44 @@ export const pokemonFormLevelMoves: PokemonSpeciesFormLevelMoves = {
[ 100, Moves.SEED_FLARE ],
]
},
[Species.BASCULIN]: {
1: [
[ 1, Moves.TAIL_WHIP ],
[ 1, Moves.WATER_GUN ],
[ 4, Moves.TACKLE ],
[ 8, Moves.FLAIL ],
[ 12, Moves.AQUA_JET ],
[ 16, Moves.BITE ],
[ 20, Moves.SCARY_FACE ],
[ 24, Moves.HEADBUTT ],
[ 28, Moves.SOAK ],
[ 32, Moves.CRUNCH ],
[ 36, Moves.TAKE_DOWN ],
[ 40, Moves.FINAL_GAMBIT ],
[ 44, Moves.WAVE_CRASH ],
[ 48, Moves.THRASH ],
[ 52, Moves.DOUBLE_EDGE ],
[ 56, Moves.HEAD_SMASH ],
],
2: [
[ 1, Moves.TAIL_WHIP ],
[ 1, Moves.WATER_GUN ],
[ 4, Moves.TACKLE ],
[ 8, Moves.FLAIL ],
[ 12, Moves.AQUA_JET ],
[ 16, Moves.BITE ],
[ 20, Moves.SCARY_FACE ],
[ 24, Moves.HEADBUTT ],
[ 28, Moves.SOAK ],
[ 32, Moves.CRUNCH ],
[ 36, Moves.TAKE_DOWN ],
[ 40, Moves.UPROAR ],
[ 44, Moves.WAVE_CRASH ],
[ 48, Moves.THRASH ],
[ 52, Moves.DOUBLE_EDGE ],
[ 56, Moves.HEAD_SMASH ],
]
},
[Species.KYUREM]: {
1: [
[ 1, Moves.DRAGON_BREATH ],

View File

@ -5724,7 +5724,6 @@ export const tmSpecies: TmSpecies = {
Species.SCOLIPEDE,
Species.WHIMSICOTT,
Species.LILLIGANT,
Species.BASCULIN,
Species.KROOKODILE,
Species.DARMANITAN,
Species.CRUSTLE,
@ -6023,6 +6022,11 @@ export const tmSpecies: TmSpecies = {
Species.HISUI_DECIDUEYE,
Species.PALDEA_TAUROS,
Species.BLOODMOON_URSALUNA,
[
Species.BASCULIN,
"blue-striped",
"red-striped",
]
],
[Moves.LOW_KICK]: [
Species.SANDSHREW,
@ -19335,7 +19339,6 @@ export const tmSpecies: TmSpecies = {
Species.CONKELDURR,
Species.THROH,
Species.SAWK,
Species.BASCULIN,
Species.DARMANITAN,
Species.SCRAFTY,
Species.ESCAVALIER,
@ -19449,6 +19452,11 @@ export const tmSpecies: TmSpecies = {
Species.HISUI_BRAVIARY,
Species.HISUI_DECIDUEYE,
Species.PALDEA_TAUROS,
[
Species.BASCULIN,
"blue-striped",
"red-striped",
],
],
[Moves.SPITE]: [
Species.EKANS,
@ -51341,7 +51349,6 @@ export const tmSpecies: TmSpecies = {
Species.SCOLIPEDE,
Species.WHIMSICOTT,
Species.LILLIGANT,
Species.BASCULIN,
Species.KROOKODILE,
Species.DARMANITAN,
Species.CRUSTLE,
@ -51655,6 +51662,11 @@ export const tmSpecies: TmSpecies = {
Species.HISUI_DECIDUEYE,
Species.PALDEA_TAUROS,
Species.BLOODMOON_URSALUNA,
[
Species.BASCULIN,
"blue-striped",
"red-striped",
],
],
[Moves.NASTY_PLOT]: [
Species.PIKACHU,

View File

@ -652,7 +652,7 @@ export default class Move implements Localizable {
break;
case MoveFlags.IGNORE_ABILITIES:
if (user.hasAbilityWithAttr(MoveAbilityBypassAbAttr)) {
const abilityEffectsIgnored = new BooleanHolder(false);
const abilityEffectsIgnored = new BooleanHolder(false);
applyAbAttrs(MoveAbilityBypassAbAttr, user, abilityEffectsIgnored, false, this);
if (abilityEffectsIgnored.value) {
return true;
@ -3160,7 +3160,7 @@ export class StatStageChangeAttr extends MoveEffectAttr {
private get showMessage () {
return this.options?.showMessage ?? true;
}
/**
* Attempts to change stats of the user or target (depending on value of selfTarget) if conditions are met
* @param user {@linkcode Pokemon} the user of the move
@ -6326,11 +6326,11 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
if (!allyPokemon?.isActive(true) && switchOutTarget.hp) {
globalScene.pushPhase(new BattleEndPhase(false));
if (globalScene.gameMode.hasRandomBiomes || globalScene.isNewBiome()) {
globalScene.pushPhase(new SelectBiomePhase());
}
globalScene.pushPhase(new NewBattlePhase());
}
}
@ -8618,7 +8618,9 @@ export function initMoves() {
.condition((user, target, move) => !target.summonData?.illusion && !user.summonData?.illusion)
// transforming from or into fusion pokemon causes various problems (such as crashes)
.condition((user, target, move) => !target.getTag(BattlerTagType.SUBSTITUTE) && !user.fusionSpecies && !target.fusionSpecies)
.ignoresProtect(),
.ignoresProtect()
// Transforming should copy the target's rage fist hit count
.edgeCase(),
new AttackMove(Moves.BUBBLE, PokemonType.WATER, MoveCategory.SPECIAL, 40, 100, 30, 10, 0, 1)
.attr(StatStageChangeAttr, [ Stat.SPD ], -1)
.target(MoveTarget.ALL_NEAR_ENEMIES),

View File

@ -488,6 +488,7 @@ export abstract class PokemonSpeciesForm {
if (formSpriteKey.startsWith("behemoth")) {
formSpriteKey = "crowned";
}
// biome-ignore lint/suspicious/no-fallthrough: Falls through
default:
ret += `-${formSpriteKey}`;
break;

View File

@ -369,6 +369,7 @@ export function getRandomWeatherType(arena: Arena): WeatherType {
if (hasSun) {
weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 });
}
break;
case Biome.VOLCANO:
weatherPool = [
{

View File

@ -31,6 +31,7 @@ import ChallengeData from "#app/system/challenge-data";
import TrainerData from "#app/system/trainer-data";
import ArenaData from "#app/system/arena-data";
import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
import { MessagePhase } from "./message-phase";
export class GameOverPhase extends BattlePhase {
private isVictory: boolean;
@ -122,7 +123,7 @@ export class GameOverPhase extends BattlePhase {
globalScene.disableMenu = true;
globalScene.time.delayedCall(1000, () => {
let firstClear = false;
if (this.isVictory && newClear) {
if (this.isVictory) {
if (globalScene.gameMode.isClassic) {
firstClear = globalScene.validateAchv(achvs.CLASSIC_VICTORY);
globalScene.validateAchv(achvs.UNEVOLVED_CLASSIC_VICTORY);
@ -226,7 +227,17 @@ export class GameOverPhase extends BattlePhase {
isVictory: this.isVictory,
clientSessionId: clientSessionId,
})
.then(success => doGameOver(!!success));
.then(success => doGameOver(!globalScene.gameMode.isDaily || !!success))
.catch(_err => {
globalScene.clearPhaseQueue();
globalScene.clearPhaseQueueSplice();
globalScene.unshiftPhase(new MessagePhase(i18next.t("menu:serverCommunicationFailed"), 2500));
// force the game to reload after 2 seconds.
setTimeout(() => {
window.location.reload();
}, 2000);
this.end();
});
} else if (this.isVictory) {
globalScene.gameData.offlineNewClear().then(result => {
doGameOver(result);

View File

@ -20,17 +20,20 @@ export class PokerogueSessionSavedataApi extends ApiBase {
* *This is **NOT** the same as {@linkcode clear | clear()}.*
* @param params The {@linkcode NewClearSessionSavedataRequest} to send
* @returns The raw savedata as `string`.
* @throws Error if the request fails
*/
public async newclear(params: NewClearSessionSavedataRequest) {
try {
const urlSearchParams = this.toUrlSearchParams(params);
const response = await this.doGet(`/savedata/session/newclear?${urlSearchParams}`);
const json = await response.json();
return Boolean(json);
if (response.ok) {
return Boolean(json);
}
throw new Error("Could not newclear session!");
} catch (err) {
console.warn("Could not newclear session!", err);
return false;
throw new Error("Could not newclear session!");
}
}

View File

@ -804,6 +804,7 @@ export function setSetting(setting: string, value: number): boolean {
break;
case SettingKeys.Candy_Upgrade_Display:
globalScene.candyUpgradeDisplay = value;
break;
case SettingKeys.Money_Format:
switch (Setting[index].options[value].value) {
case "Normal":

View File

@ -176,11 +176,13 @@ export class UiInputs {
return;
}
switch (globalScene.ui?.getMode()) {
case UiMode.MESSAGE:
case UiMode.MESSAGE: {
const messageHandler = globalScene.ui.getHandler<MessageUiHandler>();
if (!messageHandler.pendingPrompt || messageHandler.isTextAnimationInProgress()) {
return;
}
// biome-ignore lint/suspicious/noFallthroughSwitchClause: falls through to show menu overlay
}
case UiMode.TITLE:
case UiMode.COMMAND:
case UiMode.MODIFIER_SELECT:

View File

@ -57,9 +57,7 @@ describe("Pokerogue Session Savedata API", () => {
it("should return false and report a warning on ERROR", async () => {
server.use(http.get(`${apiBase}/savedata/session/newclear`, () => HttpResponse.error()));
const success = await sessionSavedataApi.newclear(params);
expect(success).toBe(false);
await expect(sessionSavedataApi.newclear(params)).rejects.toThrow("Could not newclear session!");
expect(console.warn).toHaveBeenCalledWith("Could not newclear session!", expect.any(Error));
});
});

View File

@ -7,7 +7,7 @@
"esModuleInterop": true,
"strictNullChecks": true,
"sourceMap": false,
"strict": false,
"strict": false, // TODO: Enable this eventually
"rootDir": ".",
"baseUrl": "./src",
"paths": {