Merge branch 'beta' into damo-MysteryEncounterCollection

This commit is contained in:
damocleas 2025-04-28 14:08:20 -04:00 committed by GitHub
commit c7fb032bcd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 144 additions and 83 deletions

View File

@ -1,40 +1,34 @@
# ESLint # Biome
## Key Features ## Key Features
1. **Automation**: 1. **Automation**:
- A pre-commit hook has been added to automatically run ESLint on the added or modified files, ensuring code quality before commits. - A pre-commit hook has been added to automatically run Biome on the added or modified files, ensuring code quality before commits.
2. **Manual Usage**: 2. **Manual Usage**:
- If you prefer not to use the pre-commit hook, you can manually run ESLint to automatically fix issues using the command: - If you prefer not to use the pre-commit hook, you can manually run biome to automatically fix issues using the command:
```sh ```sh
npx eslint --fix . or npm run eslint npx @biomejs/biome --write
``` ```
- Running this command will lint all files in the repository. - Running this command will lint all files in the repository.
3. **GitHub Action**: 3. **GitHub Action**:
- A GitHub Action has been added to automatically run ESLint on every push and pull request, ensuring code quality in the CI/CD pipeline. - A GitHub Action has been added to automatically run Biome on every push and pull request, ensuring code quality in the CI/CD pipeline.
## Summary of ESLint Rules If you are getting linting errors from biome and want to see which files they are coming from, you can find that out by running biome in a way that is configured to only show the errors for that specific rule: ``npx @biomejs/biome lint --only=category/ruleName``
1. **General Rules**: ## Summary of Biome Rules
- **Equality**: Use `===` and `!==` instead of `==` and `!=` (`eqeqeq`).
- **Indentation**: Enforce 2-space indentation (`indent`).
- **Quotes**: Use doublequotes for strings (`quotes`).
- **Variable Declarations**:
- Disallow `var`; use `let` or `const` (`no-var`).
- Prefer `const` for variables that are never reassigned (`prefer-const`).
- **Unused Variables**: Allow unused function parameters but enforce error for other unused variables (`@typescript-eslint/no-unused-vars`).
- **End of Line**: Ensure at least one newline at the end of files (`eol-last`).
- **Curly Braces**: Enforce the use of curly braces for all control statements (`curly`).
- **Brace Style**: Use one true brace style (`1tbs`) for TypeScript-specific syntax (`@typescript-eslint/brace-style`).
2. **TypeScript-Specific Rules**: We use the [recommended ruleset](https://biomejs.dev/linter/rules/) for Biome, with some customizations to better suit our project's needs.
- **Semicolons**:
- Enforce semicolons for TypeScript-specific syntax (`@typescript-eslint/semi`).
- Disallow unnecessary semicolons (`@typescript-eslint/no-extra-semi`).
## Benefits For a complete list of rules and their configurations, refer to the `biome.jsonc` file in the project root.
- **Consistency**: Ensures consistent coding style across the project. Some things to consider:
- **Code Quality**: Helps catch potential errors and improve overall code quality.
- **Readability**: Makes the codebase easier to read and maintain. - We have disabled rules that prioritize style over performance, such as `useTemplate`
- Some rules are currently marked as warnings (`warn`) to allow for gradual refactoring without blocking development. Do not write new code that triggers these warnings.
- The linter is configured to ignore specific files and folders, such as large or complex files that are pending refactors, to improve performance and focus on actionable areas.
Formatting is also handled by Biome. You should not have to worry about manually formatting your code.

View File

@ -1,7 +1,7 @@
{ {
"name": "pokemon-rogue-battle", "name": "pokemon-rogue-battle",
"private": true, "private": true,
"version": "1.8.4", "version": "1.8.5",
"type": "module", "type": "module",
"scripts": { "scripts": {
"start": "vite", "start": "vite",

View File

@ -516,6 +516,34 @@
"trimmed": true, "trimmed": true,
"spriteSourceSize": { "x": 0, "y": 0, "w": 28, "h": 11 }, "spriteSourceSize": { "x": 0, "y": 0, "w": 28, "h": 11 },
"sourceSize": { "w": 28, "h": 11 } "sourceSize": { "w": 28, "h": 11 }
},
"BACK_SLASH.png": {
"frame": { "x": 147, "y": 66, "w": 12, "h": 11 },
"rotated": false,
"trimmed": true,
"spriteSourceSize": { "x": 0, "y": 0, "w": 12, "h": 11 },
"sourceSize": { "w": 12, "h": 11 }
},
"FORWARD_SLASH.png": {
"frame": { "x": 144, "y": 55, "w": 12, "h": 11 },
"rotated": false,
"trimmed": true,
"spriteSourceSize": { "x": 0, "y": 0, "w": 12, "h": 11 },
"sourceSize": { "w": 12, "h": 11 }
},
"COMMA.png": {
"frame": { "x": 144, "y": 44, "w": 12, "h": 11 },
"rotated": false,
"trimmed": true,
"spriteSourceSize": { "x": 0, "y": 0, "w": 12, "h": 11 },
"sourceSize": { "w": 12, "h": 11 }
},
"PERIOD.png": {
"frame": { "x": 143, "y": 22, "w": 11, "h": 11 },
"rotated": false,
"trimmed": true,
"spriteSourceSize": { "x": 0, "y": 0, "w": 11, "h": 11 },
"sourceSize": { "w": 11, "h": 11 }
} }
}, },
"meta": { "meta": {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -31,6 +31,7 @@ const cfg_keyboard_qwerty = {
KEY_X: Phaser.Input.Keyboard.KeyCodes.X, KEY_X: Phaser.Input.Keyboard.KeyCodes.X,
KEY_Y: Phaser.Input.Keyboard.KeyCodes.Y, KEY_Y: Phaser.Input.Keyboard.KeyCodes.Y,
KEY_Z: Phaser.Input.Keyboard.KeyCodes.Z, KEY_Z: Phaser.Input.Keyboard.KeyCodes.Z,
KEY_0: Phaser.Input.Keyboard.KeyCodes.ZERO, KEY_0: Phaser.Input.Keyboard.KeyCodes.ZERO,
KEY_1: Phaser.Input.Keyboard.KeyCodes.ONE, KEY_1: Phaser.Input.Keyboard.KeyCodes.ONE,
KEY_2: Phaser.Input.Keyboard.KeyCodes.TWO, KEY_2: Phaser.Input.Keyboard.KeyCodes.TWO,
@ -41,11 +42,7 @@ const cfg_keyboard_qwerty = {
KEY_7: Phaser.Input.Keyboard.KeyCodes.SEVEN, KEY_7: Phaser.Input.Keyboard.KeyCodes.SEVEN,
KEY_8: Phaser.Input.Keyboard.KeyCodes.EIGHT, KEY_8: Phaser.Input.Keyboard.KeyCodes.EIGHT,
KEY_9: Phaser.Input.Keyboard.KeyCodes.NINE, KEY_9: Phaser.Input.Keyboard.KeyCodes.NINE,
KEY_CTRL: Phaser.Input.Keyboard.KeyCodes.CTRL,
KEY_DEL: Phaser.Input.Keyboard.KeyCodes.DELETE,
KEY_END: Phaser.Input.Keyboard.KeyCodes.END,
KEY_ENTER: Phaser.Input.Keyboard.KeyCodes.ENTER,
KEY_ESC: Phaser.Input.Keyboard.KeyCodes.ESC,
KEY_F1: Phaser.Input.Keyboard.KeyCodes.F1, KEY_F1: Phaser.Input.Keyboard.KeyCodes.F1,
KEY_F2: Phaser.Input.Keyboard.KeyCodes.F2, KEY_F2: Phaser.Input.Keyboard.KeyCodes.F2,
KEY_F3: Phaser.Input.Keyboard.KeyCodes.F3, KEY_F3: Phaser.Input.Keyboard.KeyCodes.F3,
@ -58,24 +55,41 @@ const cfg_keyboard_qwerty = {
KEY_F10: Phaser.Input.Keyboard.KeyCodes.F10, KEY_F10: Phaser.Input.Keyboard.KeyCodes.F10,
KEY_F11: Phaser.Input.Keyboard.KeyCodes.F11, KEY_F11: Phaser.Input.Keyboard.KeyCodes.F11,
KEY_F12: Phaser.Input.Keyboard.KeyCodes.F12, KEY_F12: Phaser.Input.Keyboard.KeyCodes.F12,
KEY_HOME: Phaser.Input.Keyboard.KeyCodes.HOME,
KEY_INSERT: Phaser.Input.Keyboard.KeyCodes.INSERT,
KEY_PAGE_DOWN: Phaser.Input.Keyboard.KeyCodes.PAGE_DOWN, KEY_PAGE_DOWN: Phaser.Input.Keyboard.KeyCodes.PAGE_DOWN,
KEY_PAGE_UP: Phaser.Input.Keyboard.KeyCodes.PAGE_UP, KEY_PAGE_UP: Phaser.Input.Keyboard.KeyCodes.PAGE_UP,
KEY_CTRL: Phaser.Input.Keyboard.KeyCodes.CTRL,
KEY_DEL: Phaser.Input.Keyboard.KeyCodes.DELETE,
KEY_END: Phaser.Input.Keyboard.KeyCodes.END,
KEY_ENTER: Phaser.Input.Keyboard.KeyCodes.ENTER,
KEY_ESC: Phaser.Input.Keyboard.KeyCodes.ESC,
KEY_HOME: Phaser.Input.Keyboard.KeyCodes.HOME,
KEY_INSERT: Phaser.Input.Keyboard.KeyCodes.INSERT,
KEY_PLUS: Phaser.Input.Keyboard.KeyCodes.NUMPAD_ADD, // Assuming numpad plus KEY_PLUS: Phaser.Input.Keyboard.KeyCodes.NUMPAD_ADD, // Assuming numpad plus
KEY_MINUS: Phaser.Input.Keyboard.KeyCodes.NUMPAD_SUBTRACT, // Assuming numpad minus KEY_MINUS: Phaser.Input.Keyboard.KeyCodes.NUMPAD_SUBTRACT, // Assuming numpad minus
KEY_QUOTATION: Phaser.Input.Keyboard.KeyCodes.QUOTES, KEY_QUOTATION: Phaser.Input.Keyboard.KeyCodes.QUOTES,
KEY_SHIFT: Phaser.Input.Keyboard.KeyCodes.SHIFT, KEY_SHIFT: Phaser.Input.Keyboard.KeyCodes.SHIFT,
KEY_SPACE: Phaser.Input.Keyboard.KeyCodes.SPACE, KEY_SPACE: Phaser.Input.Keyboard.KeyCodes.SPACE,
KEY_TAB: Phaser.Input.Keyboard.KeyCodes.TAB, KEY_TAB: Phaser.Input.Keyboard.KeyCodes.TAB,
KEY_TILDE: Phaser.Input.Keyboard.KeyCodes.BACKTICK, KEY_TILDE: Phaser.Input.Keyboard.KeyCodes.BACKTICK,
KEY_ARROW_UP: Phaser.Input.Keyboard.KeyCodes.UP, KEY_ARROW_UP: Phaser.Input.Keyboard.KeyCodes.UP,
KEY_ARROW_DOWN: Phaser.Input.Keyboard.KeyCodes.DOWN, KEY_ARROW_DOWN: Phaser.Input.Keyboard.KeyCodes.DOWN,
KEY_ARROW_LEFT: Phaser.Input.Keyboard.KeyCodes.LEFT, KEY_ARROW_LEFT: Phaser.Input.Keyboard.KeyCodes.LEFT,
KEY_ARROW_RIGHT: Phaser.Input.Keyboard.KeyCodes.RIGHT, KEY_ARROW_RIGHT: Phaser.Input.Keyboard.KeyCodes.RIGHT,
KEY_LEFT_BRACKET: Phaser.Input.Keyboard.KeyCodes.OPEN_BRACKET, KEY_LEFT_BRACKET: Phaser.Input.Keyboard.KeyCodes.OPEN_BRACKET,
KEY_RIGHT_BRACKET: Phaser.Input.Keyboard.KeyCodes.CLOSED_BRACKET, KEY_RIGHT_BRACKET: Phaser.Input.Keyboard.KeyCodes.CLOSED_BRACKET,
KEY_SEMICOLON: Phaser.Input.Keyboard.KeyCodes.SEMICOLON, KEY_SEMICOLON: Phaser.Input.Keyboard.KeyCodes.SEMICOLON,
KEY_COMMA: Phaser.Input.Keyboard.KeyCodes.COMMA,
KEY_PERIOD: Phaser.Input.Keyboard.KeyCodes.PERIOD,
KEY_BACK_SLASH: Phaser.Input.Keyboard.KeyCodes.BACK_SLASH,
KEY_FORWARD_SLASH: Phaser.Input.Keyboard.KeyCodes.FORWARD_SLASH,
KEY_BACKSPACE: Phaser.Input.Keyboard.KeyCodes.BACKSPACE, KEY_BACKSPACE: Phaser.Input.Keyboard.KeyCodes.BACKSPACE,
KEY_ALT: Phaser.Input.Keyboard.KeyCodes.ALT, KEY_ALT: Phaser.Input.Keyboard.KeyCodes.ALT,
}, },
@ -160,6 +174,10 @@ const cfg_keyboard_qwerty = {
KEY_RIGHT_BRACKET: "RIGHT_BRACKET.png", KEY_RIGHT_BRACKET: "RIGHT_BRACKET.png",
KEY_SEMICOLON: "SEMICOLON.png", KEY_SEMICOLON: "SEMICOLON.png",
KEY_COMMA: "COMMA.png",
KEY_PERIOD: "PERIOD.png",
KEY_BACK_SLASH: "BACK_SLASH.png",
KEY_FORWARD_SLASH: "FORWARD_SLASH.png",
KEY_BACKSPACE: "BACK.png", KEY_BACKSPACE: "BACK.png",
KEY_ALT: "ALT.png", KEY_ALT: "ALT.png",

View File

@ -3172,6 +3172,7 @@ export class PreSetStatusAbAttr extends AbAttr {
*/ */
export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr {
protected immuneEffects: StatusEffect[]; protected immuneEffects: StatusEffect[];
private lastEffect: StatusEffect;
/** /**
* @param immuneEffects - The status effects to which the Pokémon is immune. * @param immuneEffects - The status effects to which the Pokémon is immune.
@ -3197,6 +3198,7 @@ export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr {
*/ */
override applyPreSetStatus(pokemon: Pokemon, passive: boolean, simulated: boolean, effect: StatusEffect, cancelled: BooleanHolder, args: any[]): void { override applyPreSetStatus(pokemon: Pokemon, passive: boolean, simulated: boolean, effect: StatusEffect, cancelled: BooleanHolder, args: any[]): void {
cancelled.value = true; cancelled.value = true;
this.lastEffect = effect;
} }
getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string {
@ -3204,7 +3206,7 @@ export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr {
i18next.t("abilityTriggers:statusEffectImmunityWithName", { i18next.t("abilityTriggers:statusEffectImmunityWithName", {
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),
abilityName, abilityName,
statusEffectName: getStatusEffectDescriptor(args[0] as StatusEffect) statusEffectName: getStatusEffectDescriptor(this.lastEffect)
}) : }) :
i18next.t("abilityTriggers:statusEffectImmunity", { i18next.t("abilityTriggers:statusEffectImmunity", {
pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), pokemonNameWithAffix: getPokemonNameWithAffix(pokemon),

View File

@ -7665,20 +7665,6 @@ export class AverageStatsAttr extends MoveEffectAttr {
} }
} }
export class DiscourageFrequentUseAttr extends MoveAttr {
getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): number {
const lastMoves = user.getLastXMoves(4);
console.log(lastMoves);
for (let m = 0; m < lastMoves.length; m++) {
if (lastMoves[m].move === move.id) {
return (4 - (m + 1)) * -10;
}
}
return 0;
}
}
export class MoneyAttr extends MoveEffectAttr { export class MoneyAttr extends MoveEffectAttr {
constructor() { constructor() {
super(true, {firstHitOnly: true }); super(true, {firstHitOnly: true });
@ -10517,8 +10503,7 @@ export function initMoves() {
} else { } else {
return 1; return 1;
} }
}) }),
.attr(DiscourageFrequentUseAttr),
new AttackMove(Moves.SNIPE_SHOT, PokemonType.WATER, MoveCategory.SPECIAL, 80, 100, 15, -1, 0, 8) new AttackMove(Moves.SNIPE_SHOT, PokemonType.WATER, MoveCategory.SPECIAL, 80, 100, 15, -1, 0, 8)
.attr(HighCritAttr) .attr(HighCritAttr)

View File

@ -424,6 +424,7 @@ export async function initBattleWithEnemyConfig(partyConfig: EnemyPartyConfig):
console.log( console.log(
`Pokemon: ${getPokemonNameWithAffix(enemyPokemon)}`, `Pokemon: ${getPokemonNameWithAffix(enemyPokemon)}`,
`| Species ID: ${enemyPokemon.species.speciesId}`, `| Species ID: ${enemyPokemon.species.speciesId}`,
`| Level: ${enemyPokemon.level}`,
`| Nature: ${getNatureName(enemyPokemon.nature, true, true, true)}`, `| Nature: ${getNatureName(enemyPokemon.nature, true, true, true)}`,
); );
console.log(`Stats (IVs): ${stats}`); console.log(`Stats (IVs): ${stats}`);

View File

@ -12,7 +12,6 @@ import BattleInfo, {
import type Move from "#app/data/moves/move"; import type Move from "#app/data/moves/move";
import { import {
HighCritAttr, HighCritAttr,
StatChangeBeforeDmgCalcAttr,
HitsTagAttr, HitsTagAttr,
applyMoveAttrs, applyMoveAttrs,
FixedDamageAttr, FixedDamageAttr,
@ -70,10 +69,8 @@ import {
EFFECTIVE_STATS, EFFECTIVE_STATS,
} from "#enums/stat"; } from "#enums/stat";
import { import {
DamageMoneyRewardModifier,
EnemyDamageBoosterModifier, EnemyDamageBoosterModifier,
EnemyDamageReducerModifier, EnemyDamageReducerModifier,
EnemyEndureChanceModifier,
EnemyFusionChanceModifier, EnemyFusionChanceModifier,
HiddenAbilityRateBoosterModifier, HiddenAbilityRateBoosterModifier,
BaseStatModifier, BaseStatModifier,
@ -119,7 +116,6 @@ import {
TypeImmuneTag, TypeImmuneTag,
getBattlerTag, getBattlerTag,
SemiInvulnerableTag, SemiInvulnerableTag,
TypeBoostTag,
MoveRestrictionBattlerTag, MoveRestrictionBattlerTag,
ExposedTag, ExposedTag,
DragonCheerTag, DragonCheerTag,
@ -188,7 +184,7 @@ import {
PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr, PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr,
applyAllyStatMultiplierAbAttrs, applyAllyStatMultiplierAbAttrs,
AllyStatMultiplierAbAttr, AllyStatMultiplierAbAttr,
MoveAbilityBypassAbAttr MoveAbilityBypassAbAttr,
} from "#app/data/abilities/ability"; } from "#app/data/abilities/ability";
import { allAbilities } from "#app/data/data-lists"; import { allAbilities } from "#app/data/data-lists";
import type PokemonData from "#app/system/pokemon-data"; import type PokemonData from "#app/system/pokemon-data";
@ -202,7 +198,7 @@ import {
EVOLVE_MOVE, EVOLVE_MOVE,
RELEARN_MOVE, RELEARN_MOVE,
} from "#app/data/balance/pokemon-level-moves"; } from "#app/data/balance/pokemon-level-moves";
import { DamageAchv, achvs } from "#app/system/achv"; import { achvs } from "#app/system/achv";
import type { StarterDataEntry, StarterMoveset } from "#app/system/game-data"; import type { StarterDataEntry, StarterMoveset } from "#app/system/game-data";
import { DexAttr } from "#app/system/game-data"; import { DexAttr } from "#app/system/game-data";
import { import {
@ -248,7 +244,7 @@ import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
import { CustomPokemonData } from "#app/data/custom-pokemon-data"; import { CustomPokemonData } from "#app/data/custom-pokemon-data";
import { SwitchType } from "#enums/switch-type"; import { SwitchType } from "#enums/switch-type";
import { SpeciesFormKey } from "#enums/species-form-key"; import { SpeciesFormKey } from "#enums/species-form-key";
import {getStatusEffectOverlapText } from "#app/data/status-effect"; import { getStatusEffectOverlapText } from "#app/data/status-effect";
import { import {
BASE_HIDDEN_ABILITY_CHANCE, BASE_HIDDEN_ABILITY_CHANCE,
BASE_SHINY_CHANCE, BASE_SHINY_CHANCE,
@ -7030,6 +7026,15 @@ export class EnemyPokemon extends Pokemon {
} }
speciesId = prevolution; speciesId = prevolution;
} }
if (this.hasTrainer() && globalScene.currentBattle) {
const { waveIndex } = globalScene.currentBattle;
const ivs: number[] = [];
while (ivs.length < 6) {
ivs.push(this.randSeedIntRange(Math.floor(waveIndex / 10), 31));
}
this.ivs = ivs;
}
} }
this.aiType = this.aiType =

View File

@ -2,7 +2,12 @@ import { BattlerIndex } from "#app/battle";
import { BattleType } from "#enums/battle-type"; import { BattleType } from "#enums/battle-type";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants"; import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
import { applyAbAttrs, SyncEncounterNatureAbAttr, applyPreSummonAbAttrs, PreSummonAbAttr } from "#app/data/abilities/ability"; import {
applyAbAttrs,
SyncEncounterNatureAbAttr,
applyPreSummonAbAttrs,
PreSummonAbAttr,
} from "#app/data/abilities/ability";
import { initEncounterAnims, loadEncounterAnimAssets } from "#app/data/battle-anims"; import { initEncounterAnims, loadEncounterAnimAssets } from "#app/data/battle-anims";
import { getCharVariantFromDialogue } from "#app/data/dialogue"; import { getCharVariantFromDialogue } from "#app/data/dialogue";
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
@ -196,6 +201,7 @@ export class EncounterPhase extends BattlePhase {
console.log( console.log(
`Pokemon: ${getPokemonNameWithAffix(enemyPokemon)}`, `Pokemon: ${getPokemonNameWithAffix(enemyPokemon)}`,
`| Species ID: ${enemyPokemon.species.speciesId}`, `| Species ID: ${enemyPokemon.species.speciesId}`,
`| Level: ${enemyPokemon.level}`,
`| Nature: ${getNatureName(enemyPokemon.nature, true, true, true)}`, `| Nature: ${getNatureName(enemyPokemon.nature, true, true, true)}`,
); );
console.log(`Stats (IVs): ${stats}`); console.log(`Stats (IVs): ${stats}`);

View File

@ -859,7 +859,7 @@ export class MoveEffectPhase extends PokemonPhase {
}); });
if (isCritical) { if (isCritical) {
globalScene.queueMessage(i18next.t("battle:criticalHit")); globalScene.queueMessage(i18next.t("battle:hitResultCriticalHit"));
} }
if (damage <= 0) { if (damage <= 0) {

View File

@ -15,14 +15,17 @@ export class PokerogueSystemSavedataApi extends ApiBase {
/** /**
* Get a system savedata. * Get a system savedata.
* @param params The {@linkcode GetSystemSavedataRequest} to send * @param params The {@linkcode GetSystemSavedataRequest} to send
* @returns The system savedata as `string` or `null` on error * @returns The system savedata as `string` or either the status code or `null` on error
*/ */
public async get(params: GetSystemSavedataRequest) { public async get(params: GetSystemSavedataRequest): Promise<string | number | null> {
try { try {
const urlSearchParams = this.toUrlSearchParams(params); const urlSearchParams = this.toUrlSearchParams(params);
const response = await this.doGet(`/savedata/system/get?${urlSearchParams}`); const response = await this.doGet(`/savedata/system/get?${urlSearchParams}`);
const rawSavedata = await response.text(); const rawSavedata = await response.text();
if (!response.ok) {
console.warn("Could not get system savedata!", response.status, rawSavedata);
return response.status;
}
return rawSavedata; return rawSavedata;
} catch (err) { } catch (err) {
console.warn("Could not get system savedata!", err); console.warn("Could not get system savedata!", err);

View File

@ -462,8 +462,13 @@ export class GameData {
if (!bypassLogin) { if (!bypassLogin) {
pokerogueApi.savedata.system.get({ clientSessionId }).then(saveDataOrErr => { pokerogueApi.savedata.system.get({ clientSessionId }).then(saveDataOrErr => {
if (!saveDataOrErr || saveDataOrErr.length === 0 || saveDataOrErr[0] !== "{") { if (
if (saveDataOrErr?.startsWith("sql: no rows in result set")) { typeof saveDataOrErr === "number" ||
!saveDataOrErr ||
saveDataOrErr.length === 0 ||
saveDataOrErr[0] !== "{"
) {
if (saveDataOrErr === 404) {
globalScene.queueMessage( globalScene.queueMessage(
"Save data could not be found. If this is a new account, you can safely ignore this message.", "Save data could not be found. If this is a new account, you can safely ignore this message.",
null, null,
@ -471,7 +476,7 @@ export class GameData {
); );
return resolve(true); return resolve(true);
} }
if (saveDataOrErr?.includes("Too many connections")) { if (typeof saveDataOrErr === "string" && saveDataOrErr?.includes("Too many connections")) {
globalScene.queueMessage( globalScene.queueMessage(
"Too many people are trying to connect and the server is overloaded. Please try again later.", "Too many people are trying to connect and the server is overloaded. Please try again later.",
null, null,
@ -479,7 +484,6 @@ export class GameData {
); );
return resolve(false); return resolve(false);
} }
console.error(saveDataOrErr);
return resolve(false); return resolve(false);
} }
@ -1500,7 +1504,7 @@ export class GameData {
link.remove(); link.remove();
}; };
if (!bypassLogin && dataType < GameDataType.SETTINGS) { if (!bypassLogin && dataType < GameDataType.SETTINGS) {
let promise: Promise<string | null> = Promise.resolve(null); let promise: Promise<string | null | number> = Promise.resolve(null);
if (dataType === GameDataType.SYSTEM) { if (dataType === GameDataType.SYSTEM) {
promise = pokerogueApi.savedata.system.get({ clientSessionId }); promise = pokerogueApi.savedata.system.get({ clientSessionId });
@ -1512,7 +1516,7 @@ export class GameData {
} }
promise.then(response => { promise.then(response => {
if (!response?.length || response[0] !== "{") { if (typeof response === "number" || !response?.length || response[0] !== "{") {
console.error(response); console.error(response);
resolve(false); resolve(false);
return; return;

View File

@ -292,6 +292,13 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
starterSelectBg.setOrigin(0, 0); starterSelectBg.setOrigin(0, 0);
this.starterSelectContainer.add(starterSelectBg); this.starterSelectContainer.add(starterSelectBg);
this.pokemonSprite = globalScene.add.sprite(53, 63, "pkmn__sub");
this.pokemonSprite.setPipeline(globalScene.spritePipeline, {
tone: [0.0, 0.0, 0.0, 0.0],
ignoreTimeTint: true,
});
this.starterSelectContainer.add(this.pokemonSprite);
this.shinyOverlay = globalScene.add.image(6, 6, "summary_overlay_shiny"); this.shinyOverlay = globalScene.add.image(6, 6, "summary_overlay_shiny");
this.shinyOverlay.setOrigin(0, 0); this.shinyOverlay.setOrigin(0, 0);
this.shinyOverlay.setVisible(false); this.shinyOverlay.setVisible(false);
@ -343,13 +350,6 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
this.starterSelectContainer.add(starterBoxContainer); this.starterSelectContainer.add(starterBoxContainer);
this.pokemonSprite = globalScene.add.sprite(53, 63, "pkmn__sub");
this.pokemonSprite.setPipeline(globalScene.spritePipeline, {
tone: [0.0, 0.0, 0.0, 0.0],
ignoreTimeTint: true,
});
this.starterSelectContainer.add(this.pokemonSprite);
this.type1Icon = globalScene.add.sprite(8, 98, getLocalizedSpriteKey("types")); this.type1Icon = globalScene.add.sprite(8, 98, getLocalizedSpriteKey("types"));
this.type1Icon.setScale(0.5); this.type1Icon.setScale(0.5);
this.type1Icon.setOrigin(0, 0); this.type1Icon.setOrigin(0, 0);

View File

@ -596,6 +596,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.iconAnimHandler = new PokemonIconAnimHandler(); this.iconAnimHandler = new PokemonIconAnimHandler();
this.iconAnimHandler.setup(); this.iconAnimHandler.setup();
this.pokemonSprite = globalScene.add.sprite(53, 63, "pkmn__sub");
this.pokemonSprite.setPipeline(globalScene.spritePipeline, {
tone: [0.0, 0.0, 0.0, 0.0],
ignoreTimeTint: true,
});
this.starterSelectContainer.add(this.pokemonSprite);
this.pokemonNumberText = addTextObject(17, 1, "0000", TextStyle.SUMMARY); this.pokemonNumberText = addTextObject(17, 1, "0000", TextStyle.SUMMARY);
this.pokemonNumberText.setOrigin(0, 0); this.pokemonNumberText.setOrigin(0, 0);
this.starterSelectContainer.add(this.pokemonNumberText); this.starterSelectContainer.add(this.pokemonNumberText);
@ -825,13 +832,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
return icon; return icon;
}); });
this.pokemonSprite = globalScene.add.sprite(53, 63, "pkmn__sub");
this.pokemonSprite.setPipeline(globalScene.spritePipeline, {
tone: [0.0, 0.0, 0.0, 0.0],
ignoreTimeTint: true,
});
this.starterSelectContainer.add(this.pokemonSprite);
this.type1Icon = globalScene.add.sprite(8, 98, getLocalizedSpriteKey("types")); this.type1Icon = globalScene.add.sprite(8, 98, getLocalizedSpriteKey("types"));
this.type1Icon.setScale(0.5); this.type1Icon.setScale(0.5);
this.type1Icon.setOrigin(0, 0); this.type1Icon.setOrigin(0, 0);

View File

@ -209,4 +209,19 @@ describe("Spec - Pokemon", () => {
expect(types[1]).toBe(PokemonType.DARK); expect(types[1]).toBe(PokemonType.DARK);
}); });
}); });
it.each([5, 25, 55, 95, 145, 195])(
"should set minimum IVs for enemy trainer pokemon based on wave (%i)",
async wave => {
game.override.startingWave(wave);
await game.classicMode.startBattle([Species.FEEBAS]);
const { waveIndex } = game.scene.currentBattle;
for (const pokemon of game.scene.getEnemyParty()) {
for (const index in pokemon.ivs) {
expect(pokemon.ivs[index]).toBeGreaterThanOrEqual(Math.floor(waveIndex / 10));
}
}
},
);
}); });