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? - [ ] The PR is self-contained and cannot be split into smaller PRs?
- [ ] Have I provided a clear explanation of the changes? - [ ] Have I provided a clear explanation of the changes?
- [ ] Have I tested the changes manually? - [ ] 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 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 provided screenshots/videos of the changes (if applicable)?
- [ ] Have I made sure that any UI change works for both UI themes (default and legacy)? - [ ] 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" "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 }, "organizeImports": { "enabled": false },
"linter": { "linter": {
"ignore": [ "ignore": [
@ -55,13 +58,13 @@
}, },
"style": { "style": {
"noVar": "error", "noVar": "error",
"useEnumInitializers": "off", "useEnumInitializers": "off", // large enums like Moves/Species would make this cumbersome
"useBlockStatements": "error", "useBlockStatements": "error",
"useConst": "error", "useConst": "error",
"useImportType": "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", "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 "useDefaultParameterLast": "off", // TODO: Fix spots in the codebase where this flag would be triggered, and then enable
"useSingleVarDeclarator": "off", "useSingleVarDeclarator": "off",
"useNodejsImportProtocol": "off", "useNodejsImportProtocol": "off",
@ -70,17 +73,20 @@
}, },
"suspicious": { "suspicious": {
"noDoubleEquals": "error", "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", "noExplicitAny": "off",
"noAssignInExpressions": "off", "noAssignInExpressions": "off",
"noPrototypeBuiltins": "off", "noPrototypeBuiltins": "off",
"noFallthroughSwitchClause": "off", "noFallthroughSwitchClause": "error", // Prevents accidental automatic fallthroughs in switch cases (use disable comment if needed)
"noImplicitAnyLet": "info", // TODO: Refactor and make this an error "noImplicitAnyLet": "warn", // TODO: Refactor and make this an error
"noRedeclare": "off", // TODO: Refactor and make this an error "noRedeclare": "info", // TODO: Refactor and make this an error
"noGlobalIsNan": "off", "noGlobalIsNan": "off",
"noAsyncPromiseExecutor": "warn" // TODO: Refactor and make this an error "noAsyncPromiseExecutor": "warn" // TODO: Refactor and make this an error
}, },
"complexity": { "complexity": {
"noExcessiveCognitiveComplexity": "warn", "noExcessiveCognitiveComplexity": "warn", // TODO: Refactor and make this an error
"useLiteralKeys": "off", "useLiteralKeys": "off",
"noForEach": "off", // Foreach vs for of is not that simple. "noForEach": "off", // Foreach vs for of is not that simple.
"noUselessSwitchCase": "off", // Explicit > Implicit "noUselessSwitchCase": "off", // Explicit > Implicit

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 stylisticTs from "@stylistic/eslint-plugin-ts";
import parser from "@typescript-eslint/parser"; import parser from "@typescript-eslint/parser";
import importX from "eslint-plugin-import-x"; import importX from "eslint-plugin-import-x";
export default [ export default tseslint.config(
{ {
name: "eslint-config", name: "eslint-config",
files: ["src/**/*.{ts,tsx,js,jsx}", "test/**/*.{ts,tsx,js,jsx}"], files: ["src/**/*.{ts,tsx,js,jsx}", "test/**/*.{ts,tsx,js,jsx}"],
@ -14,12 +15,11 @@ export default [
plugins: { plugins: {
"import-x": importX, "import-x": importX,
"@stylistic/ts": stylisticTs, "@stylistic/ts": stylisticTs,
"@typescript-eslint": tseslint, "@typescript-eslint": tseslint.plugin,
}, },
rules: { 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-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 "import-x/extensions": ["error", "never", { json: "always" }], // Enforces no extension for imports unless json
}, },
}, },
@ -33,11 +33,11 @@ export default [
}, },
}, },
plugins: { plugins: {
"@typescript-eslint": tseslint, "@typescript-eslint": tseslint.plugin,
}, },
rules: { 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-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/ "@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 ], [ 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]: { [Species.KYUREM]: {
1: [ 1: [
[ 1, Moves.DRAGON_BREATH ], [ 1, Moves.DRAGON_BREATH ],

View File

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

View File

@ -8618,7 +8618,9 @@ export function initMoves() {
.condition((user, target, move) => !target.summonData?.illusion && !user.summonData?.illusion) .condition((user, target, move) => !target.summonData?.illusion && !user.summonData?.illusion)
// transforming from or into fusion pokemon causes various problems (such as crashes) // transforming from or into fusion pokemon causes various problems (such as crashes)
.condition((user, target, move) => !target.getTag(BattlerTagType.SUBSTITUTE) && !user.fusionSpecies && !target.fusionSpecies) .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) new AttackMove(Moves.BUBBLE, PokemonType.WATER, MoveCategory.SPECIAL, 40, 100, 30, 10, 0, 1)
.attr(StatStageChangeAttr, [ Stat.SPD ], -1) .attr(StatStageChangeAttr, [ Stat.SPD ], -1)
.target(MoveTarget.ALL_NEAR_ENEMIES), .target(MoveTarget.ALL_NEAR_ENEMIES),

View File

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

View File

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

View File

@ -31,6 +31,7 @@ import ChallengeData from "#app/system/challenge-data";
import TrainerData from "#app/system/trainer-data"; import TrainerData from "#app/system/trainer-data";
import ArenaData from "#app/system/arena-data"; import ArenaData from "#app/system/arena-data";
import { pokerogueApi } from "#app/plugins/api/pokerogue-api"; import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
import { MessagePhase } from "./message-phase";
export class GameOverPhase extends BattlePhase { export class GameOverPhase extends BattlePhase {
private isVictory: boolean; private isVictory: boolean;
@ -122,7 +123,7 @@ export class GameOverPhase extends BattlePhase {
globalScene.disableMenu = true; globalScene.disableMenu = true;
globalScene.time.delayedCall(1000, () => { globalScene.time.delayedCall(1000, () => {
let firstClear = false; let firstClear = false;
if (this.isVictory && newClear) { if (this.isVictory) {
if (globalScene.gameMode.isClassic) { if (globalScene.gameMode.isClassic) {
firstClear = globalScene.validateAchv(achvs.CLASSIC_VICTORY); firstClear = globalScene.validateAchv(achvs.CLASSIC_VICTORY);
globalScene.validateAchv(achvs.UNEVOLVED_CLASSIC_VICTORY); globalScene.validateAchv(achvs.UNEVOLVED_CLASSIC_VICTORY);
@ -226,7 +227,17 @@ export class GameOverPhase extends BattlePhase {
isVictory: this.isVictory, isVictory: this.isVictory,
clientSessionId: clientSessionId, 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) { } else if (this.isVictory) {
globalScene.gameData.offlineNewClear().then(result => { globalScene.gameData.offlineNewClear().then(result => {
doGameOver(result); doGameOver(result);

View File

@ -20,17 +20,20 @@ export class PokerogueSessionSavedataApi extends ApiBase {
* *This is **NOT** the same as {@linkcode clear | clear()}.* * *This is **NOT** the same as {@linkcode clear | clear()}.*
* @param params The {@linkcode NewClearSessionSavedataRequest} to send * @param params The {@linkcode NewClearSessionSavedataRequest} to send
* @returns The raw savedata as `string`. * @returns The raw savedata as `string`.
* @throws Error if the request fails
*/ */
public async newclear(params: NewClearSessionSavedataRequest) { public async newclear(params: NewClearSessionSavedataRequest) {
try { try {
const urlSearchParams = this.toUrlSearchParams(params); const urlSearchParams = this.toUrlSearchParams(params);
const response = await this.doGet(`/savedata/session/newclear?${urlSearchParams}`); const response = await this.doGet(`/savedata/session/newclear?${urlSearchParams}`);
const json = await response.json(); const json = await response.json();
if (response.ok) {
return Boolean(json); return Boolean(json);
}
throw new Error("Could not newclear session!");
} catch (err) { } catch (err) {
console.warn("Could not newclear session!", 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; break;
case SettingKeys.Candy_Upgrade_Display: case SettingKeys.Candy_Upgrade_Display:
globalScene.candyUpgradeDisplay = value; globalScene.candyUpgradeDisplay = value;
break;
case SettingKeys.Money_Format: case SettingKeys.Money_Format:
switch (Setting[index].options[value].value) { switch (Setting[index].options[value].value) {
case "Normal": case "Normal":

View File

@ -176,11 +176,13 @@ export class UiInputs {
return; return;
} }
switch (globalScene.ui?.getMode()) { switch (globalScene.ui?.getMode()) {
case UiMode.MESSAGE: case UiMode.MESSAGE: {
const messageHandler = globalScene.ui.getHandler<MessageUiHandler>(); const messageHandler = globalScene.ui.getHandler<MessageUiHandler>();
if (!messageHandler.pendingPrompt || messageHandler.isTextAnimationInProgress()) { if (!messageHandler.pendingPrompt || messageHandler.isTextAnimationInProgress()) {
return; return;
} }
// biome-ignore lint/suspicious/noFallthroughSwitchClause: falls through to show menu overlay
}
case UiMode.TITLE: case UiMode.TITLE:
case UiMode.COMMAND: case UiMode.COMMAND:
case UiMode.MODIFIER_SELECT: 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 () => { it("should return false and report a warning on ERROR", async () => {
server.use(http.get(`${apiBase}/savedata/session/newclear`, () => HttpResponse.error())); server.use(http.get(`${apiBase}/savedata/session/newclear`, () => HttpResponse.error()));
const success = await sessionSavedataApi.newclear(params); await expect(sessionSavedataApi.newclear(params)).rejects.toThrow("Could not newclear session!");
expect(success).toBe(false);
expect(console.warn).toHaveBeenCalledWith("Could not newclear session!", expect.any(Error)); expect(console.warn).toHaveBeenCalledWith("Could not newclear session!", expect.any(Error));
}); });
}); });

View File

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