Merge branch 'beta' into fix-form-unlocks

This commit is contained in:
NightKev 2025-04-30 19:15:18 -07:00 committed by GitHub
commit 3051c9bb9e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 860 additions and 483 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/
}, },
}, },
]; );

View File

@ -9,7 +9,7 @@
"build": "vite build", "build": "vite build",
"build:beta": "vite build --mode beta", "build:beta": "vite build --mode beta",
"preview": "vite preview", "preview": "vite preview",
"test": "vitest run", "test": "vitest run --no-isolate",
"test:cov": "vitest run --coverage --no-isolate", "test:cov": "vitest run --coverage --no-isolate",
"test:watch": "vitest watch --coverage --no-isolate", "test:watch": "vitest watch --coverage --no-isolate",
"test:silent": "vitest run --silent --no-isolate", "test:silent": "vitest run --silent --no-isolate",

@ -1 +1 @@
Subproject commit 18c1963ef309612a5a7fef76f9879709a7202189 Subproject commit 833dc40ec7409031fcea147ccbc45ec9c0ba0213

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

@ -4,12 +4,19 @@ export type SignatureSpecies = {
[key in string]: (Species | Species[])[]; [key in string]: (Species | Species[])[];
}; };
/* /**
* The signature species for each Gym Leader, Elite Four member, and Champion. * The signature species for each Gym Leader, Elite Four member, and Champion.
* The key is the trainer type, and the value is an array of Species or Species arrays. * The key is the trainer type, and the value is an array of Species or Species arrays.
* This is in a separate const so it can be accessed from other places and not just the trainerConfigs * This is in a separate const so it can be accessed from other places and not just the trainerConfigs
*
* @remarks
* The `Proxy` object allows us to define a handler that will intercept
* the property access and return an empty array if the property does not exist in the object.
*
* This means that accessing `signatureSpecies` will not throw an error if the property does not exist,
* but instead default to an empty array.
*/ */
export const signatureSpecies: SignatureSpecies = { export const signatureSpecies: SignatureSpecies = new Proxy({
// Gym Leaders- Kanto // Gym Leaders- Kanto
BROCK: [Species.ONIX, Species.GEODUDE, [Species.OMANYTE, Species.KABUTO], Species.AERODACTYL], BROCK: [Species.ONIX, Species.GEODUDE, [Species.OMANYTE, Species.KABUTO], Species.AERODACTYL],
MISTY: [Species.STARYU, Species.PSYDUCK, Species.WOOPER, Species.LAPRAS], MISTY: [Species.STARYU, Species.PSYDUCK, Species.WOOPER, Species.LAPRAS],
@ -92,71 +99,8 @@ export const signatureSpecies: SignatureSpecies = {
RYME: [Species.TOXEL, Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], // Tera Ghost Toxel RYME: [Species.TOXEL, Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], // Tera Ghost Toxel
TULIP: [Species.FLABEBE, Species.FLITTLE, Species.RALTS, Species.GIRAFARIG], // Tera Psychic Flabebe TULIP: [Species.FLABEBE, Species.FLITTLE, Species.RALTS, Species.GIRAFARIG], // Tera Psychic Flabebe
GRUSHA: [Species.SWABLU, Species.CETODDLE, Species.SNOM, Species.CUBCHOO], // Tera Ice Swablu GRUSHA: [Species.SWABLU, Species.CETODDLE, Species.SNOM, Species.CUBCHOO], // Tera Ice Swablu
}, {
// Elite Four- Kanto get(target, prop: string) {
LORELEI: [ return target[prop as keyof SignatureSpecies] ?? [];
Species.JYNX, }
[Species.SLOWBRO, Species.GALAR_SLOWBRO], });
Species.LAPRAS,
[Species.CLOYSTER, Species.ALOLA_SANDSLASH],
],
BRUNO: [Species.MACHAMP, Species.HITMONCHAN, Species.HITMONLEE, [Species.GOLEM, Species.ALOLA_GOLEM]],
AGATHA: [Species.GENGAR, [Species.ARBOK, Species.WEEZING], Species.CROBAT, Species.ALOLA_MAROWAK],
LANCE: [Species.DRAGONITE, Species.GYARADOS, Species.AERODACTYL, Species.ALOLA_EXEGGUTOR],
// Elite Four- Johto (Bruno included)
WILL: [Species.XATU, Species.JYNX, [Species.SLOWBRO, Species.SLOWKING], Species.EXEGGUTOR],
KOGA: [[Species.MUK, Species.WEEZING], [Species.VENOMOTH, Species.ARIADOS], Species.CROBAT, Species.TENTACRUEL],
KAREN: [Species.UMBREON, Species.HONCHKROW, Species.HOUNDOOM, Species.WEAVILE],
// Elite Four- Hoenn
SIDNEY: [
[Species.SHIFTRY, Species.CACTURNE],
[Species.SHARPEDO, Species.CRAWDAUNT],
Species.ABSOL,
Species.MIGHTYENA,
],
PHOEBE: [Species.SABLEYE, Species.DUSKNOIR, Species.BANETTE, [Species.DRIFBLIM, Species.MISMAGIUS]],
GLACIA: [Species.GLALIE, Species.WALREIN, Species.FROSLASS, Species.ABOMASNOW],
DRAKE: [Species.ALTARIA, Species.SALAMENCE, Species.FLYGON, Species.KINGDRA],
// Elite Four- Sinnoh
AARON: [[Species.SCIZOR, Species.KLEAVOR], Species.HERACROSS, [Species.VESPIQUEN, Species.YANMEGA], Species.DRAPION],
BERTHA: [Species.WHISCASH, Species.HIPPOWDON, Species.GLISCOR, Species.RHYPERIOR],
FLINT: [
[Species.RAPIDASH, Species.FLAREON],
Species.MAGMORTAR,
[Species.STEELIX, Species.LOPUNNY],
Species.INFERNAPE,
], // Tera Fire Steelix or Lopunny
LUCIAN: [Species.MR_MIME, Species.GALLADE, Species.BRONZONG, [Species.ALAKAZAM, Species.ESPEON]],
// Elite Four- Unova
SHAUNTAL: [Species.COFAGRIGUS, Species.CHANDELURE, Species.GOLURK, Species.JELLICENT],
MARSHAL: [Species.CONKELDURR, Species.MIENSHAO, Species.THROH, Species.SAWK],
GRIMSLEY: [Species.LIEPARD, Species.KINGAMBIT, Species.SCRAFTY, Species.KROOKODILE],
CAITLIN: [Species.MUSHARNA, Species.GOTHITELLE, Species.SIGILYPH, Species.REUNICLUS],
// Elite Four- Kalos
MALVA: [Species.PYROAR, Species.TORKOAL, Species.CHANDELURE, Species.TALONFLAME],
SIEBOLD: [Species.CLAWITZER, Species.GYARADOS, Species.BARBARACLE, Species.STARMIE],
WIKSTROM: [Species.KLEFKI, Species.PROBOPASS, Species.SCIZOR, Species.AEGISLASH],
DRASNA: [Species.DRAGALGE, Species.DRUDDIGON, Species.ALTARIA, Species.NOIVERN],
// Elite Four- Alola
HALA: [Species.HARIYAMA, Species.BEWEAR, Species.CRABOMINABLE, [Species.POLIWRATH, Species.ANNIHILAPE]],
MOLAYNE: [Species.KLEFKI, Species.MAGNEZONE, Species.METAGROSS, Species.ALOLA_DUGTRIO],
OLIVIA: [Species.RELICANTH, Species.CARBINK, Species.ALOLA_GOLEM, Species.LYCANROC],
ACEROLA: [[Species.BANETTE, Species.DRIFBLIM], Species.MIMIKYU, Species.DHELMISE, Species.PALOSSAND],
KAHILI: [[Species.BRAVIARY, Species.MANDIBUZZ], Species.HAWLUCHA, Species.ORICORIO, Species.TOUCANNON],
// Elite Four- Galar
MARNIE_ELITE: [Species.MORPEKO, Species.LIEPARD, [Species.TOXICROAK, Species.SCRAFTY], Species.GRIMMSNARL],
NESSA_ELITE: [Species.GOLISOPOD, [Species.QUAGSIRE, Species.PELIPPER], Species.TOXAPEX, Species.DREDNAW],
BEA_ELITE: [Species.HAWLUCHA, [Species.GRAPPLOCT, Species.SIRFETCHD], Species.FALINKS, Species.MACHAMP],
ALLISTER_ELITE: [Species.DUSKNOIR, [Species.POLTEAGEIST, Species.RUNERIGUS], Species.CURSOLA, Species.GENGAR],
RAIHAN_ELITE: [Species.GOODRA, [Species.TORKOAL, Species.TURTONATOR], Species.FLYGON, Species.ARCHALUDON],
// Elite Four- Paldea
RIKA: [Species.CLODSIRE, [Species.DUGTRIO, Species.DONPHAN], Species.CAMERUPT, Species.WHISCASH], // Tera Ground Clodsire
POPPY: [Species.TINKATON, Species.BRONZONG, Species.CORVIKNIGHT, Species.COPPERAJAH], // Tera Steel Tinkaton
LARRY_ELITE: [Species.FLAMIGO, Species.STARAPTOR, [Species.ALTARIA, Species.TROPIUS], Species.ORICORIO], // Tera Flying Flamigo; random Oricorio
HASSEL: [Species.BAXCALIBUR, [Species.FLAPPLE, Species.APPLETUN], Species.DRAGALGE, Species.NOIVERN], // Tera Dragon Baxcalibur
// Elite Four- BBL
CRISPIN: [Species.BLAZIKEN, Species.MAGMORTAR, [Species.CAMERUPT, Species.TALONFLAME], Species.ROTOM], // Tera Fire Blaziken; Heat Rotom
AMARYS: [Species.METAGROSS, Species.SCIZOR, Species.EMPOLEON, Species.SKARMORY], // Tera Steel Metagross
LACEY: [Species.EXCADRILL, Species.PRIMARINA, [Species.WHIMSICOTT, Species.ALCREMIE], Species.GRANBULL], // Tera Fairy Excadrill
DRAYTON: [Species.ARCHALUDON, Species.DRAGONITE, Species.HAXORUS, Species.SCEPTILE], // Tera Dragon Archaludon
};

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

@ -2463,7 +2463,7 @@ export class StatusEffectAttr extends MoveEffectAttr {
return false; return false;
} }
if (((!pokemon.status || this.overrideStatus) || (pokemon.status.effect === this.effect && moveChance < 0)) if (((!pokemon.status || this.overrideStatus) || (pokemon.status.effect === this.effect && moveChance < 0))
&& pokemon.trySetStatus(this.effect, true, user, this.turnsRemaining, null, this.overrideStatus)) { && pokemon.trySetStatus(this.effect, true, user, this.turnsRemaining, null, this.overrideStatus, false)) {
applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, move, null, false, this.effect); applyPostAttackAbAttrs(ConfusionOnStatusEffectAbAttr, user, target, move, null, false, this.effect);
return true; return true;
} }
@ -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;

File diff suppressed because it is too large Load Diff

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

@ -5529,9 +5529,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
sourcePokemon: Pokemon | null = null, sourcePokemon: Pokemon | null = null,
turnsRemaining = 0, turnsRemaining = 0,
sourceText: string | null = null, sourceText: string | null = null,
overrideStatus?: boolean overrideStatus?: boolean,
quiet = true,
): boolean { ): boolean {
if (!this.canSetStatus(effect, false, overrideStatus, sourcePokemon)) { if (!this.canSetStatus(effect, quiet, overrideStatus, sourcePokemon)) {
return false; return false;
} }
if (this.isFainted() && effect !== StatusEffect.FAINT) { if (this.isFainted() && effect !== StatusEffect.FAINT) {

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

@ -23,18 +23,18 @@ describe("Abilities - Illusion", () => {
beforeEach(() => { beforeEach(() => {
game = new GameManager(phaserGame); game = new GameManager(phaserGame);
game.override.battleStyle("single"); game.override
game.override.enemySpecies(Species.ZORUA); .battleStyle("single")
game.override.enemyAbility(Abilities.ILLUSION); .enemySpecies(Species.ZORUA)
game.override.enemyMoveset(Moves.TACKLE); .enemyAbility(Abilities.ILLUSION)
game.override.enemyHeldItems([{ name: "WIDE_LENS", count: 3 }]); .enemyMoveset(Moves.TACKLE)
.enemyHeldItems([{ name: "WIDE_LENS", count: 3 }])
game.override.moveset([Moves.WORRY_SEED, Moves.SOAK, Moves.TACKLE]); .moveset([Moves.WORRY_SEED, Moves.SOAK, Moves.TACKLE])
game.override.startingHeldItems([{ name: "WIDE_LENS", count: 3 }]); .startingHeldItems([{ name: "WIDE_LENS", count: 3 }]);
}); });
it("creates illusion at the start", async () => { it("creates illusion at the start", async () => {
await game.classicMode.startBattle([Species.ZOROARK, Species.AXEW]); await game.classicMode.startBattle([Species.ZOROARK, Species.FEEBAS]);
const zoroark = game.scene.getPlayerPokemon()!; const zoroark = game.scene.getPlayerPokemon()!;
const zorua = game.scene.getEnemyPokemon()!; const zorua = game.scene.getEnemyPokemon()!;
@ -43,7 +43,7 @@ describe("Abilities - Illusion", () => {
}); });
it("break after receiving damaging move", async () => { it("break after receiving damaging move", async () => {
await game.classicMode.startBattle([Species.AXEW]); await game.classicMode.startBattle([Species.FEEBAS]);
game.move.select(Moves.TACKLE); game.move.select(Moves.TACKLE);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
@ -55,7 +55,7 @@ describe("Abilities - Illusion", () => {
}); });
it("break after getting ability changed", async () => { it("break after getting ability changed", async () => {
await game.classicMode.startBattle([Species.AXEW]); await game.classicMode.startBattle([Species.FEEBAS]);
game.move.select(Moves.WORRY_SEED); game.move.select(Moves.WORRY_SEED);
await game.phaseInterceptor.to("TurnEndPhase"); await game.phaseInterceptor.to("TurnEndPhase");
@ -76,7 +76,7 @@ describe("Abilities - Illusion", () => {
it("causes enemy AI to consider the illusion's type instead of the actual type when considering move effectiveness", async () => { it("causes enemy AI to consider the illusion's type instead of the actual type when considering move effectiveness", async () => {
game.override.enemyMoveset([Moves.FLAMETHROWER, Moves.PSYCHIC, Moves.TACKLE]); game.override.enemyMoveset([Moves.FLAMETHROWER, Moves.PSYCHIC, Moves.TACKLE]);
await game.classicMode.startBattle([Species.ZOROARK, Species.AXEW]); await game.classicMode.startBattle([Species.ZOROARK, Species.FEEBAS]);
const enemy = game.scene.getEnemyPokemon()!; const enemy = game.scene.getEnemyPokemon()!;
const zoroark = game.scene.getPlayerPokemon()!; const zoroark = game.scene.getPlayerPokemon()!;

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": {