Fix all remaining biome lints

This commit is contained in:
Sirz Benjie 2025-03-07 21:31:08 -06:00
parent 852e70e2c3
commit 5c53f54d80
No known key found for this signature in database
GPG Key ID: 4A524B4D196C759E
63 changed files with 7752 additions and 7684 deletions

View File

@ -2,92 +2,86 @@
module.exports = { module.exports = {
forbidden: [ forbidden: [
{ {
name: 'no-circular-at-runtime', name: "no-circular-at-runtime",
severity: 'warn', severity: "warn",
comment: comment:
'This dependency is part of a circular relationship. You might want to revise ' + "This dependency is part of a circular relationship. You might want to revise " +
'your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ', "your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ",
from: {}, from: {},
to: { to: {
circular: true, circular: true,
viaOnly: { viaOnly: {
dependencyTypesNot: [ dependencyTypesNot: ["type-only"],
'type-only' },
] },
}
}
}, },
{ {
name: 'no-orphans', name: "no-orphans",
comment: comment:
"This is an orphan module - it's likely not used (anymore?). Either use it or " + "This is an orphan module - it's likely not used (anymore?). Either use it or " +
"remove it. If it's logical this module is an orphan (i.e. it's a config file), " + "remove it. If it's logical this module is an orphan (i.e. it's a config file), " +
"add an exception for it in your dependency-cruiser configuration. By default " + "add an exception for it in your dependency-cruiser configuration. By default " +
"this rule does not scrutinize dot-files (e.g. .eslintrc.js), TypeScript declaration " + "this rule does not scrutinize dot-files (e.g. .eslintrc.js), TypeScript declaration " +
"files (.d.ts), tsconfig.json and some of the babel and webpack configs.", "files (.d.ts), tsconfig.json and some of the babel and webpack configs.",
severity: 'warn', severity: "warn",
from: { from: {
orphan: true, orphan: true,
pathNot: [ pathNot: [
'(^|/)[.][^/]+[.](?:js|cjs|mjs|ts|cts|mts|json)$', // dot files "(^|/)[.][^/]+[.](?:js|cjs|mjs|ts|cts|mts|json)$", // dot files
'[.]d[.]ts$', // TypeScript declaration files "[.]d[.]ts$", // TypeScript declaration files
'(^|/)tsconfig[.]json$', // TypeScript config "(^|/)tsconfig[.]json$", // TypeScript config
'(^|/)(?:babel|webpack)[.]config[.](?:js|cjs|mjs|ts|cts|mts|json)$' // other configs "(^|/)(?:babel|webpack)[.]config[.](?:js|cjs|mjs|ts|cts|mts|json)$", // other configs
] ],
}, },
to: {}, to: {},
}, },
{ {
name: 'no-deprecated-core', name: "no-deprecated-core",
comment: comment:
'A module depends on a node core module that has been deprecated. Find an alternative - these are ' + "A module depends on a node core module that has been deprecated. Find an alternative - these are " +
"bound to exist - node doesn't deprecate lightly.", "bound to exist - node doesn't deprecate lightly.",
severity: 'warn', severity: "warn",
from: {}, from: {},
to: { to: {
dependencyTypes: [ dependencyTypes: ["core"],
'core'
],
path: [ path: [
'^v8/tools/codemap$', "^v8/tools/codemap$",
'^v8/tools/consarray$', "^v8/tools/consarray$",
'^v8/tools/csvparser$', "^v8/tools/csvparser$",
'^v8/tools/logreader$', "^v8/tools/logreader$",
'^v8/tools/profile_view$', "^v8/tools/profile_view$",
'^v8/tools/profile$', "^v8/tools/profile$",
'^v8/tools/SourceMap$', "^v8/tools/SourceMap$",
'^v8/tools/splaytree$', "^v8/tools/splaytree$",
'^v8/tools/tickprocessor-driver$', "^v8/tools/tickprocessor-driver$",
'^v8/tools/tickprocessor$', "^v8/tools/tickprocessor$",
'^node-inspect/lib/_inspect$', "^node-inspect/lib/_inspect$",
'^node-inspect/lib/internal/inspect_client$', "^node-inspect/lib/internal/inspect_client$",
'^node-inspect/lib/internal/inspect_repl$', "^node-inspect/lib/internal/inspect_repl$",
'^async_hooks$', "^async_hooks$",
'^punycode$', "^punycode$",
'^domain$', "^domain$",
'^constants$', "^constants$",
'^sys$', "^sys$",
'^_linklist$', "^_linklist$",
'^_stream_wrap$' "^_stream_wrap$",
], ],
} },
}, },
{ {
name: 'not-to-deprecated', name: "not-to-deprecated",
comment: comment:
'This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later ' + "This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later " +
'version of that module, or find an alternative. Deprecated modules are a security risk.', "version of that module, or find an alternative. Deprecated modules are a security risk.",
severity: 'warn', severity: "warn",
from: {}, from: {},
to: { to: {
dependencyTypes: [ dependencyTypes: ["deprecated"],
'deprecated' },
]
}
}, },
{ {
name: 'no-non-package-json', name: "no-non-package-json",
severity: 'error', severity: "error",
comment: comment:
"This module depends on an npm package that isn't in the 'dependencies' section of your package.json. " + "This module depends on an npm package that isn't in the 'dependencies' section of your package.json. " +
"That's problematic as the package either (1) won't be available on live (2 - worse) will be " + "That's problematic as the package either (1) won't be available on live (2 - worse) will be " +
@ -95,87 +89,75 @@ module.exports = {
"in your package.json.", "in your package.json.",
from: {}, from: {},
to: { to: {
dependencyTypes: [ dependencyTypes: ["npm-no-pkg", "npm-unknown"],
'npm-no-pkg', },
'npm-unknown'
]
}
}, },
{ {
name: 'not-to-unresolvable', name: "not-to-unresolvable",
comment: comment:
"This module depends on a module that cannot be found ('resolved to disk'). If it's an npm " + "This module depends on a module that cannot be found ('resolved to disk'). If it's an npm " +
'module: add it to your package.json. In all other cases you likely already know what to do.', "module: add it to your package.json. In all other cases you likely already know what to do.",
severity: 'error', severity: "error",
from: {}, from: {},
to: { to: {
couldNotResolve: true couldNotResolve: true,
} },
}, },
{ {
name: 'no-duplicate-dep-types', name: "no-duplicate-dep-types",
comment: comment:
"Likely this module depends on an external ('npm') package that occurs more than once " + "Likely this module depends on an external ('npm') package that occurs more than once " +
"in your package.json i.e. bot as a devDependencies and in dependencies. This will cause " + "in your package.json i.e. bot as a devDependencies and in dependencies. This will cause " +
"maintenance problems later on.", "maintenance problems later on.",
severity: 'warn', severity: "warn",
from: {}, from: {},
to: { to: {
moreThanOneDependencyType: true, moreThanOneDependencyType: true,
// as it's pretty common to have a type import be a type only import // as it's pretty common to have a type import be a type only import
// _and_ (e.g.) a devDependency - don't consider type-only dependency // _and_ (e.g.) a devDependency - don't consider type-only dependency
// types for this rule // types for this rule
dependencyTypesNot: ["type-only"] dependencyTypesNot: ["type-only"],
} },
}, },
/* rules you might want to tweak for your specific situation: */ /* rules you might want to tweak for your specific situation: */
{ {
name: 'not-to-spec', name: "not-to-spec",
comment: comment:
'This module depends on a spec (test) file. The sole responsibility of a spec file is to test code. ' + "This module depends on a spec (test) file. The sole responsibility of a spec file is to test code. " +
"If there's something in a spec that's of use to other modules, it doesn't have that single " + "If there's something in a spec that's of use to other modules, it doesn't have that single " +
'responsibility anymore. Factor it out into (e.g.) a separate utility/ helper or a mock.', "responsibility anymore. Factor it out into (e.g.) a separate utility/ helper or a mock.",
severity: 'error', severity: "error",
from: {}, from: {},
to: { to: {
path: '[.](?:spec|test)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$' path: "[.](?:spec|test)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$",
} },
}, },
{ {
name: 'not-to-dev-dep', name: "not-to-dev-dep",
severity: 'error', severity: "error",
comment: comment:
"This module depends on an npm package from the 'devDependencies' section of your " + "This module depends on an npm package from the 'devDependencies' section of your " +
'package.json. It looks like something that ships to production, though. To prevent problems ' + "package.json. It looks like something that ships to production, though. To prevent problems " +
"with npm packages that aren't there on production declare it (only!) in the 'dependencies'" + "with npm packages that aren't there on production declare it (only!) in the 'dependencies'" +
'section of your package.json. If this module is development only - add it to the ' + "section of your package.json. If this module is development only - add it to the " +
'from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration', "from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration",
from: { from: {
path: '^(src)', path: "^(src)",
pathNot: [ pathNot: ["[.](?:spec|test|setup|script)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$", "./test"],
'[.](?:spec|test|setup|script)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$',
'./test'
]
}, },
to: { to: {
dependencyTypes: [ dependencyTypes: ["npm-dev"],
'npm-dev',
],
// type only dependencies are not a problem as they don't end up in the // type only dependencies are not a problem as they don't end up in the
// production code or are ignored by the runtime. // production code or are ignored by the runtime.
dependencyTypesNot: [ dependencyTypesNot: ["type-only"],
'type-only' pathNot: ["node_modules/@types/"],
], },
pathNot: [
'node_modules/@types/'
]
}
}, },
{ {
name: 'optional-deps-used', name: "optional-deps-used",
severity: 'info', severity: "info",
comment: comment:
"This module depends on an npm package that is declared as an optional dependency " + "This module depends on an npm package that is declared as an optional dependency " +
"in your package.json. As this makes sense in limited situations only, it's flagged here. " + "in your package.json. As this makes sense in limited situations only, it's flagged here. " +
@ -183,33 +165,28 @@ module.exports = {
"dependency-cruiser configuration.", "dependency-cruiser configuration.",
from: {}, from: {},
to: { to: {
dependencyTypes: [ dependencyTypes: ["npm-optional"],
'npm-optional' },
]
}
}, },
{ {
name: 'peer-deps-used', name: "peer-deps-used",
comment: comment:
"This module depends on an npm package that is declared as a peer dependency " + "This module depends on an npm package that is declared as a peer dependency " +
"in your package.json. This makes sense if your package is e.g. a plugin, but in " + "in your package.json. This makes sense if your package is e.g. a plugin, but in " +
"other cases - maybe not so much. If the use of a peer dependency is intentional " + "other cases - maybe not so much. If the use of a peer dependency is intentional " +
"add an exception to your dependency-cruiser configuration.", "add an exception to your dependency-cruiser configuration.",
severity: 'warn', severity: "warn",
from: {}, from: {},
to: { to: {
dependencyTypes: [ dependencyTypes: ["npm-peer"],
'npm-peer' },
] },
}
}
], ],
options: { options: {
/* Which modules not to follow further when encountered */ /* Which modules not to follow further when encountered */
doNotFollow: { doNotFollow: {
/* path: an array of regular expressions in strings to match against */ /* path: an array of regular expressions in strings to match against */
path: ['node_modules'] path: ["node_modules"],
}, },
/* Which modules to exclude */ /* Which modules to exclude */
@ -271,7 +248,7 @@ module.exports = {
defaults to './tsconfig.json'. defaults to './tsconfig.json'.
*/ */
tsConfig: { tsConfig: {
fileName: 'tsconfig.json' fileName: "tsconfig.json",
}, },
/* Webpack configuration to use to get resolve options from. /* Webpack configuration to use to get resolve options from.
@ -345,7 +322,7 @@ module.exports = {
collapses everything in node_modules to one folder deep so you see collapses everything in node_modules to one folder deep so you see
the external modules, but their innards. the external modules, but their innards.
*/ */
collapsePattern: 'node_modules/(?:@[^/]+/[^/]+|[^/]+)', collapsePattern: "node_modules/(?:@[^/]+/[^/]+|[^/]+)",
/* Options to tweak the appearance of your graph.See /* Options to tweak the appearance of your graph.See
https://github.com/sverweij/dependency-cruiser/blob/main/doc/options-reference.md#reporteroptions https://github.com/sverweij/dependency-cruiser/blob/main/doc/options-reference.md#reporteroptions
@ -367,7 +344,8 @@ module.exports = {
dependency graph reporter (`archi`) you probably want to tweak dependency graph reporter (`archi`) you probably want to tweak
this collapsePattern to your situation. this collapsePattern to your situation.
*/ */
collapsePattern: '^(?:packages|src|lib(s?)|app(s?)|bin|test(s?)|spec(s?))/[^/]+|node_modules/(?:@[^/]+/[^/]+|[^/]+)', collapsePattern:
"^(?:packages|src|lib(s?)|app(s?)|bin|test(s?)|spec(s?))/[^/]+|node_modules/(?:@[^/]+/[^/]+|[^/]+)",
/* Options to tweak the appearance of your graph. If you don't specify a /* Options to tweak the appearance of your graph. If you don't specify a
theme for 'archi' dependency-cruiser will use the one specified in the theme for 'archi' dependency-cruiser will use the one specified in the
@ -375,10 +353,10 @@ module.exports = {
*/ */
// theme: { }, // theme: { },
}, },
"text": { text: {
"highlightFocused": true highlightFocused: true,
}, },
} },
} },
}; };
// generated: dependency-cruiser@16.3.3 on 2024-06-13T23:26:36.169Z // generated: dependency-cruiser@16.3.3 on 2024-06-13T23:26:36.169Z

View File

@ -27,7 +27,7 @@
"*.css", // TODO? "*.css", // TODO?
"*.html", // TODO? "*.html", // TODO?
// TODO: these files are too big and complex, ignore them until their respective refactors // TODO: these files are too big and complex, ignore them until their respective refactors
"src/data/move.ts", "src/data/moves/move.ts",
"src/data/ability.ts", "src/data/ability.ts",
"src/field/pokemon.ts", "src/field/pokemon.ts",
@ -77,7 +77,7 @@
"complexity": { "complexity": {
"noExcessiveCognitiveComplexity": "warn", "noExcessiveCognitiveComplexity": "warn",
"useLiteralKeys": "off", "useLiteralKeys": "off",
"noForEach": "info", // TODO: Refactor use of foreach and remove this line. "noForEach": "off", // Foreach vs for of is not that simple.
"noUselessSwitchCase": "off", // Explicit > Implicit "noUselessSwitchCase": "off", // Explicit > Implicit
"noUselessConstructor": "warn", // TODO: Refactor and make this an error "noUselessConstructor": "warn", // TODO: Refactor and make this an error
"noBannedTypes": "warn" // TODO: Refactor and make this an error "noBannedTypes": "warn" // TODO: Refactor and make this an error

View File

@ -31,7 +31,8 @@ async function promptTestType() {
if (typeAnswer.selectedOption === "EXIT") { if (typeAnswer.selectedOption === "EXIT") {
console.log("Exiting..."); console.log("Exiting...");
return process.exit(); return process.exit();
} else if (!typeChoices.includes(typeAnswer.selectedOption)) { }
if (!typeChoices.includes(typeAnswer.selectedOption)) {
console.error(`Please provide a valid type (${typeChoices.join(", ")})!`); console.error(`Please provide a valid type (${typeChoices.join(", ")})!`);
return await promptTestType(); return await promptTestType();
} }

14354
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,8 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { import { AttackMove, BeakBlastHeaderAttr, DelayedAttackAttr, SelfStatusMove, allMoves } from "./moves/move";
AttackMove,
BeakBlastHeaderAttr,
DelayedAttackAttr,
SelfStatusMove,
allMoves,
} from "./moves/move";
import { MoveFlags } from "#enums/MoveFlags"; import { MoveFlags } from "#enums/MoveFlags";
import type Pokemon from "../field/pokemon"; import type Pokemon from "../field/pokemon";
import { import { type nil, getFrameMs, getEnumKeys, getEnumValues, animationFileName } from "../utils";
type nil,
getFrameMs,
getEnumKeys,
getEnumValues,
animationFileName,
} from "../utils";
import type { BattlerIndex } from "../battle"; import type { BattlerIndex } from "../battle";
import type { Element } from "json-stable-stringify"; import type { Element } from "json-stable-stringify";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
@ -1122,103 +1110,113 @@ export abstract class BattleAnim {
spritePriorities.push(1); spritePriorities.push(1);
} }
const graphicIndex = g++; const graphicIndex = g++;
const moveSprite = sprites[graphicIndex]; const moveSprite = sprites[graphicIndex];
if (spritePriorities[graphicIndex] !== frame.priority) { if (spritePriorities[graphicIndex] !== frame.priority) {
spritePriorities[graphicIndex] = frame.priority; spritePriorities[graphicIndex] = frame.priority;
/** Move the position that the moveSprite is rendered in based on the priority. /** Move the position that the moveSprite is rendered in based on the priority.
* @param priority The priority level to draw the sprite. * @param priority The priority level to draw the sprite.
* - 0: Draw the sprite in front of the pokemon on the field. * - 0: Draw the sprite in front of the pokemon on the field.
* - 1: Draw the sprite in front of the user pokemon. * - 1: Draw the sprite in front of the user pokemon.
* - 2: Draw the sprite in front of its `bgSprite` (if it has one), or its * - 2: Draw the sprite in front of its `bgSprite` (if it has one), or its
* `AnimFocus` (if that is user/target), otherwise behind everything. * `AnimFocus` (if that is user/target), otherwise behind everything.
* - 3: Draw the sprite behind its `AnimFocus` (if that is user/target), otherwise in front of everything. * - 3: Draw the sprite behind its `AnimFocus` (if that is user/target), otherwise in front of everything.
*/ */
const setSpritePriority = (priority: number) => { const setSpritePriority = (priority: number) => {
/** The sprite we are moving the moveSprite in relation to */ /** The sprite we are moving the moveSprite in relation to */
let targetSprite: Phaser.GameObjects.GameObject | nil; let targetSprite: Phaser.GameObjects.GameObject | nil;
/** The method that is being used to move the sprite.*/ /** The method that is being used to move the sprite.*/
let moveFunc: ((sprite: Phaser.GameObjects.GameObject, target: Phaser.GameObjects.GameObject) => void) | let moveFunc:
((sprite: Phaser.GameObjects.GameObject) => void) = globalScene.field.bringToTop; | ((sprite: Phaser.GameObjects.GameObject, target: Phaser.GameObjects.GameObject) => void)
| ((sprite: Phaser.GameObjects.GameObject) => void) = globalScene.field.bringToTop;
if (priority === 0) { // Place the sprite in front of the pokemon on the field. if (priority === 0) {
targetSprite = globalScene.getEnemyField().find(p => p) ?? globalScene.getPlayerField().find(p => p); // Place the sprite in front of the pokemon on the field.
console.log(typeof targetSprite); targetSprite = globalScene.getEnemyField().find(p => p) ?? globalScene.getPlayerField().find(p => p);
moveFunc = globalScene.field.moveBelow; console.log(typeof targetSprite);
} else if (priority === 2 && this.bgSprite) { moveFunc = globalScene.field.moveBelow;
moveFunc = globalScene.field.moveAbove; } else if (priority === 2 && this.bgSprite) {
targetSprite = this.bgSprite; moveFunc = globalScene.field.moveAbove;
} else if (priority === 2 || priority === 3) { targetSprite = this.bgSprite;
moveFunc = priority === 2 ? globalScene.field.moveBelow : globalScene.field.moveAbove; } else if (priority === 2 || priority === 3) {
if (frame.focus === AnimFocus.USER) { moveFunc = priority === 2 ? globalScene.field.moveBelow : globalScene.field.moveAbove;
targetSprite = this.user; if (frame.focus === AnimFocus.USER) {
} else if (frame.focus === AnimFocus.TARGET) { targetSprite = this.user;
targetSprite = this.target; } else if (frame.focus === AnimFocus.TARGET) {
} targetSprite = this.target;
} }
// If target sprite is not undefined and exists in the field container, then move the sprite using the moveFunc. }
// Otherwise, default to just bringing it to the top. // If target sprite is not undefined and exists in the field container, then move the sprite using the moveFunc.
targetSprite && globalScene.field.exists(targetSprite) ? moveFunc.bind(globalScene.field)(moveSprite as Phaser.GameObjects.GameObject, targetSprite) : globalScene.field.bringToTop(moveSprite as Phaser.GameObjects.GameObject); // Otherwise, default to just bringing it to the top.
}; targetSprite && globalScene.field.exists(targetSprite)
setSpritePriority(frame.priority); ? moveFunc.bind(globalScene.field)(moveSprite as Phaser.GameObjects.GameObject, targetSprite)
} : globalScene.field.bringToTop(moveSprite as Phaser.GameObjects.GameObject);
moveSprite.setFrame(frame.graphicFrame); };
//console.log(AnimFocus[frame.focus]); setSpritePriority(frame.priority);
}
moveSprite.setFrame(frame.graphicFrame);
//console.log(AnimFocus[frame.focus]);
const graphicFrameData = frameData.get(frame.target)!.get(graphicIndex)!; // TODO: are those bangs correct? const graphicFrameData = frameData.get(frame.target)!.get(graphicIndex)!; // TODO: are those bangs correct?
moveSprite.setPosition(graphicFrameData.x, graphicFrameData.y); moveSprite.setPosition(graphicFrameData.x, graphicFrameData.y);
moveSprite.setAngle(graphicFrameData.angle); moveSprite.setAngle(graphicFrameData.angle);
moveSprite.setScale(graphicFrameData.scaleX, graphicFrameData.scaleY); moveSprite.setScale(graphicFrameData.scaleX, graphicFrameData.scaleY);
moveSprite.setAlpha(frame.opacity / 255); moveSprite.setAlpha(frame.opacity / 255);
moveSprite.setVisible(frame.visible); moveSprite.setVisible(frame.visible);
moveSprite.setBlendMode(frame.blendType === AnimBlendType.NORMAL ? Phaser.BlendModes.NORMAL : frame.blendType === AnimBlendType.ADD ? Phaser.BlendModes.ADD : Phaser.BlendModes.DIFFERENCE); moveSprite.setBlendMode(
} frame.blendType === AnimBlendType.NORMAL
? Phaser.BlendModes.NORMAL
: frame.blendType === AnimBlendType.ADD
? Phaser.BlendModes.ADD
: Phaser.BlendModes.DIFFERENCE,
);
} }
if (anim?.frameTimedEvents.has(f)) { }
const base = anim.frames.length - f; if (anim?.frameTimedEvents.has(f)) {
// Bang is correct due to `has` check above, which cannot return true for an undefined / null `f` const base = anim.frames.length - f;
for (const event of anim.frameTimedEvents.get(f)!) { // Bang is correct due to `has` check above, which cannot return true for an undefined / null `f`
r = Math.max(base + event.execute(this), r); for (const event of anim.frameTimedEvents.get(f)!) {
} r = Math.max(base + event.execute(this), r);
} }
const targets = getEnumValues(AnimFrameTarget); }
for (const i of targets) { const targets = getEnumValues(AnimFrameTarget);
const count = i === AnimFrameTarget.GRAPHIC ? g : i === AnimFrameTarget.USER ? u : t; for (const i of targets) {
if (count < spriteCache[i].length) { const count = i === AnimFrameTarget.GRAPHIC ? g : i === AnimFrameTarget.USER ? u : t;
const spritesToRemove = spriteCache[i].slice(count, spriteCache[i].length); if (count < spriteCache[i].length) {
for (const rs of spritesToRemove) { const spritesToRemove = spriteCache[i].slice(count, spriteCache[i].length);
if (!rs.getData("locked") as boolean) { for (const rs of spritesToRemove) {
const spriteCacheIndex = spriteCache[i].indexOf(rs); if (!rs.getData("locked") as boolean) {
spriteCache[i].splice(spriteCacheIndex, 1); const spriteCacheIndex = spriteCache[i].indexOf(rs);
if (i === AnimFrameTarget.GRAPHIC) { spriteCache[i].splice(spriteCacheIndex, 1);
spritePriorities.splice(spriteCacheIndex, 1); if (i === AnimFrameTarget.GRAPHIC) {
} spritePriorities.splice(spriteCacheIndex, 1);
rs.destroy();
} }
rs.destroy();
} }
} }
} }
f++; }
r--; f++;
}, r--;
onComplete: () => { },
for (const ms of Object.values(spriteCache).flat()) { onComplete: () => {
if (ms && !ms.getData("locked")) { for (const ms of Object.values(spriteCache).flat()) {
ms.destroy(); if (ms && !ms.getData("locked")) {
} ms.destroy();
}
if (r) {
globalScene.tweens.addCounter({
duration: getFrameMs(r),
onComplete: () => cleanUpAndComplete()
});
} else {
cleanUpAndComplete();
} }
} }
}); if (r) {
} globalScene.tweens.addCounter({
duration: getFrameMs(r),
onComplete: () => cleanUpAndComplete(),
});
} else {
cleanUpAndComplete();
}
},
});
}
private getGraphicFrameDataWithoutTarget( private getGraphicFrameDataWithoutTarget(
frames: AnimFrame[], frames: AnimFrame[],
@ -1356,51 +1354,57 @@ export abstract class BattleAnim {
moveSprite.setAngle(graphicFrameData.angle); moveSprite.setAngle(graphicFrameData.angle);
moveSprite.setScale(graphicFrameData.scaleX, graphicFrameData.scaleY); moveSprite.setScale(graphicFrameData.scaleX, graphicFrameData.scaleY);
moveSprite.setAlpha(frame.opacity / 255); moveSprite.setAlpha(frame.opacity / 255);
moveSprite.setVisible(frame.visible); moveSprite.setVisible(frame.visible);
moveSprite.setBlendMode(frame.blendType === AnimBlendType.NORMAL ? Phaser.BlendModes.NORMAL : frame.blendType === AnimBlendType.ADD ? Phaser.BlendModes.ADD : Phaser.BlendModes.DIFFERENCE); moveSprite.setBlendMode(
} frame.blendType === AnimBlendType.NORMAL
? Phaser.BlendModes.NORMAL
: frame.blendType === AnimBlendType.ADD
? Phaser.BlendModes.ADD
: Phaser.BlendModes.DIFFERENCE,
);
} }
if (anim?.frameTimedEvents.get(frameCount)) { }
const base = anim.frames.length - frameCount; if (anim?.frameTimedEvents.get(frameCount)) {
for (const event of anim.frameTimedEvents.get(frameCount)!) { const base = anim.frames.length - frameCount;
totalFrames = Math.max(base + event.execute(this, frameTimedEventPriority), totalFrames); for (const event of anim.frameTimedEvents.get(frameCount)!) {
} totalFrames = Math.max(base + event.execute(this, frameTimedEventPriority), totalFrames);
} }
const targets = getEnumValues(AnimFrameTarget); }
for (const i of targets) { const targets = getEnumValues(AnimFrameTarget);
const count = graphicFrameCount; for (const i of targets) {
if (count < spriteCache[i].length) { const count = graphicFrameCount;
const spritesToRemove = spriteCache[i].slice(count, spriteCache[i].length); if (count < spriteCache[i].length) {
for (const sprite of spritesToRemove) { const spritesToRemove = spriteCache[i].slice(count, spriteCache[i].length);
if (!sprite.getData("locked") as boolean) { for (const sprite of spritesToRemove) {
const spriteCacheIndex = spriteCache[i].indexOf(sprite); if (!sprite.getData("locked") as boolean) {
spriteCache[i].splice(spriteCacheIndex, 1); const spriteCacheIndex = spriteCache[i].indexOf(sprite);
sprite.destroy(); spriteCache[i].splice(spriteCacheIndex, 1);
} sprite.destroy();
} }
} }
} }
frameCount++; }
totalFrames--; frameCount++;
}, totalFrames--;
onComplete: () => { },
for (const sprite of Object.values(spriteCache).flat()) { onComplete: () => {
if (sprite && !sprite.getData("locked")) { for (const sprite of Object.values(spriteCache).flat()) {
sprite.destroy(); if (sprite && !sprite.getData("locked")) {
} sprite.destroy();
}
if (totalFrames) {
globalScene.tweens.addCounter({
duration: getFrameMs(totalFrames),
onComplete: () => cleanUpAndComplete()
});
} else {
cleanUpAndComplete();
} }
} }
}); if (totalFrames) {
} globalScene.tweens.addCounter({
duration: getFrameMs(totalFrames),
onComplete: () => cleanUpAndComplete(),
});
} else {
cleanUpAndComplete();
}
},
});
}
} }
export class CommonBattleAnim extends BattleAnim { export class CommonBattleAnim extends BattleAnim {

View File

@ -2125,7 +2125,13 @@ export class TypeBoostTag extends BattlerTag {
public boostValue: number; public boostValue: number;
public oneUse: boolean; public oneUse: boolean;
constructor(tagType: BattlerTagType, sourceMove: Moves, boostedType: PokemonType, boostValue: number, oneUse: boolean) { constructor(
tagType: BattlerTagType,
sourceMove: Moves,
boostedType: PokemonType,
boostValue: number,
oneUse: boolean,
) {
super(tagType, BattlerTagLapseType.TURN_END, 1, sourceMove); super(tagType, BattlerTagLapseType.TURN_END, 1, sourceMove);
this.boostedType = boostedType; this.boostedType = boostedType;
@ -2334,8 +2340,10 @@ export class RoostedTag extends BattlerTag {
const currentTypes = pokemon.getTypes(); const currentTypes = pokemon.getTypes();
const baseTypes = pokemon.getTypes(false, false, true); const baseTypes = pokemon.getTypes(false, false, true);
const forestsCurseApplied: boolean = currentTypes.includes(PokemonType.GRASS) && !baseTypes.includes(PokemonType.GRASS); const forestsCurseApplied: boolean =
const trickOrTreatApplied: boolean = currentTypes.includes(PokemonType.GHOST) && !baseTypes.includes(PokemonType.GHOST); currentTypes.includes(PokemonType.GRASS) && !baseTypes.includes(PokemonType.GRASS);
const trickOrTreatApplied: boolean =
currentTypes.includes(PokemonType.GHOST) && !baseTypes.includes(PokemonType.GHOST);
if (this.isBaseFlying) { if (this.isBaseFlying) {
let modifiedTypes: PokemonType[] = []; let modifiedTypes: PokemonType[] = [];

View File

@ -735,7 +735,9 @@ interface monotypeOverride {
* Implements a mono type challenge. * Implements a mono type challenge.
*/ */
export class SingleTypeChallenge extends Challenge { export class SingleTypeChallenge extends Challenge {
private static TYPE_OVERRIDES: monotypeOverride[] = [{ species: Species.CASTFORM, type: PokemonType.NORMAL, fusion: false }]; private static TYPE_OVERRIDES: monotypeOverride[] = [
{ species: Species.CASTFORM, type: PokemonType.NORMAL, fusion: false },
];
// TODO: Find a solution for all Pokemon with this ssui issue, including Basculin and Burmy // TODO: Find a solution for all Pokemon with this ssui issue, including Basculin and Burmy
private static SPECIES_OVERRIDES: Species[] = [Species.MELOETTA]; private static SPECIES_OVERRIDES: Species[] = [Species.MELOETTA];

View File

@ -969,7 +969,12 @@ export class AttackTypeBoosterHeldItemTypeRequirement extends EncounterPokemonRe
invertQuery: boolean; invertQuery: boolean;
requireTransferable: boolean; requireTransferable: boolean;
constructor(heldItemTypes: PokemonType | PokemonType[], minNumberOfPokemon = 1, invertQuery = false, requireTransferable = true) { constructor(
heldItemTypes: PokemonType | PokemonType[],
minNumberOfPokemon = 1,
invertQuery = false,
requireTransferable = true,
) {
super(); super();
this.minNumberOfPokemon = minNumberOfPokemon; this.minNumberOfPokemon = minNumberOfPokemon;
this.invertQuery = invertQuery; this.invertQuery = invertQuery;

View File

@ -210,8 +210,8 @@ export async function initBattleWithEnemyConfig(partyConfig: EnemyPartyConfig):
battle.enemyLevels = battle.enemyLevels.map(level => level + additive); battle.enemyLevels = battle.enemyLevels.map(level => level + additive);
battle.enemyLevels.forEach((level, e) => { battle.enemyLevels.forEach((level, e) => {
let enemySpecies; let enemySpecies: PokemonSpecies | undefined;
let dataSource; let dataSource: PokemonData | undefined;
let isBoss = false; let isBoss = false;
if (!loaded) { if (!loaded) {
if ((!isNullOrUndefined(trainerType) || trainerConfig) && battle.trainer) { if ((!isNullOrUndefined(trainerType) || trainerConfig) && battle.trainer) {
@ -991,7 +991,7 @@ export function handleMysteryEncounterBattleStartEffects() {
) { ) {
const effects = encounter.startOfBattleEffects; const effects = encounter.startOfBattleEffects;
effects.forEach(effect => { effects.forEach(effect => {
let source; let source: EnemyPokemon | Pokemon;
if (effect.sourcePokemon) { if (effect.sourcePokemon) {
source = effect.sourcePokemon; source = effect.sourcePokemon;
} else if (!isNullOrUndefined(effect.sourceBattlerIndex)) { } else if (!isNullOrUndefined(effect.sourceBattlerIndex)) {
@ -1009,6 +1009,7 @@ export function handleMysteryEncounterBattleStartEffects() {
} else { } else {
source = globalScene.getEnemyField()[0]; source = globalScene.getEnemyField()[0];
} }
// @ts-ignore: source cannot be undefined
globalScene.pushPhase(new MovePhase(source, effect.targets, effect.move, effect.followUp, effect.ignorePp)); globalScene.pushPhase(new MovePhase(source, effect.targets, effect.move, effect.followUp, effect.ignorePp));
}); });
@ -1045,7 +1046,7 @@ export function getRandomEncounterSpecies(level: number, isBoss = false, rerollH
let bossSpecies: PokemonSpecies; let bossSpecies: PokemonSpecies;
let isEventEncounter = false; let isEventEncounter = false;
const eventEncounters = globalScene.eventManager.getEventEncounters(); const eventEncounters = globalScene.eventManager.getEventEncounters();
let formIndex; let formIndex: number | undefined;
if (eventEncounters.length > 0 && randSeedInt(2) === 1) { if (eventEncounters.length > 0 && randSeedInt(2) === 1) {
const eventEncounter = randSeedItem(eventEncounters); const eventEncounter = randSeedItem(eventEncounters);

View File

@ -60,15 +60,15 @@ export class TrainerPartyTemplate {
this.balanced = !!balanced; this.balanced = !!balanced;
} }
getStrength(index: number): PartyMemberStrength { getStrength(_index: number): PartyMemberStrength {
return this.strength; return this.strength;
} }
isSameSpecies(index: number): boolean { isSameSpecies(_index: number): boolean {
return this.sameSpecies; return this.sameSpecies;
} }
isBalanced(index: number): boolean { isBalanced(_index: number): boolean {
return this.balanced; return this.balanced;
} }
} }
@ -1230,10 +1230,10 @@ export class TrainerConfig {
/** /**
* Initializes the trainer configuration for a Stat Trainer, as part of the Trainer's Test Mystery Encounter. * Initializes the trainer configuration for a Stat Trainer, as part of the Trainer's Test Mystery Encounter.
* @param isMale Whether the stat trainer is Male or Female (for localization of the title). * @param _isMale Whether the stat trainer is Male or Female (for localization of the title).
* @returns {TrainerConfig} The updated TrainerConfig instance. * @returns {TrainerConfig} The updated TrainerConfig instance.
**/ **/
initForStatTrainer(isMale = false): TrainerConfig { initForStatTrainer(_isMale = false): TrainerConfig {
if (!getIsInitialized()) { if (!getIsInitialized()) {
initI18n(); initI18n();
} }

View File

@ -10,7 +10,8 @@ import {
getTerrainStartMessage, getTerrainStartMessage,
getWeatherClearMessage, getWeatherClearMessage,
getWeatherStartMessage, getWeatherStartMessage,
getLegendaryWeatherContinuesMessage, Weather, getLegendaryWeatherContinuesMessage,
Weather,
} from "#app/data/weather"; } from "#app/data/weather";
import { CommonAnim } from "#app/data/battle-anims"; import { CommonAnim } from "#app/data/battle-anims";
import type { PokemonType } from "#enums/pokemon-type"; import type { PokemonType } from "#enums/pokemon-type";
@ -319,8 +320,13 @@ export class Arena {
const oldWeatherType = this.weather?.weatherType || WeatherType.NONE; const oldWeatherType = this.weather?.weatherType || WeatherType.NONE;
if (this.weather?.isImmutable() && ![ WeatherType.HARSH_SUN, WeatherType.HEAVY_RAIN, WeatherType.STRONG_WINDS, WeatherType.NONE ].includes(weather)) { if (
globalScene.unshiftPhase(new CommonAnimPhase(undefined, undefined, CommonAnim.SUNNY + (oldWeatherType - 1), true)); this.weather?.isImmutable() &&
![WeatherType.HARSH_SUN, WeatherType.HEAVY_RAIN, WeatherType.STRONG_WINDS, WeatherType.NONE].includes(weather)
) {
globalScene.unshiftPhase(
new CommonAnimPhase(undefined, undefined, CommonAnim.SUNNY + (oldWeatherType - 1), true),
);
globalScene.queueMessage(getLegendaryWeatherContinuesMessage(oldWeatherType)!); globalScene.queueMessage(getLegendaryWeatherContinuesMessage(oldWeatherType)!);
return false; return false;
} }

View File

@ -8,7 +8,7 @@ import TransitionImagePackPlugin from "phaser3-rex-plugins/templates/transitioni
import { initI18n } from "./plugins/i18n"; import { initI18n } from "./plugins/i18n";
// Catch global errors and display them in an alert so users can report the issue. // Catch global errors and display them in an alert so users can report the issue.
window.onerror = (message, source, lineno, colno, error) => { window.onerror = (_message, _source, _lineno, _colno, error) => {
console.error(error); console.error(error);
// const errorString = `Received unhandled error. Open browser console and click OK to see details.\nError: ${message}\nSource: ${source}\nLine: ${lineno}\nColumn: ${colno}\nStack: ${error.stack}`; // const errorString = `Received unhandled error. Open browser console and click OK to see details.\nError: ${message}\nSource: ${source}\nLine: ${lineno}\nColumn: ${colno}\nStack: ${error.stack}`;
//alert(errorString); //alert(errorString);
@ -40,7 +40,7 @@ Phaser.GameObjects.Text.prototype.setPositionRelative = setPositionRelative;
Phaser.GameObjects.Rectangle.prototype.setPositionRelative = setPositionRelative; Phaser.GameObjects.Rectangle.prototype.setPositionRelative = setPositionRelative;
document.fonts.load("16px emerald").then(() => document.fonts.load("10px pkmnems")); document.fonts.load("16px emerald").then(() => document.fonts.load("10px pkmnems"));
// biome-ignore lint/suspicious/noImplicitAnyLet: TODO
let game; let game;
const startGame = async (manifest?: any) => { const startGame = async (manifest?: any) => {

View File

@ -373,7 +373,7 @@ export class MovePhase extends BattlePhase {
* TODO: is this sustainable? * TODO: is this sustainable?
*/ */
let failedDueToTerrain = false; let failedDueToTerrain = false;
let failedDueToWeather: boolean = false; let failedDueToWeather = false;
if (success) { if (success) {
const passesConditions = move.applyConditions(this.pokemon, targets[0], move); const passesConditions = move.applyConditions(this.pokemon, targets[0], move);
failedDueToWeather = globalScene.arena.isMoveWeatherCancelled(this.pokemon, move); failedDueToWeather = globalScene.arena.isMoveWeatherCancelled(this.pokemon, move);
@ -517,7 +517,8 @@ export class MovePhase extends BattlePhase {
// Handle interaction between the rage powder center-of-attention tag and moves used by grass types/overcoat-havers (which are immune to RP's redirect) // Handle interaction between the rage powder center-of-attention tag and moves used by grass types/overcoat-havers (which are immune to RP's redirect)
if ( if (
redirectTag && redirectTag &&
(!redirectTag.powder || (!this.pokemon.isOfType(PokemonType.GRASS) && !this.pokemon.hasAbility(Abilities.OVERCOAT))) (!redirectTag.powder ||
(!this.pokemon.isOfType(PokemonType.GRASS) && !this.pokemon.hasAbility(Abilities.OVERCOAT)))
) { ) {
redirectTarget.value = p.getBattlerIndex(); redirectTarget.value = p.getBattlerIndex();
redirectedByAbility = false; redirectedByAbility = false;

View File

@ -221,10 +221,6 @@ export class MysteryEncounterOptionSelectedPhase extends Phase {
* See {@linkcode TurnEndPhase} for more details * See {@linkcode TurnEndPhase} for more details
*/ */
export class MysteryEncounterBattleStartCleanupPhase extends Phase { export class MysteryEncounterBattleStartCleanupPhase extends Phase {
constructor() {
super();
}
/** /**
* Cleans up `TURN_END` tags, any {@linkcode PostTurnStatusEffectPhase}s, checks for Pokemon switches, then continues * Cleans up `TURN_END` tags, any {@linkcode PostTurnStatusEffectPhase}s, checks for Pokemon switches, then continues
*/ */
@ -250,7 +246,7 @@ export class MysteryEncounterBattleStartCleanupPhase extends Phase {
}); });
// Remove any status tick phases // Remove any status tick phases
while (!!globalScene.findPhase(p => p instanceof PostTurnStatusEffectPhase)) { while (globalScene.findPhase(p => p instanceof PostTurnStatusEffectPhase)) {
globalScene.tryRemovePhase(p => p instanceof PostTurnStatusEffectPhase); globalScene.tryRemovePhase(p => p instanceof PostTurnStatusEffectPhase);
} }

View File

@ -24,7 +24,7 @@ export class RevivalBlessingPhase extends BattlePhase {
Mode.PARTY, Mode.PARTY,
PartyUiMode.REVIVAL_BLESSING, PartyUiMode.REVIVAL_BLESSING,
this.user.getFieldIndex(), this.user.getFieldIndex(),
(slotIndex: integer, option: PartyOption) => { (slotIndex: integer, _option: PartyOption) => {
if (slotIndex >= 0 && slotIndex < 6) { if (slotIndex >= 0 && slotIndex < 6) {
const pokemon = globalScene.getPlayerParty()[slotIndex]; const pokemon = globalScene.getPlayerParty()[slotIndex];
if (!pokemon || !pokemon.isFainted()) { if (!pokemon || !pokemon.isFainted()) {

View File

@ -51,7 +51,7 @@ export class SelectBiomePhase extends BattlePhase {
? [biomeLinks[currentBiome] as Biome] ? [biomeLinks[currentBiome] as Biome]
: (biomeLinks[currentBiome] as (Biome | [Biome, number])[]) : (biomeLinks[currentBiome] as (Biome | [Biome, number])[])
) )
.filter((b, i) => !Array.isArray(b) || !Utils.randSeedInt(b[1])) .filter((b, _i) => !Array.isArray(b) || !Utils.randSeedInt(b[1]))
.map(b => (Array.isArray(b) ? b[0] : b)); .map(b => (Array.isArray(b) ? b[0] : b));
}, globalScene.currentBattle.waveIndex); }, globalScene.currentBattle.waveIndex);
const biomeSelectItems = biomeChoices.map(b => { const biomeSelectItems = biomeChoices.map(b => {

View File

@ -74,7 +74,7 @@ export class SelectModifierPhase extends BattlePhase {
} }
// If custom modifiers are specified, overrides default item count // If custom modifiers are specified, overrides default item count
if (!!this.customModifierSettings) { if (this.customModifierSettings) {
const newItemCount = const newItemCount =
(this.customModifierSettings.guaranteedModifierTiers?.length || 0) + (this.customModifierSettings.guaranteedModifierTiers?.length || 0) +
(this.customModifierSettings.guaranteedModifierTypeOptions?.length || 0) + (this.customModifierSettings.guaranteedModifierTypeOptions?.length || 0) +

View File

@ -185,7 +185,7 @@ export class StatStageChangePhase extends PokemonPhase {
: Math.max(pokemon.getStatStage(s) + stages.value, -6)) - pokemon.getStatStage(s), : Math.max(pokemon.getStatStage(s) + stages.value, -6)) - pokemon.getStatStage(s),
); );
this.onChange && this.onChange(this.getPokemon(), filteredStats, relLevels); this.onChange?.(this.getPokemon(), filteredStats, relLevels);
const end = () => { const end = () => {
if (this.showMessage) { if (this.showMessage) {

View File

@ -221,7 +221,7 @@ export class TurnStartPhase extends FieldPhase {
let runningPokemon = pokemon; let runningPokemon = pokemon;
if (globalScene.currentBattle.double) { if (globalScene.currentBattle.double) {
const playerActivePokemon = field.filter(pokemon => { const playerActivePokemon = field.filter(pokemon => {
if (!!pokemon) { if (pokemon) {
return pokemon.isPlayer() && pokemon.isActive(); return pokemon.isPlayer() && pokemon.isActive();
} }
return; return;

View File

@ -265,31 +265,30 @@ export interface StarterPreferences {
const StarterPrefers_DEFAULT: string = "{}"; const StarterPrefers_DEFAULT: string = "{}";
let StarterPrefers_private_latest: string = StarterPrefers_DEFAULT; let StarterPrefers_private_latest: string = StarterPrefers_DEFAULT;
// called on starter selection show once
export function loadStarterPreferences(): StarterPreferences {
return JSON.parse(
(StarterPrefers_private_latest =
localStorage.getItem(`starterPrefs_${loggedInUser?.username}`) || StarterPrefers_DEFAULT),
);
}
// called on starter selection clear, always
export function saveStarterPreferences(prefs: StarterPreferences): void {
const pStr: string = JSON.stringify(prefs);
if (pStr !== StarterPrefers_private_latest) {
// something changed, store the update
localStorage.setItem(`starterPrefs_${loggedInUser?.username}`, pStr);
// update the latest prefs
StarterPrefers_private_latest = pStr;
}
}
// This is its own class as StarterPreferences... // This is its own class as StarterPreferences...
// - don't need to be loaded on startup // - don't need to be loaded on startup
// - isn't stored with other data // - isn't stored with other data
// - don't require to be encrypted // - don't require to be encrypted
// - shouldn't require calls outside of the starter selection // - shouldn't require calls outside of the starter selection
export class StarterPrefs { export class StarterPrefs {}
// called on starter selection show once
static load(): StarterPreferences {
return JSON.parse(
(StarterPrefers_private_latest =
localStorage.getItem(`starterPrefs_${loggedInUser?.username}`) || StarterPrefers_DEFAULT),
);
}
// called on starter selection clear, always
static save(prefs: StarterPreferences): void {
const pStr: string = JSON.stringify(prefs);
if (pStr !== StarterPrefers_private_latest) {
// something changed, store the update
localStorage.setItem(`starterPrefs_${loggedInUser?.username}`, pStr);
// update the latest prefs
StarterPrefers_private_latest = pStr;
}
}
}
export interface StarterDataEntry { export interface StarterDataEntry {
moveset: StarterMoveset | StarterFormMoveData | null; moveset: StarterMoveset | StarterFormMoveData | null;
@ -424,7 +423,7 @@ export class GameData {
const data = this.getSystemSaveData(); const data = this.getSystemSaveData();
const maxIntAttrValue = 0x80000000; const maxIntAttrValue = 0x80000000;
const systemData = JSON.stringify(data, (k: any, v: any) => const systemData = JSON.stringify(data, (_k: any, v: any) =>
typeof v === "bigint" ? (v <= maxIntAttrValue ? Number(v) : v.toString()) : v, typeof v === "bigint" ? (v <= maxIntAttrValue ? Number(v) : v.toString()) : v,
); );
@ -1319,7 +1318,7 @@ export class GameData {
} }
localStorage.removeItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`); localStorage.removeItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`);
} else { } else {
if (jsonResponse && jsonResponse.error?.startsWith("session out of date")) { if (jsonResponse?.error?.startsWith("session out of date")) {
globalScene.clearPhaseQueue(); globalScene.clearPhaseQueue();
globalScene.unshiftPhase(new ReloadSessionPhase()); globalScene.unshiftPhase(new ReloadSessionPhase());
} }
@ -1439,7 +1438,7 @@ export class GameData {
localStorage.setItem( localStorage.setItem(
`data_${loggedInUser?.username}`, `data_${loggedInUser?.username}`,
encrypt( encrypt(
JSON.stringify(systemData, (k: any, v: any) => JSON.stringify(systemData, (_k: any, v: any) =>
typeof v === "bigint" ? (v <= maxIntAttrValue ? Number(v) : v.toString()) : v, typeof v === "bigint" ? (v <= maxIntAttrValue ? Number(v) : v.toString()) : v,
), ),
bypassLogin, bypassLogin,
@ -1636,11 +1635,9 @@ export class GameData {
`An error occurred while updating ${dataName} data. Please contact the administrator.`, `An error occurred while updating ${dataName} data. Please contact the administrator.`,
); );
} }
window.location = window.location;
}); });
}); });
} else { } else {
window.location = window.location;
} }
}, },
() => { () => {
@ -2108,7 +2105,7 @@ export class GameData {
return ret; return ret;
} }
getSpeciesDexAttrProps(species: PokemonSpecies, dexAttr: bigint): DexAttrProps { getSpeciesDexAttrProps(_species: PokemonSpecies, dexAttr: bigint): DexAttrProps {
const shiny = !(dexAttr & DexAttr.NON_SHINY); const shiny = !(dexAttr & DexAttr.NON_SHINY);
const female = !(dexAttr & DexAttr.MALE); const female = !(dexAttr & DexAttr.MALE);
let variant: Variant = 0; let variant: Variant = 0;

View File

@ -28,7 +28,7 @@ export default class ModifierData {
this.className = sourceModifier ? sourceModifier.constructor.name : source.className; this.className = sourceModifier ? sourceModifier.constructor.name : source.className;
} }
toModifier(constructor: any): PersistentModifier | null { toModifier(_constructor: any): PersistentModifier | null {
const typeFunc = getModifierTypeFuncById(this.typeId); const typeFunc = getModifierTypeFuncById(this.typeId);
if (!typeFunc) { if (!typeFunc) {
return null; return null;
@ -46,7 +46,7 @@ export default class ModifierData {
} }
const ret = Reflect.construct( const ret = Reflect.construct(
constructor, _constructor,
([type] as any[]).concat(this.args).concat(this.stackCount), ([type] as any[]).concat(this.args).concat(this.stackCount),
) as PersistentModifier; ) as PersistentModifier;

View File

@ -14,7 +14,8 @@ export const systemMigrators = [
Object.keys(data.starterData).forEach(sd => { Object.keys(data.starterData).forEach(sd => {
const caughtAttr = data.dexData[sd]?.caughtAttr; const caughtAttr = data.dexData[sd]?.caughtAttr;
const speciesNumber = Number(sd); const speciesNumber = Number(sd);
if (!speciesNumber) { // An unknown bug at some point in time caused some accounts to have starter data for pokedex number 0 which crashes if (!speciesNumber) {
// An unknown bug at some point in time caused some accounts to have starter data for pokedex number 0 which crashes
return; return;
} }
const species = getPokemonSpecies(speciesNumber); const species = getPokemonSpecies(speciesNumber);

View File

@ -31,10 +31,10 @@ export class Voucher {
/** /**
* Get the name of the voucher * Get the name of the voucher
* @param playerGender - this is ignored here. It's only there to match the signature of the function in the Achv class * @param _playerGender - this is ignored here. It's only there to match the signature of the function in the Achv class
* @returns the name of the voucher * @returns the name of the voucher
*/ */
getName(playerGender: PlayerGender): string { getName(_playerGender: PlayerGender): string {
return getVoucherTypeName(this.voucherType); return getVoucherTypeName(this.voucherType);
} }

View File

@ -128,7 +128,7 @@ export default class AchvBar extends Phaser.GameObjects.Container {
this.shown = true; this.shown = true;
} }
protected hide(playerGender: PlayerGender): void { protected hide(_playerGender: PlayerGender): void {
if (!this.shown) { if (!this.shown) {
return; return;
} }

View File

@ -215,7 +215,7 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
globalScene.eventTarget.addEventListener(BattleSceneEventType.TURN_END, this.onTurnEndEvent); globalScene.eventTarget.addEventListener(BattleSceneEventType.TURN_END, this.onTurnEndEvent);
} }
private onNewArena(event: Event) { private onNewArena(_event: Event) {
this.fieldEffectInfo.length = 0; this.fieldEffectInfo.length = 0;
// Subscribes to required events available on battle start // Subscribes to required events available on battle start
@ -282,7 +282,7 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
let foundIndex: number; let foundIndex: number;
switch (arenaEffectChangedEvent.constructor) { switch (arenaEffectChangedEvent.constructor) {
case TagAddedEvent: case TagAddedEvent: {
const tagAddedEvent = arenaEffectChangedEvent as TagAddedEvent; const tagAddedEvent = arenaEffectChangedEvent as TagAddedEvent;
const isArenaTrapTag = globalScene.arena.getTag(tagAddedEvent.arenaTagType) instanceof ArenaTrapTag; const isArenaTrapTag = globalScene.arena.getTag(tagAddedEvent.arenaTagType) instanceof ArenaTrapTag;
let arenaEffectType: ArenaEffectType; let arenaEffectType: ArenaEffectType;
@ -321,7 +321,8 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
tagType: tagAddedEvent.arenaTagType, tagType: tagAddedEvent.arenaTagType,
}); });
break; break;
case TagRemovedEvent: }
case TagRemovedEvent: {
const tagRemovedEvent = arenaEffectChangedEvent as TagRemovedEvent; const tagRemovedEvent = arenaEffectChangedEvent as TagRemovedEvent;
foundIndex = this.fieldEffectInfo.findIndex(info => info.tagType === tagRemovedEvent.arenaTagType); foundIndex = this.fieldEffectInfo.findIndex(info => info.tagType === tagRemovedEvent.arenaTagType);
@ -330,9 +331,10 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
this.fieldEffectInfo.splice(foundIndex, 1); this.fieldEffectInfo.splice(foundIndex, 1);
} }
break; break;
}
case WeatherChangedEvent: case WeatherChangedEvent:
case TerrainChangedEvent: case TerrainChangedEvent: {
const fieldEffectChangedEvent = arenaEffectChangedEvent as WeatherChangedEvent | TerrainChangedEvent; const fieldEffectChangedEvent = arenaEffectChangedEvent as WeatherChangedEvent | TerrainChangedEvent;
// Stores the old Weather/Terrain name in case it's in the array already // Stores the old Weather/Terrain name in case it's in the array already
@ -365,6 +367,7 @@ export class ArenaFlyout extends Phaser.GameObjects.Container {
this.fieldEffectInfo[foundIndex] = newInfo; // Otherwise, replace the old info this.fieldEffectInfo[foundIndex] = newInfo; // Otherwise, replace the old info
} }
break; break;
}
} }
this.updateFieldText(); this.updateFieldText();

View File

@ -107,12 +107,12 @@ export class BaseStatsOverlay extends Phaser.GameObjects.Container implements In
} }
// width of this element // width of this element
static getWidth(scale: number): number { static getWidth(_scale: number): number {
return globalScene.game.canvas.width / GLOBAL_SCALE / 2; return globalScene.game.canvas.width / GLOBAL_SCALE / 2;
} }
// height of this element // height of this element
static getHeight(scale: number, onSide?: boolean): number { static getHeight(scale: number, _onSide?: boolean): number {
return HEIGHT * scale; return HEIGHT * scale;
} }
} }

View File

@ -958,5 +958,5 @@ export class EnemyBattleInfo extends BattleInfo {
super(140, -141, false); super(140, -141, false);
} }
setMini(mini: boolean): void {} // Always mini setMini(_mini: boolean): void {} // Always mini
} }

View File

@ -197,7 +197,8 @@ export default class CommandUiHandler extends UiHandler {
canTera(): boolean { canTera(): boolean {
const hasTeraMod = !!globalScene.getModifiers(TerastallizeAccessModifier).length; const hasTeraMod = !!globalScene.getModifiers(TerastallizeAccessModifier).length;
const activePokemon = globalScene.getField()[this.fieldIndex]; const activePokemon = globalScene.getField()[this.fieldIndex];
const isBlockedForm = activePokemon.isMega() || activePokemon.isMax() || activePokemon.hasSpecies(Species.NECROZMA, "ultra"); const isBlockedForm =
activePokemon.isMega() || activePokemon.isMax() || activePokemon.hasSpecies(Species.NECROZMA, "ultra");
const currentTeras = globalScene.arena.playerTerasUsed; const currentTeras = globalScene.arena.playerTerasUsed;
const plannedTera = const plannedTera =
globalScene.currentBattle.preTurnCommands[0]?.command === Command.TERA && this.fieldIndex > 0 ? 1 : 0; globalScene.currentBattle.preTurnCommands[0]?.command === Command.TERA && this.fieldIndex > 0 ? 1 : 0;

View File

@ -158,8 +158,8 @@ export default class LoginFormUiHandler extends FormModalUiHandler {
const [usernameInput, passwordInput] = this.inputs; const [usernameInput, passwordInput] = this.inputs;
pokerogueApi.account.login({ username: usernameInput.text, password: passwordInput.text }).then(error => { pokerogueApi.account.login({ username: usernameInput.text, password: passwordInput.text }).then(error => {
if (!error) { if (!error && originalLoginAction) {
originalLoginAction && originalLoginAction(); originalLoginAction();
} else { } else {
onFail(error); onFail(error);
} }

View File

@ -47,7 +47,7 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler {
showDialogue( showDialogue(
text: string, text: string,
name?: string, _name?: string,
delay?: number | null, delay?: number | null,
callback?: Function | null, callback?: Function | null,
callbackDelay?: number | null, callbackDelay?: number | null,

View File

@ -168,7 +168,7 @@ export abstract class ModalUiHandler extends UiHandler {
} }
} }
processInput(button: Button): boolean { processInput(_button: Button): boolean {
return false; return false;
} }

View File

@ -173,7 +173,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
return false; return false;
} }
if (args.length !== 4 || !(args[1] instanceof Array) || !(args[2] instanceof Function)) { if (args.length !== 4 || !Array.isArray(args[1]) || !(args[2] instanceof Function)) {
return false; return false;
} }

View File

@ -233,7 +233,7 @@ export default class MoveInfoOverlay extends Phaser.GameObjects.Container implem
} }
// width of this element // width of this element
static getWidth(scale: number): number { static getWidth(_scale: number): number {
return globalScene.game.canvas.width / GLOBAL_SCALE / 2; return globalScene.game.canvas.width / GLOBAL_SCALE / 2;
} }

View File

@ -168,6 +168,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
} }
} else { } else {
switch (this.optionsContainer.getAll()?.length) { switch (this.optionsContainer.getAll()?.length) {
// biome-ignore lint/suspicious/useDefaultSwitchClauseLast: Default shares logic with case 3 and it makes more sense for the statements to be ordered by the case value
default: default:
case 3: case 3:
success = this.handleTwoOptionMoveInput(button); success = this.handleTwoOptionMoveInput(button);
@ -376,6 +377,7 @@ export default class MysteryEncounterUiHandler extends UiHandler {
let optionText: BBCodeText; let optionText: BBCodeText;
switch (this.encounterOptions.length) { switch (this.encounterOptions.length) {
// biome-ignore lint/suspicious/useDefaultSwitchClauseLast: default shares logic with case 2 and it makes more sense for the statements to be ordered by the case number
default: default:
case 2: case 2:
optionText = addBBCodeTextObject(i % 2 === 0 ? 0 : 100, 8, "-", TextStyle.WINDOW, { optionText = addBBCodeTextObject(i % 2 === 0 ? 0 : 100, 8, "-", TextStyle.WINDOW, {

View File

@ -572,7 +572,7 @@ export default class PartyUiHandler extends MessageUiHandler {
shiny: pokemon.shiny, shiny: pokemon.shiny,
variant: pokemon.variant, variant: pokemon.variant,
form: pokemon.formIndex, form: pokemon.formIndex,
female: pokemon.gender === Gender.FEMALE ? true : false, female: pokemon.gender === Gender.FEMALE,
}; };
ui.setOverlayMode(Mode.POKEDEX_PAGE, pokemon.species, pokemon.formIndex, attributes).then(() => ui.setOverlayMode(Mode.POKEDEX_PAGE, pokemon.species, pokemon.formIndex, attributes).then(() =>
this.clearOptions(), this.clearOptions(),
@ -1301,7 +1301,7 @@ export default class PartyUiHandler extends MessageUiHandler {
if (this.partyUiMode === PartyUiMode.RELEASE) { if (this.partyUiMode === PartyUiMode.RELEASE) {
const selectCallback = this.selectCallback; const selectCallback = this.selectCallback;
this.selectCallback = null; this.selectCallback = null;
selectCallback && selectCallback(this.cursor, PartyOption.RELEASE); selectCallback?.(this.cursor, PartyOption.RELEASE);
} }
this.showText("", 0); this.showText("", 0);
}, },

View File

@ -168,12 +168,12 @@ export default class PokedexInfoOverlay extends Phaser.GameObjects.Container imp
} }
// width of this element // width of this element
static getWidth(scale: number): number { static getWidth(_scale: number): number {
return globalScene.game.canvas.width / GLOBAL_SCALE / 2; return globalScene.game.canvas.width / GLOBAL_SCALE / 2;
} }
// height of this element // height of this element
static getHeight(scale: number, onSide?: boolean): number { static getHeight(scale: number, _onSide?: boolean): number {
return DESC_HEIGHT * scale; return DESC_HEIGHT * scale;
} }
} }

View File

@ -763,7 +763,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
this.tmMoves = this.tmMoves =
speciesTmMoves[species.speciesId] speciesTmMoves[species.speciesId]
?.filter(m => (Array.isArray(m) ? (m[0] === formKey ? true : false) : true)) ?.filter(m => (Array.isArray(m) ? m[0] === formKey : true))
.map(m => (Array.isArray(m) ? m[1] : m)) .map(m => (Array.isArray(m) ? m[1] : m))
.sort((a, b) => (allMoves[a].name > allMoves[b].name ? 1 : -1)) ?? []; .sort((a, b) => (allMoves[a].name > allMoves[b].name ? 1 : -1)) ?? [];
@ -1539,7 +1539,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
}); });
this.evolutions.map(evo => { this.evolutions.map(evo => {
const evoSpecies = allSpecies.find(species => species.speciesId === evo.speciesId); const evoSpecies = allSpecies.find(species => species.speciesId === evo.speciesId);
const isCaughtEvo = this.isCaught(evoSpecies) ? true : false; const isCaughtEvo = !!this.isCaught(evoSpecies);
// Attempts to find the formIndex of the evolved species // Attempts to find the formIndex of the evolved species
const newFormKey = evo.evoFormKey const newFormKey = evo.evoFormKey
? evo.evoFormKey ? evo.evoFormKey
@ -1664,7 +1664,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
const natures = globalScene.gameData.getNaturesForAttr(this.speciesStarterDexEntry?.natureAttr); const natures = globalScene.gameData.getNaturesForAttr(this.speciesStarterDexEntry?.natureAttr);
ui.setModeWithoutClear(Mode.OPTION_SELECT, { ui.setModeWithoutClear(Mode.OPTION_SELECT, {
options: natures options: natures
.map((n: Nature, i: number) => { .map((n: Nature, _i: number) => {
const option: OptionSelectItem = { const option: OptionSelectItem = {
label: getNatureName(n, true, true, true, globalScene.uiTheme), label: getNatureName(n, true, true, true, globalScene.uiTheme),
handler: () => { handler: () => {
@ -2029,6 +2029,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
} }
updateButtonIcon(iconSetting, gamepadType, iconElement, controlLabel): void { updateButtonIcon(iconSetting, gamepadType, iconElement, controlLabel): void {
// biome-ignore lint/suspicious/noImplicitAnyLet: TODO
let iconPath; let iconPath;
// touch controls cannot be rebound as is, and are just emulating a keyboard event. // touch controls cannot be rebound as is, and are just emulating a keyboard event.
// Additionally, since keyboard controls can be rebound (and will be displayed when they are), we need to have special handling for the touch controls // Additionally, since keyboard controls can be rebound (and will be displayed when they are), we need to have special handling for the touch controls
@ -2074,6 +2075,8 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
this.hideInstructions(); this.hideInstructions();
this.instructionsContainer.removeAll(); this.instructionsContainer.removeAll();
this.filterInstructionsContainer.removeAll(); this.filterInstructionsContainer.removeAll();
// biome-ignore lint/suspicious/noImplicitAnyLet: TODO
let gamepadType; let gamepadType;
if (globalScene.inputMethod === "gamepad") { if (globalScene.inputMethod === "gamepad") {
gamepadType = globalScene.inputController.getConfig( gamepadType = globalScene.inputController.getConfig(
@ -2166,7 +2169,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
return ret; return ret;
} }
getFriendship(speciesId: number) { getFriendship(_speciesId: number) {
let currentFriendship = globalScene.gameData.starterData[this.starterId].friendship; let currentFriendship = globalScene.gameData.starterData[this.starterId].friendship;
if (!currentFriendship || currentFriendship === undefined) { if (!currentFriendship || currentFriendship === undefined) {
currentFriendship = 0; currentFriendship = 0;
@ -2399,7 +2402,7 @@ export default class PokedexPageUiHandler extends MessageUiHandler {
this.assetLoadCancelled = assetLoadCancelled; this.assetLoadCancelled = assetLoadCancelled;
if (shouldUpdateSprite) { if (shouldUpdateSprite) {
const back = this.showBackSprite ? true : false; const back = !!this.showBackSprite;
species.loadAssets(female!, formIndex, shiny, variant as Variant, true, back).then(() => { species.loadAssets(female!, formIndex, shiny, variant as Variant, true, back).then(() => {
// TODO: is this bang correct? // TODO: is this bang correct?
if (assetLoadCancelled.value) { if (assetLoadCancelled.value) {

View File

@ -20,10 +20,6 @@ export default class PokedexScanUiHandler extends FormModalUiHandler {
abilityKeys: string[]; abilityKeys: string[];
row: number; row: number;
constructor(mode) {
super(mode);
}
setup() { setup() {
super.setup(); super.setup();
@ -32,19 +28,19 @@ export default class PokedexScanUiHandler extends FormModalUiHandler {
this.abilityKeys = allAbilities.map(a => a.name); this.abilityKeys = allAbilities.map(a => a.name);
} }
getModalTitle(config?: ModalConfig): string { getModalTitle(_config?: ModalConfig): string {
return i18next.t("pokedexUiHandler:scanChooseOption"); return i18next.t("pokedexUiHandler:scanChooseOption");
} }
getWidth(config?: ModalConfig): number { getWidth(_config?: ModalConfig): number {
return 300; return 300;
} }
getMargin(config?: ModalConfig): [number, number, number, number] { getMargin(_config?: ModalConfig): [number, number, number, number] {
return [0, 0, 48, 0]; return [0, 0, 48, 0];
} }
getButtonLabels(config?: ModalConfig): string[] { getButtonLabels(_config?: ModalConfig): string[] {
return [i18next.t("pokedexUiHandler:scanSelect"), i18next.t("pokedexUiHandler:scanCancel")]; return [i18next.t("pokedexUiHandler:scanSelect"), i18next.t("pokedexUiHandler:scanCancel")];
} }

View File

@ -12,7 +12,7 @@ import { getStarterValueFriendshipCap, speciesStarterCosts, POKERUS_STARTER_COUN
import { catchableSpecies } from "#app/data/balance/biomes"; import { catchableSpecies } from "#app/data/balance/biomes";
import { PokemonType } from "#enums/pokemon-type"; import { PokemonType } from "#enums/pokemon-type";
import type { DexAttrProps, DexEntry, StarterAttributes, StarterPreferences } from "#app/system/game-data"; import type { DexAttrProps, DexEntry, StarterAttributes, StarterPreferences } from "#app/system/game-data";
import { AbilityAttr, DexAttr, StarterPrefs } from "#app/system/game-data"; import { AbilityAttr, DexAttr, loadStarterPreferences, saveStarterPreferences } from "#app/system/game-data";
import MessageUiHandler from "#app/ui/message-ui-handler"; import MessageUiHandler from "#app/ui/message-ui-handler";
import PokemonIconAnimHandler, { PokemonIconAnimMode } from "#app/ui/pokemon-icon-anim-handler"; import PokemonIconAnimHandler, { PokemonIconAnimMode } from "#app/ui/pokemon-icon-anim-handler";
import { TextStyle, addTextObject } from "#app/ui/text"; import { TextStyle, addTextObject } from "#app/ui/text";
@ -612,7 +612,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
show(args: any[]): boolean { show(args: any[]): boolean {
if (!this.starterPreferences) { if (!this.starterPreferences) {
this.starterPreferences = StarterPrefs.load(); this.starterPreferences = loadStarterPreferences();
} }
this.pokerusSpecies = getPokerusStarters(); this.pokerusSpecies = getPokerusStarters();
@ -675,11 +675,12 @@ export default class PokedexUiHandler extends MessageUiHandler {
const hasNonShiny = caughtAttr & DexAttr.NON_SHINY; const hasNonShiny = caughtAttr & DexAttr.NON_SHINY;
if (starterAttributes.shiny && !hasShiny) { if (starterAttributes.shiny && !hasShiny) {
// shiny form wasn't unlocked, purging shiny and variant setting // shiny form wasn't unlocked, purging shiny and variant setting
delete starterAttributes.shiny;
delete starterAttributes.variant; starterAttributes.shiny = undefined;
starterAttributes.variant = undefined;
} else if (starterAttributes.shiny === false && !hasNonShiny) { } else if (starterAttributes.shiny === false && !hasNonShiny) {
// non shiny form wasn't unlocked, purging shiny setting // non shiny form wasn't unlocked, purging shiny setting
delete starterAttributes.shiny; starterAttributes.shiny = undefined;
} }
if (starterAttributes.variant !== undefined) { if (starterAttributes.variant !== undefined) {
@ -694,14 +695,14 @@ export default class PokedexUiHandler extends MessageUiHandler {
!unlockedVariants[starterAttributes.variant] !unlockedVariants[starterAttributes.variant]
) { ) {
// variant value is invalid or requested variant wasn't unlocked, purging setting // variant value is invalid or requested variant wasn't unlocked, purging setting
delete starterAttributes.variant; starterAttributes.variant = undefined;
} }
} }
if (starterAttributes.female !== undefined) { if (starterAttributes.female !== undefined) {
if (!(starterAttributes.female ? caughtAttr & DexAttr.FEMALE : caughtAttr & DexAttr.MALE)) { if (!(starterAttributes.female ? caughtAttr & DexAttr.FEMALE : caughtAttr & DexAttr.MALE)) {
// requested gender wasn't unlocked, purging setting // requested gender wasn't unlocked, purging setting
delete starterAttributes.female; starterAttributes.female = undefined;
} }
} }
@ -720,7 +721,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
]; ];
if (!unlockedAbilities[starterAttributes.ability]) { if (!unlockedAbilities[starterAttributes.ability]) {
// requested ability wasn't unlocked, purging setting // requested ability wasn't unlocked, purging setting
delete starterAttributes.ability; starterAttributes.ability = undefined;
} }
} }
@ -731,14 +732,14 @@ export default class PokedexUiHandler extends MessageUiHandler {
!(caughtAttr & globalScene.gameData.getFormAttr(selectedForm))) !(caughtAttr & globalScene.gameData.getFormAttr(selectedForm)))
) { ) {
// requested form wasn't unlocked/isn't a starter form, purging setting // requested form wasn't unlocked/isn't a starter form, purging setting
delete starterAttributes.form; starterAttributes.form = undefined;
} }
if (starterAttributes.nature !== undefined) { if (starterAttributes.nature !== undefined) {
const unlockedNatures = globalScene.gameData.getNaturesForAttr(dexEntry.natureAttr); const unlockedNatures = globalScene.gameData.getNaturesForAttr(dexEntry.natureAttr);
if (unlockedNatures.indexOf(starterAttributes.nature as unknown as Nature) < 0) { if (unlockedNatures.indexOf(starterAttributes.nature as unknown as Nature) < 0) {
// requested nature wasn't unlocked, purging setting // requested nature wasn't unlocked, purging setting
delete starterAttributes.nature; starterAttributes.nature = undefined;
} }
} }
@ -1236,12 +1237,13 @@ export default class PokedexUiHandler extends MessageUiHandler {
success = true; success = true;
} }
break; break;
case Button.CYCLE_FORM: case Button.CYCLE_FORM: {
const species = this.pokemonContainers[this.cursor].species; const species = this.pokemonContainers[this.cursor].species;
if (this.canShowFormTray) { if (this.canShowFormTray) {
success = this.openFormTray(species); success = this.openFormTray(species);
} }
break; break;
}
} }
} }
} }
@ -1256,6 +1258,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
} }
updateButtonIcon(iconSetting, gamepadType, iconElement, controlLabel): void { updateButtonIcon(iconSetting, gamepadType, iconElement, controlLabel): void {
// biome-ignore lint/suspicious/noImplicitAnyLet: TODO
let iconPath; let iconPath;
// touch controls cannot be rebound as is, and are just emulating a keyboard event. // touch controls cannot be rebound as is, and are just emulating a keyboard event.
// Additionally, since keyboard controls can be rebound (and will be displayed when they are), we need to have special handling for the touch controls // Additionally, since keyboard controls can be rebound (and will be displayed when they are), we need to have special handling for the touch controls
@ -1283,6 +1286,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
} }
updateFilterButtonIcon(iconSetting, gamepadType, iconElement, controlLabel): void { updateFilterButtonIcon(iconSetting, gamepadType, iconElement, controlLabel): void {
// biome-ignore lint/suspicious/noImplicitAnyLet: TODO
let iconPath; let iconPath;
// touch controls cannot be rebound as is, and are just emulating a keyboard event. // touch controls cannot be rebound as is, and are just emulating a keyboard event.
// Additionally, since keyboard controls can be rebound (and will be displayed when they are), we need to have special handling for the touch controls // Additionally, since keyboard controls can be rebound (and will be displayed when they are), we need to have special handling for the touch controls
@ -1461,8 +1465,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
if (biomes.length === 0) { if (biomes.length === 0) {
biomes.push("Uncatchable"); biomes.push("Uncatchable");
} }
const showNoBiome = const showNoBiome = !!(biomes.length === 0 && this.filterBar.getVals(DropDownColumn.BIOME).length === 36);
biomes.length === 0 && this.filterBar.getVals(DropDownColumn.BIOME).length === 36 ? true : false;
const fitsBiome = const fitsBiome =
this.filterBar.getVals(DropDownColumn.BIOME).some(item => biomes.includes(indexToBiome.get(item) ?? "")) || this.filterBar.getVals(DropDownColumn.BIOME).some(item => biomes.includes(indexToBiome.get(item) ?? "")) ||
showNoBiome; showNoBiome;
@ -1650,19 +1653,18 @@ export default class PokedexUiHandler extends MessageUiHandler {
const sort = this.filterBar.getVals(DropDownColumn.SORT)[0]; const sort = this.filterBar.getVals(DropDownColumn.SORT)[0];
this.filteredPokemonData.sort((a, b) => { this.filteredPokemonData.sort((a, b) => {
switch (sort.val) { switch (sort.val) {
default:
break;
case SortCriteria.NUMBER: case SortCriteria.NUMBER:
return (a.species.speciesId - b.species.speciesId) * -sort.dir; return (a.species.speciesId - b.species.speciesId) * -sort.dir;
case SortCriteria.COST: case SortCriteria.COST:
return (a.cost - b.cost) * -sort.dir; return (a.cost - b.cost) * -sort.dir;
case SortCriteria.CANDY: case SortCriteria.CANDY: {
const candyCountA = const candyCountA =
globalScene.gameData.starterData[this.getStarterSpeciesId(a.species.speciesId)].candyCount; globalScene.gameData.starterData[this.getStarterSpeciesId(a.species.speciesId)].candyCount;
const candyCountB = const candyCountB =
globalScene.gameData.starterData[this.getStarterSpeciesId(b.species.speciesId)].candyCount; globalScene.gameData.starterData[this.getStarterSpeciesId(b.species.speciesId)].candyCount;
return (candyCountA - candyCountB) * -sort.dir; return (candyCountA - candyCountB) * -sort.dir;
case SortCriteria.IV: }
case SortCriteria.IV: {
const avgIVsA = const avgIVsA =
globalScene.gameData.dexData[a.species.speciesId].ivs.reduce((a, b) => a + b, 0) / globalScene.gameData.dexData[a.species.speciesId].ivs.reduce((a, b) => a + b, 0) /
globalScene.gameData.dexData[a.species.speciesId].ivs.length; globalScene.gameData.dexData[a.species.speciesId].ivs.length;
@ -1670,6 +1672,7 @@ export default class PokedexUiHandler extends MessageUiHandler {
globalScene.gameData.dexData[b.species.speciesId].ivs.reduce((a, b) => a + b, 0) / globalScene.gameData.dexData[b.species.speciesId].ivs.reduce((a, b) => a + b, 0) /
globalScene.gameData.dexData[b.species.speciesId].ivs.length; globalScene.gameData.dexData[b.species.speciesId].ivs.length;
return (avgIVsA - avgIVsB) * -sort.dir; return (avgIVsA - avgIVsB) * -sort.dir;
}
case SortCriteria.NAME: case SortCriteria.NAME:
return a.species.name.localeCompare(b.species.name) * -sort.dir; return a.species.name.localeCompare(b.species.name) * -sort.dir;
case SortCriteria.CAUGHT: case SortCriteria.CAUGHT:
@ -1684,6 +1687,8 @@ export default class PokedexUiHandler extends MessageUiHandler {
globalScene.gameData.dexData[this.getStarterSpeciesId(b.species.speciesId)].hatchedCount) * globalScene.gameData.dexData[this.getStarterSpeciesId(b.species.speciesId)].hatchedCount) *
-sort.dir -sort.dir
); );
default:
break;
} }
return 0; return 0;
}); });

View File

@ -169,7 +169,9 @@ export default class PokemonHatchInfoContainer extends PokemonInfoContainer {
for (let em = 0; em < 4; em++) { for (let em = 0; em < 4; em++) {
const eggMove = hasEggMoves ? allMoves[speciesEggMoves[species.speciesId][em]] : null; const eggMove = hasEggMoves ? allMoves[speciesEggMoves[species.speciesId][em]] : null;
const eggMoveUnlocked = eggMove && globalScene.gameData.starterData[species.speciesId].eggMoves & Math.pow(2, em); const eggMoveUnlocked = eggMove && globalScene.gameData.starterData[species.speciesId].eggMoves & Math.pow(2, em);
this.pokemonEggMoveBgs[em].setFrame(PokemonType[eggMove ? eggMove.type : PokemonType.UNKNOWN].toString().toLowerCase()); this.pokemonEggMoveBgs[em].setFrame(
PokemonType[eggMove ? eggMove.type : PokemonType.UNKNOWN].toString().toLowerCase(),
);
this.pokemonEggMoveLabels[em].setText(eggMove && eggMoveUnlocked ? eggMove.name : "???"); this.pokemonEggMoveLabels[em].setText(eggMove && eggMoveUnlocked ? eggMove.name : "???");
if (!(eggMove && hatchInfo.starterDataEntryBeforeUpdate.eggMoves & Math.pow(2, em)) && eggMoveUnlocked) { if (!(eggMove && hatchInfo.starterDataEntryBeforeUpdate.eggMoves & Math.pow(2, em)) && eggMoveUnlocked) {

View File

@ -21,15 +21,15 @@ const languageSettings: { [key: string]: LanguageSetting } = {
}; };
export default class RegistrationFormUiHandler extends FormModalUiHandler { export default class RegistrationFormUiHandler extends FormModalUiHandler {
getModalTitle(config?: ModalConfig): string { getModalTitle(_config?: ModalConfig): string {
return i18next.t("menu:register"); return i18next.t("menu:register");
} }
getWidth(config?: ModalConfig): number { getWidth(_config?: ModalConfig): number {
return 160; return 160;
} }
getMargin(config?: ModalConfig): [number, number, number, number] { getMargin(_config?: ModalConfig): [number, number, number, number] {
return [0, 0, 48, 0]; return [0, 0, 48, 0];
} }
@ -37,7 +37,7 @@ export default class RegistrationFormUiHandler extends FormModalUiHandler {
return 8; return 8;
} }
getButtonLabels(config?: ModalConfig): string[] { getButtonLabels(_config?: ModalConfig): string[] {
return [i18next.t("menu:register"), i18next.t("menu:backToLogin")]; return [i18next.t("menu:register"), i18next.t("menu:backToLogin")];
} }
@ -134,7 +134,7 @@ export default class RegistrationFormUiHandler extends FormModalUiHandler {
}) })
.then(loginError => { .then(loginError => {
if (!loginError) { if (!loginError) {
originalRegistrationAction && originalRegistrationAction(); originalRegistrationAction?.();
} else { } else {
onFail(loginError); onFail(loginError);
} }

View File

@ -5,19 +5,19 @@ import i18next from "i18next";
import type { PlayerPokemon } from "#app/field/pokemon"; import type { PlayerPokemon } from "#app/field/pokemon";
export default class RenameFormUiHandler extends FormModalUiHandler { export default class RenameFormUiHandler extends FormModalUiHandler {
getModalTitle(config?: ModalConfig): string { getModalTitle(_config?: ModalConfig): string {
return i18next.t("menu:renamePokemon"); return i18next.t("menu:renamePokemon");
} }
getWidth(config?: ModalConfig): number { getWidth(_config?: ModalConfig): number {
return 160; return 160;
} }
getMargin(config?: ModalConfig): [number, number, number, number] { getMargin(_config?: ModalConfig): [number, number, number, number] {
return [0, 0, 48, 0]; return [0, 0, 48, 0];
} }
getButtonLabels(config?: ModalConfig): string[] { getButtonLabels(_config?: ModalConfig): string[] {
return [i18next.t("menu:rename"), i18next.t("menu:cancel")]; return [i18next.t("menu:rename"), i18next.t("menu:cancel")];
} }

View File

@ -113,16 +113,16 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
switch (this.uiMode) { switch (this.uiMode) {
case SaveSlotUiMode.LOAD: case SaveSlotUiMode.LOAD:
this.saveSlotSelectCallback = null; this.saveSlotSelectCallback = null;
originalCallback && originalCallback(cursor); originalCallback?.(cursor);
break; break;
case SaveSlotUiMode.SAVE: case SaveSlotUiMode.SAVE: {
const saveAndCallback = () => { const saveAndCallback = () => {
const originalCallback = this.saveSlotSelectCallback; const originalCallback = this.saveSlotSelectCallback;
this.saveSlotSelectCallback = null; this.saveSlotSelectCallback = null;
ui.revertMode(); ui.revertMode();
ui.showText("", 0); ui.showText("", 0);
ui.setMode(Mode.MESSAGE); ui.setMode(Mode.MESSAGE);
originalCallback && originalCallback(cursor); originalCallback?.(cursor);
}; };
if (this.sessionSlots[cursor].hasData) { if (this.sessionSlots[cursor].hasData) {
ui.showText(i18next.t("saveSlotSelectUiHandler:overwriteData"), null, () => { ui.showText(i18next.t("saveSlotSelectUiHandler:overwriteData"), null, () => {
@ -153,12 +153,13 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
return false; return false;
} }
break; break;
}
} }
success = true; success = true;
} }
} else { } else {
this.saveSlotSelectCallback = null; this.saveSlotSelectCallback = null;
originalCallback && originalCallback(-1); originalCallback?.(-1);
success = true; success = true;
} }
} else { } else {

View File

@ -43,7 +43,7 @@ export default class SessionReloadModalUiHandler extends ModalUiHandler {
this.modalContainer.add(label); this.modalContainer.add(label);
} }
show(args: any[]): boolean { show(_args: any[]): boolean {
const config: ModalConfig = { const config: ModalConfig = {
buttonActions: [], buttonActions: [],
}; };

View File

@ -123,7 +123,7 @@ export default abstract class AbstractBindingUiHandler extends UiHandler {
if (this.timeLeftAutoClose >= 0) { if (this.timeLeftAutoClose >= 0) {
this.manageAutoCloseTimer(); this.manageAutoCloseTimer();
} else { } else {
this.cancelFn && this.cancelFn(); this.cancelFn?.();
} }
}, 1000); }, 1000);
} }
@ -185,19 +185,19 @@ export default abstract class AbstractBindingUiHandler extends UiHandler {
let success = false; let success = false;
switch (button) { switch (button) {
case Button.LEFT: case Button.LEFT:
case Button.RIGHT: case Button.RIGHT: {
// Toggle between action and cancel options. // Toggle between action and cancel options.
const cursor = this.cursor ? 0 : 1; success = this.setCursor(this.cursor ? 0 : 1);
success = this.setCursor(cursor);
break; break;
}
case Button.ACTION: case Button.ACTION:
// Process actions based on current cursor position. // Process actions based on current cursor position.
if (this.cursor === 0) { if (this.cursor === 0) {
this.cancelFn && this.cancelFn(); this.cancelFn?.();
} else { } else {
success = this.swapAction(); success = this.swapAction();
NavigationManager.getInstance().updateIcons(); NavigationManager.getInstance().updateIcons();
this.cancelFn && this.cancelFn(success); this.cancelFn?.(success);
} }
break; break;
} }

View File

@ -47,7 +47,7 @@ export default class GamepadBindingUiHandler extends AbstractBindingUiHandler {
return globalScene.inputController?.selectedDevice[Device.GAMEPAD]; return globalScene.inputController?.selectedDevice[Device.GAMEPAD];
} }
gamepadButtonDown(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void { gamepadButtonDown(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, _value: number): void {
const blacklist = [12, 13, 14, 15]; // d-pad buttons are blacklisted. const blacklist = [12, 13, 14, 15]; // d-pad buttons are blacklisted.
// Check conditions before processing the button press. // Check conditions before processing the button press.
if ( if (

View File

@ -53,7 +53,7 @@ export default class MoveTouchControlsHandler {
this.touchControls = touchControls; this.touchControls = touchControls;
this.inConfigurationMode = false; this.inConfigurationMode = false;
this.setPositions(this.getSavedPositionsOfCurrentOrientation() ?? []); this.setPositions(this.getSavedPositionsOfCurrentOrientation() ?? []);
window.addEventListener("resize", event => { window.addEventListener("resize", _event => {
const screenSize = this.getScreenSize(); const screenSize = this.getScreenSize();
if (screenSize.width > screenSize.height !== this.isLandscapeMode) { if (screenSize.width > screenSize.height !== this.isLandscapeMode) {
this.changeOrientation(screenSize.width > screenSize.height); this.changeOrientation(screenSize.width > screenSize.height);

View File

@ -43,8 +43,8 @@ export default class SettingsKeyboardUiHandler extends AbstractControlSettingsUi
const deleteEvent = globalScene.input.keyboard?.addKey(Phaser.Input.Keyboard.KeyCodes.DELETE); const deleteEvent = globalScene.input.keyboard?.addKey(Phaser.Input.Keyboard.KeyCodes.DELETE);
const restoreDefaultEvent = globalScene.input.keyboard?.addKey(Phaser.Input.Keyboard.KeyCodes.HOME); const restoreDefaultEvent = globalScene.input.keyboard?.addKey(Phaser.Input.Keyboard.KeyCodes.HOME);
deleteEvent && deleteEvent.on("up", this.onDeleteDown, this); deleteEvent?.on("up", this.onDeleteDown, this);
restoreDefaultEvent && restoreDefaultEvent.on("up", this.onHomeDown, this); restoreDefaultEvent?.on("up", this.onHomeDown, this);
} }
setSetting = setSettingKeyboard; setSetting = setSettingKeyboard;

View File

@ -30,7 +30,7 @@ import type {
StarterAttributes, StarterAttributes,
StarterPreferences, StarterPreferences,
} from "#app/system/game-data"; } from "#app/system/game-data";
import { AbilityAttr, DexAttr, StarterPrefs } from "#app/system/game-data"; import { AbilityAttr, DexAttr, loadStarterPreferences, saveStarterPreferences } from "#app/system/game-data";
import { Tutorial, handleTutorial } from "#app/tutorial"; import { Tutorial, handleTutorial } from "#app/tutorial";
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import MessageUiHandler from "#app/ui/message-ui-handler"; import MessageUiHandler from "#app/ui/message-ui-handler";
@ -79,6 +79,7 @@ import type { Nature } from "#enums/nature";
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants"; import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
import { achvs } from "#app/system/achv"; import { achvs } from "#app/system/achv";
import * as Utils from "../utils"; import * as Utils from "../utils";
import type { GameObjects } from "phaser";
export type StarterSelectCallback = (starters: Starter[]) => void; export type StarterSelectCallback = (starters: Starter[]) => void;
@ -1174,7 +1175,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
show(args: any[]): boolean { show(args: any[]): boolean {
if (!this.starterPreferences) { if (!this.starterPreferences) {
// starterPreferences haven't been loaded yet // starterPreferences haven't been loaded yet
this.starterPreferences = StarterPrefs.load(); this.starterPreferences = loadStarterPreferences();
} }
this.moveInfoOverlay.clear(); // clear this when removing a menu; the cancel button doesn't seem to trigger this automatically on controllers this.moveInfoOverlay.clear(); // clear this when removing a menu; the cancel button doesn't seem to trigger this automatically on controllers
this.pokerusSpecies = getPokerusStarters(); this.pokerusSpecies = getPokerusStarters();
@ -1241,11 +1242,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
const hasNonShiny = caughtAttr & DexAttr.NON_SHINY; const hasNonShiny = caughtAttr & DexAttr.NON_SHINY;
if (starterAttributes.shiny && !hasShiny) { if (starterAttributes.shiny && !hasShiny) {
// shiny form wasn't unlocked, purging shiny and variant setting // shiny form wasn't unlocked, purging shiny and variant setting
delete starterAttributes.shiny; starterAttributes.shiny = undefined;
delete starterAttributes.variant; starterAttributes.variant = undefined;
} else if (starterAttributes.shiny === false && !hasNonShiny) { } else if (starterAttributes.shiny === false && !hasNonShiny) {
// non shiny form wasn't unlocked, purging shiny setting // non shiny form wasn't unlocked, purging shiny setting
delete starterAttributes.shiny; starterAttributes.shiny = undefined;
} }
if (starterAttributes.variant !== undefined) { if (starterAttributes.variant !== undefined) {
@ -1260,14 +1261,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
!unlockedVariants[starterAttributes.variant] !unlockedVariants[starterAttributes.variant]
) { ) {
// variant value is invalid or requested variant wasn't unlocked, purging setting // variant value is invalid or requested variant wasn't unlocked, purging setting
delete starterAttributes.variant; starterAttributes.variant = undefined;
} }
} }
if (starterAttributes.female !== undefined) { if (starterAttributes.female !== undefined) {
if (!(starterAttributes.female ? caughtAttr & DexAttr.FEMALE : caughtAttr & DexAttr.MALE)) { if (!(starterAttributes.female ? caughtAttr & DexAttr.FEMALE : caughtAttr & DexAttr.MALE)) {
// requested gender wasn't unlocked, purging setting // requested gender wasn't unlocked, purging setting
delete starterAttributes.female; starterAttributes.female = undefined;
} }
} }
@ -1286,7 +1287,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
]; ];
if (!unlockedAbilities[starterAttributes.ability]) { if (!unlockedAbilities[starterAttributes.ability]) {
// requested ability wasn't unlocked, purging setting // requested ability wasn't unlocked, purging setting
delete starterAttributes.ability; starterAttributes.ability = undefined;
} }
} }
@ -1297,14 +1298,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
!(caughtAttr & globalScene.gameData.getFormAttr(selectedForm))) !(caughtAttr & globalScene.gameData.getFormAttr(selectedForm)))
) { ) {
// requested form wasn't unlocked/isn't a starter form, purging setting // requested form wasn't unlocked/isn't a starter form, purging setting
delete starterAttributes.form; starterAttributes.form = undefined;
} }
if (starterAttributes.nature !== undefined) { if (starterAttributes.nature !== undefined) {
const unlockedNatures = globalScene.gameData.getNaturesForAttr(dexEntry.natureAttr); const unlockedNatures = globalScene.gameData.getNaturesForAttr(dexEntry.natureAttr);
if (unlockedNatures.indexOf(starterAttributes.nature as unknown as Nature) < 0) { if (unlockedNatures.indexOf(starterAttributes.nature as unknown as Nature) < 0) {
// requested nature wasn't unlocked, purging setting // requested nature wasn't unlocked, purging setting
delete starterAttributes.nature; starterAttributes.nature = undefined;
} }
} }
@ -1836,7 +1837,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
break; break;
} }
} else { } else {
let starterContainer; let starterContainer: StarterContainer;
const starterData = globalScene.gameData.starterData[this.lastSpecies.speciesId]; const starterData = globalScene.gameData.starterData[this.lastSpecies.speciesId];
// prepare persistent starter data to store changes // prepare persistent starter data to store changes
let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId]; let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId];
@ -2806,8 +2807,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
} }
} }
updateButtonIcon(iconSetting, gamepadType, iconElement, controlLabel): void { updateButtonIcon(
let iconPath; iconSetting: SettingKeyboard,
gamepadType: string,
iconElement: GameObjects.Sprite,
controlLabel: GameObjects.Text,
): void {
// biome-ignore lint/suspicious/noImplicitAnyLet: TODO
let iconPath: string;
// touch controls cannot be rebound as is, and are just emulating a keyboard event. // touch controls cannot be rebound as is, and are just emulating a keyboard event.
// Additionally, since keyboard controls can be rebound (and will be displayed when they are), we need to have special handling for the touch controls // Additionally, since keyboard controls can be rebound (and will be displayed when they are), we need to have special handling for the touch controls
if (gamepadType === "touch") { if (gamepadType === "touch") {
@ -2840,6 +2847,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
} else { } else {
iconPath = globalScene.inputController?.getIconForLatestInputRecorded(iconSetting); iconPath = globalScene.inputController?.getIconForLatestInputRecorded(iconSetting);
} }
// @ts-ignore: TODO can iconPath actually be undefined?
iconElement.setTexture(gamepadType, iconPath); iconElement.setTexture(gamepadType, iconPath);
iconElement.setPosition(this.instructionRowX, this.instructionRowY); iconElement.setPosition(this.instructionRowX, this.instructionRowY);
controlLabel.setPosition(this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY); controlLabel.setPosition(this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY);
@ -2853,8 +2861,13 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
} }
} }
updateFilterButtonIcon(iconSetting, gamepadType, iconElement, controlLabel): void { updateFilterButtonIcon(
let iconPath; iconSetting: SettingKeyboard,
gamepadType: string,
iconElement: GameObjects.Sprite,
controlLabel: GameObjects.Text,
): void {
let iconPath: string;
// touch controls cannot be rebound as is, and are just emulating a keyboard event. // touch controls cannot be rebound as is, and are just emulating a keyboard event.
// Additionally, since keyboard controls can be rebound (and will be displayed when they are), we need to have special handling for the touch controls // Additionally, since keyboard controls can be rebound (and will be displayed when they are), we need to have special handling for the touch controls
if (gamepadType === "touch") { if (gamepadType === "touch") {
@ -2884,7 +2897,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.hideInstructions(); this.hideInstructions();
this.instructionsContainer.removeAll(); this.instructionsContainer.removeAll();
this.filterInstructionsContainer.removeAll(); this.filterInstructionsContainer.removeAll();
let gamepadType; let gamepadType: string;
if (globalScene.inputMethod === "gamepad") { if (globalScene.inputMethod === "gamepad") {
gamepadType = globalScene.inputController.getConfig( gamepadType = globalScene.inputController.getConfig(
globalScene.inputController.selectedDevice[Device.GAMEPAD], globalScene.inputController.selectedDevice[Device.GAMEPAD],
@ -3216,17 +3229,16 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
const sort = this.filterBar.getVals(DropDownColumn.SORT)[0]; const sort = this.filterBar.getVals(DropDownColumn.SORT)[0];
this.filteredStarterContainers.sort((a, b) => { this.filteredStarterContainers.sort((a, b) => {
switch (sort.val) { switch (sort.val) {
default:
break;
case SortCriteria.NUMBER: case SortCriteria.NUMBER:
return (a.species.speciesId - b.species.speciesId) * -sort.dir; return (a.species.speciesId - b.species.speciesId) * -sort.dir;
case SortCriteria.COST: case SortCriteria.COST:
return (a.cost - b.cost) * -sort.dir; return (a.cost - b.cost) * -sort.dir;
case SortCriteria.CANDY: case SortCriteria.CANDY: {
const candyCountA = globalScene.gameData.starterData[a.species.speciesId].candyCount; const candyCountA = globalScene.gameData.starterData[a.species.speciesId].candyCount;
const candyCountB = globalScene.gameData.starterData[b.species.speciesId].candyCount; const candyCountB = globalScene.gameData.starterData[b.species.speciesId].candyCount;
return (candyCountA - candyCountB) * -sort.dir; return (candyCountA - candyCountB) * -sort.dir;
case SortCriteria.IV: }
case SortCriteria.IV: {
const avgIVsA = const avgIVsA =
globalScene.gameData.dexData[a.species.speciesId].ivs.reduce((a, b) => a + b, 0) / globalScene.gameData.dexData[a.species.speciesId].ivs.reduce((a, b) => a + b, 0) /
globalScene.gameData.dexData[a.species.speciesId].ivs.length; globalScene.gameData.dexData[a.species.speciesId].ivs.length;
@ -3234,6 +3246,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
globalScene.gameData.dexData[b.species.speciesId].ivs.reduce((a, b) => a + b, 0) / globalScene.gameData.dexData[b.species.speciesId].ivs.reduce((a, b) => a + b, 0) /
globalScene.gameData.dexData[b.species.speciesId].ivs.length; globalScene.gameData.dexData[b.species.speciesId].ivs.length;
return (avgIVsA - avgIVsB) * -sort.dir; return (avgIVsA - avgIVsB) * -sort.dir;
}
case SortCriteria.NAME: case SortCriteria.NAME:
return a.species.name.localeCompare(b.species.name) * -sort.dir; return a.species.name.localeCompare(b.species.name) * -sort.dir;
case SortCriteria.CAUGHT: case SortCriteria.CAUGHT:
@ -3893,7 +3906,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
.filter(f => f).length > 1; .filter(f => f).length > 1;
this.canCycleNature = globalScene.gameData.getNaturesForAttr(dexEntry.natureAttr).length > 1; this.canCycleNature = globalScene.gameData.getNaturesForAttr(dexEntry.natureAttr).length > 1;
this.canCycleTera = this.canCycleTera =
!this.statsMode && globalScene.gameData.achvUnlocks.hasOwnProperty(achvs.TERASTALLIZE.id) && !this.statsMode &&
globalScene.gameData.achvUnlocks.hasOwnProperty(achvs.TERASTALLIZE.id) &&
!Utils.isNullOrUndefined(getPokemonSpeciesForm(species.speciesId, formIndex ?? 0).type2); !Utils.isNullOrUndefined(getPokemonSpeciesForm(species.speciesId, formIndex ?? 0).type2);
} }
@ -4015,7 +4029,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
const availableStarterMoves = this.speciesStarterMoves.concat( const availableStarterMoves = this.speciesStarterMoves.concat(
speciesEggMoves.hasOwnProperty(species.speciesId) speciesEggMoves.hasOwnProperty(species.speciesId)
? speciesEggMoves[species.speciesId].filter( ? speciesEggMoves[species.speciesId].filter(
(_, em: number) => globalScene.gameData.starterData[species.speciesId].eggMoves & (1 << em), (_: any, em: number) => globalScene.gameData.starterData[species.speciesId].eggMoves & (1 << em),
) )
: [], : [],
); );
@ -4081,7 +4095,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
for (let em = 0; em < 4; em++) { for (let em = 0; em < 4; em++) {
const eggMove = hasEggMoves ? allMoves[speciesEggMoves[species.speciesId][em]] : null; const eggMove = hasEggMoves ? allMoves[speciesEggMoves[species.speciesId][em]] : null;
const eggMoveUnlocked = eggMove && globalScene.gameData.starterData[species.speciesId].eggMoves & (1 << em); const eggMoveUnlocked = eggMove && globalScene.gameData.starterData[species.speciesId].eggMoves & (1 << em);
this.pokemonEggMoveBgs[em].setFrame(PokemonType[eggMove ? eggMove.type : PokemonType.UNKNOWN].toString().toLowerCase()); this.pokemonEggMoveBgs[em].setFrame(
PokemonType[eggMove ? eggMove.type : PokemonType.UNKNOWN].toString().toLowerCase(),
);
this.pokemonEggMoveLabels[em].setText(eggMove && eggMoveUnlocked ? eggMove.name : "???"); this.pokemonEggMoveLabels[em].setText(eggMove && eggMoveUnlocked ? eggMove.name : "???");
} }
@ -4354,26 +4370,25 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
const thisObj = this; const thisObj = this;
const originalStarterSelectCallback = this.starterSelectCallback; const originalStarterSelectCallback = this.starterSelectCallback;
this.starterSelectCallback = null; this.starterSelectCallback = null;
originalStarterSelectCallback && originalStarterSelectCallback?.(
originalStarterSelectCallback( new Array(this.starterSpecies.length).fill(0).map((_, i) => {
new Array(this.starterSpecies.length).fill(0).map((_, i) => { const starterSpecies = thisObj.starterSpecies[i];
const starterSpecies = thisObj.starterSpecies[i]; return {
return { species: starterSpecies,
species: starterSpecies, dexAttr: thisObj.starterAttr[i],
dexAttr: thisObj.starterAttr[i], abilityIndex: thisObj.starterAbilityIndexes[i],
abilityIndex: thisObj.starterAbilityIndexes[i], passive: !(
passive: !( globalScene.gameData.starterData[starterSpecies.speciesId].passiveAttr ^
globalScene.gameData.starterData[starterSpecies.speciesId].passiveAttr ^ (PassiveAttr.ENABLED | PassiveAttr.UNLOCKED)
(PassiveAttr.ENABLED | PassiveAttr.UNLOCKED) ),
), nature: thisObj.starterNatures[i] as Nature,
nature: thisObj.starterNatures[i] as Nature, teraType: thisObj.starterTeras[i] as PokemonType,
teraType: thisObj.starterTeras[i] as PokemonType, moveset: thisObj.starterMovesets[i],
moveset: thisObj.starterMovesets[i], pokerus: thisObj.pokerusSpecies.includes(starterSpecies),
pokerus: thisObj.pokerusSpecies.includes(starterSpecies), nickname: thisObj.starterPreferences[starterSpecies.speciesId]?.nickname,
nickname: thisObj.starterPreferences[starterSpecies.speciesId]?.nickname, };
}; }),
}), );
);
}; };
startRun(); startRun();
}, },
@ -4495,9 +4510,15 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
//@ts-ignore //@ts-ignore
this.statsContainer.updateIvs(null); // TODO: resolve ts-ignore. !?!? this.statsContainer.updateIvs(null); // TODO: resolve ts-ignore. !?!?
this.teraIcon.setVisible(globalScene.gameData.achvUnlocks.hasOwnProperty(achvs.TERASTALLIZE.id)); this.teraIcon.setVisible(globalScene.gameData.achvUnlocks.hasOwnProperty(achvs.TERASTALLIZE.id));
const props = globalScene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.getCurrentDexProps(this.lastSpecies.speciesId)); const props = globalScene.gameData.getSpeciesDexAttrProps(
this.lastSpecies,
this.getCurrentDexProps(this.lastSpecies.speciesId),
);
const formIndex = props.formIndex; const formIndex = props.formIndex;
this.canCycleTera = !this.statsMode && globalScene.gameData.achvUnlocks.hasOwnProperty(achvs.TERASTALLIZE.id) && !Utils.isNullOrUndefined(getPokemonSpeciesForm(this.lastSpecies.speciesId, formIndex ?? 0).type2); this.canCycleTera =
!this.statsMode &&
globalScene.gameData.achvUnlocks.hasOwnProperty(achvs.TERASTALLIZE.id) &&
!Utils.isNullOrUndefined(getPokemonSpeciesForm(this.lastSpecies.speciesId, formIndex ?? 0).type2);
this.updateInstructions(); this.updateInstructions();
} }
} }
@ -4537,7 +4558,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
clear(): void { clear(): void {
super.clear(); super.clear();
StarterPrefs.save(this.starterPreferences); saveStarterPreferences(this.starterPreferences);
this.cursor = -1; this.cursor = -1;
this.hideInstructions(); this.hideInstructions();
this.activeTooltip = undefined; this.activeTooltip = undefined;

View File

@ -456,7 +456,7 @@ export default class SummaryUiHandler extends UiHandler {
this.genderText.setShadowColor(getGenderColor(this.pokemon.getGender(true), true)); this.genderText.setShadowColor(getGenderColor(this.pokemon.getGender(true), true));
switch (this.summaryUiMode) { switch (this.summaryUiMode) {
case SummaryUiMode.DEFAULT: case SummaryUiMode.DEFAULT: {
const page = args.length < 2 ? Page.PROFILE : (args[2] as Page); const page = args.length < 2 ? Page.PROFILE : (args[2] as Page);
this.hideMoveEffect(true); this.hideMoveEffect(true);
this.setCursor(page); this.setCursor(page);
@ -464,6 +464,7 @@ export default class SummaryUiHandler extends UiHandler {
this.selectCallback = args[3]; this.selectCallback = args[3];
} }
break; break;
}
case SummaryUiMode.LEARN_MOVE: case SummaryUiMode.LEARN_MOVE:
this.newMove = args[2] as Move; this.newMove = args[2] as Move;
this.moveSelectFunction = args[3] as Function; this.moveSelectFunction = args[3] as Function;
@ -500,7 +501,7 @@ export default class SummaryUiHandler extends UiHandler {
if (button === Button.ACTION) { if (button === Button.ACTION) {
if (this.pokemon && this.moveCursor < this.pokemon.moveset.length) { if (this.pokemon && this.moveCursor < this.pokemon.moveset.length) {
if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) {
this.moveSelectFunction && this.moveSelectFunction(this.moveCursor); this.moveSelectFunction?.(this.moveCursor);
} else { } else {
if (this.selectedMoveIndex === -1) { if (this.selectedMoveIndex === -1) {
this.selectedMoveIndex = this.moveCursor; this.selectedMoveIndex = this.moveCursor;
@ -602,7 +603,7 @@ export default class SummaryUiHandler extends UiHandler {
const pages = Utils.getEnumValues(Page); const pages = Utils.getEnumValues(Page);
switch (button) { switch (button) {
case Button.UP: case Button.UP:
case Button.DOWN: case Button.DOWN: {
if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) {
break; break;
} }
@ -618,6 +619,7 @@ export default class SummaryUiHandler extends UiHandler {
this.show([party[partyMemberIndex + (isDown ? 1 : -1)], this.summaryUiMode, page]); this.show([party[partyMemberIndex + (isDown ? 1 : -1)], this.summaryUiMode, page]);
} }
break; break;
}
case Button.LEFT: case Button.LEFT:
if (this.cursor) { if (this.cursor) {
success = this.setCursor(this.cursor - 1); success = this.setCursor(this.cursor - 1);
@ -786,7 +788,7 @@ export default class SummaryUiHandler extends UiHandler {
} }
switch (page) { switch (page) {
case Page.PROFILE: case Page.PROFILE: {
const profileContainer = globalScene.add.container(0, -pageBg.height); const profileContainer = globalScene.add.container(0, -pageBg.height);
pageContainer.add(profileContainer); pageContainer.add(profileContainer);
@ -956,7 +958,8 @@ export default class SummaryUiHandler extends UiHandler {
memoText.setOrigin(0, 0); memoText.setOrigin(0, 0);
profileContainer.add(memoText); profileContainer.add(memoText);
break; break;
case Page.STATS: }
case Page.STATS: {
this.statsContainer = globalScene.add.container(0, -pageBg.height); this.statsContainer = globalScene.add.container(0, -pageBg.height);
pageContainer.add(this.statsContainer); pageContainer.add(this.statsContainer);
this.permStatsContainer = globalScene.add.container(27, 56); this.permStatsContainer = globalScene.add.container(27, 56);
@ -1075,7 +1078,8 @@ export default class SummaryUiHandler extends UiHandler {
this.abilityPrompt.setOrigin(0, 0); this.abilityPrompt.setOrigin(0, 0);
this.statsContainer.add(this.abilityPrompt); this.statsContainer.add(this.abilityPrompt);
break; break;
case Page.MOVES: }
case Page.MOVES: {
this.movesContainer = globalScene.add.container(5, -pageBg.height + 26); this.movesContainer = globalScene.add.container(5, -pageBg.height + 26);
pageContainer.add(this.movesContainer); pageContainer.add(this.movesContainer);
@ -1168,6 +1172,7 @@ export default class SummaryUiHandler extends UiHandler {
this.moveDescriptionText.setMask(moveDescriptionTextMask); this.moveDescriptionText.setMask(moveDescriptionTextMask);
break; break;
}
} }
} }
@ -1221,7 +1226,7 @@ export default class SummaryUiHandler extends UiHandler {
hideMoveSelect() { hideMoveSelect() {
if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) {
this.moveSelectFunction && this.moveSelectFunction(4); this.moveSelectFunction?.(4);
return; return;
} }

View File

@ -142,7 +142,7 @@ export default class TargetSelectUiHandler extends UiHandler {
if (this.targetFlashTween) { if (this.targetFlashTween) {
this.targetFlashTween.stop(); this.targetFlashTween.stop();
for (const pokemon of multipleTargets) { for (const pokemon of multipleTargets) {
pokemon.setAlpha(!!pokemon.getTag(SubstituteTag) ? 0.5 : 1); pokemon.setAlpha(pokemon.getTag(SubstituteTag) ? 0.5 : 1);
this.highlightItems(pokemon.id, 1); this.highlightItems(pokemon.id, 1);
} }
} }
@ -194,7 +194,7 @@ export default class TargetSelectUiHandler extends UiHandler {
} }
for (const pokemon of this.targetsHighlighted) { for (const pokemon of this.targetsHighlighted) {
pokemon.setAlpha(!!pokemon.getTag(SubstituteTag) ? 0.5 : 1); pokemon.setAlpha(pokemon.getTag(SubstituteTag) ? 0.5 : 1);
this.highlightItems(pokemon.id, 1); this.highlightItems(pokemon.id, 1);
} }

View File

@ -48,19 +48,19 @@ export default class TestDialogueUiHandler extends FormModalUiHandler {
this.keys = keys; this.keys = keys;
} }
getModalTitle(config?: ModalConfig): string { getModalTitle(_config?: ModalConfig): string {
return "Test Dialogue"; return "Test Dialogue";
} }
getWidth(config?: ModalConfig): number { getWidth(_config?: ModalConfig): number {
return 300; return 300;
} }
getMargin(config?: ModalConfig): [number, number, number, number] { getMargin(_config?: ModalConfig): [number, number, number, number] {
return [0, 0, 48, 0]; return [0, 0, 48, 0];
} }
getButtonLabels(config?: ModalConfig): string[] { getButtonLabels(_config?: ModalConfig): string[] {
return ["Check", "Cancel"]; return ["Check", "Cancel"];
} }

View File

@ -330,6 +330,7 @@ export default class UI extends Phaser.GameObjects.Container {
): void { ): void {
if (prompt && text.indexOf("$") > -1) { if (prompt && text.indexOf("$") > -1) {
const messagePages = text.split(/\$/g).map(m => m.trim()); const messagePages = text.split(/\$/g).map(m => m.trim());
// biome-ignore lint/complexity/useOptionalChain: optional chain would change this to be null instead of undefined.
let showMessageAndCallback = () => callback && callback(); let showMessageAndCallback = () => callback && callback();
for (let p = messagePages.length - 1; p >= 0; p--) { for (let p = messagePages.length - 1; p >= 0; p--) {
const originalFunc = showMessageAndCallback; const originalFunc = showMessageAndCallback;

View File

@ -117,27 +117,35 @@ describe("Moves - Aurora Veil", () => {
}); });
it("does not affect physical critical hits", async () => { it("does not affect physical critical hits", async () => {
game.override.moveset([ Moves.WICKED_BLOW ]); game.override.moveset([Moves.WICKED_BLOW]);
const moveToUse = Moves.WICKED_BLOW; const moveToUse = Moves.WICKED_BLOW;
await game.classicMode.startBattle([ Species.SHUCKLE ]); await game.classicMode.startBattle([Species.SHUCKLE]);
game.move.select(moveToUse); game.move.select(moveToUse);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
const mockedDmg = getMockedMoveDamage(game.scene.getEnemyPokemon()!, game.scene.getPlayerPokemon()!, allMoves[moveToUse]); const mockedDmg = getMockedMoveDamage(
game.scene.getEnemyPokemon()!,
game.scene.getPlayerPokemon()!,
allMoves[moveToUse],
);
expect(mockedDmg).toBe(allMoves[moveToUse].power); expect(mockedDmg).toBe(allMoves[moveToUse].power);
}); });
it("does not affect critical hits", async () => { it("does not affect critical hits", async () => {
game.override.moveset([ Moves.FROST_BREATH ]); game.override.moveset([Moves.FROST_BREATH]);
const moveToUse = Moves.FROST_BREATH; const moveToUse = Moves.FROST_BREATH;
vi.spyOn(allMoves[Moves.FROST_BREATH], "accuracy", "get").mockReturnValue(100); vi.spyOn(allMoves[Moves.FROST_BREATH], "accuracy", "get").mockReturnValue(100);
await game.classicMode.startBattle([ Species.SHUCKLE ]); await game.classicMode.startBattle([Species.SHUCKLE]);
game.move.select(moveToUse); game.move.select(moveToUse);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
const mockedDmg = getMockedMoveDamage(game.scene.getEnemyPokemon()!, game.scene.getPlayerPokemon()!, allMoves[moveToUse]); const mockedDmg = getMockedMoveDamage(
game.scene.getEnemyPokemon()!,
game.scene.getPlayerPokemon()!,
allMoves[moveToUse],
);
expect(mockedDmg).toBe(allMoves[moveToUse].power); expect(mockedDmg).toBe(allMoves[moveToUse].power);
}); });
}); });
@ -158,13 +166,13 @@ const getMockedMoveDamage = (defender: Pokemon, attacker: Pokemon, move: Move) =
if (globalScene.arena.getTagOnSide(ArenaTagType.AURORA_VEIL, side)) { if (globalScene.arena.getTagOnSide(ArenaTagType.AURORA_VEIL, side)) {
if (move.getAttrs(CritOnlyAttr).length === 0) { if (move.getAttrs(CritOnlyAttr).length === 0) {
globalScene.arena.applyTagsForSide( globalScene.arena.applyTagsForSide(
ArenaTagType.AURORA_VEIL, ArenaTagType.AURORA_VEIL,
side, side,
false, false,
attacker, attacker,
move.category, move.category,
multiplierHolder, multiplierHolder,
); );
} }
} }

View File

@ -199,27 +199,27 @@ describe("Moves - Instruct", () => {
const [karp1, karp2] = game.scene.getEnemyField()!; const [karp1, karp2] = game.scene.getEnemyField()!;
expect(karp1.isFainted()).toBe(true); expect(karp1.isFainted()).toBe(true);
expect(karp2.isFainted()).toBe(true); expect(karp2.isFainted()).toBe(true);
}), });
it("should allow for dancer copying of instructed dance move", async () => { it("should allow for dancer copying of instructed dance move", async () => {
game.override.battleType("double").enemyMoveset([Moves.INSTRUCT, Moves.SPLASH]).enemyLevel(1000); game.override.battleType("double").enemyMoveset([Moves.INSTRUCT, Moves.SPLASH]).enemyLevel(1000);
await game.classicMode.startBattle([Species.ORICORIO, Species.VOLCARONA]); await game.classicMode.startBattle([Species.ORICORIO, Species.VOLCARONA]);
const [oricorio, volcarona] = game.scene.getPlayerField(); const [oricorio, volcarona] = game.scene.getPlayerField();
game.move.changeMoveset(oricorio, Moves.SPLASH); game.move.changeMoveset(oricorio, Moves.SPLASH);
game.move.changeMoveset(volcarona, Moves.FIERY_DANCE); game.move.changeMoveset(volcarona, Moves.FIERY_DANCE);
game.move.select(Moves.SPLASH, BattlerIndex.PLAYER); game.move.select(Moves.SPLASH, BattlerIndex.PLAYER);
game.move.select(Moves.FIERY_DANCE, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY); game.move.select(Moves.FIERY_DANCE, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY);
await game.forceEnemyMove(Moves.INSTRUCT, BattlerIndex.PLAYER_2); await game.forceEnemyMove(Moves.INSTRUCT, BattlerIndex.PLAYER_2);
await game.forceEnemyMove(Moves.SPLASH); await game.forceEnemyMove(Moves.SPLASH);
await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]);
await game.phaseInterceptor.to("BerryPhase"); await game.phaseInterceptor.to("BerryPhase");
// fiery dance triggered dancer successfully for a total of 4 hits // fiery dance triggered dancer successfully for a total of 4 hits
// Enemy level is set to a high value so that it does not faint even after all 4 hits // Enemy level is set to a high value so that it does not faint even after all 4 hits
instructSuccess(volcarona, Moves.FIERY_DANCE); instructSuccess(volcarona, Moves.FIERY_DANCE);
expect(game.scene.getEnemyField()[0].turnData.attacksReceived.length).toBe(4); expect(game.scene.getEnemyField()[0].turnData.attacksReceived.length).toBe(4);
}); });
it("should not repeat move when switching out", async () => { it("should not repeat move when switching out", async () => {
game.override.enemyMoveset(Moves.INSTRUCT).enemySpecies(Species.UNOWN); game.override.enemyMoveset(Moves.INSTRUCT).enemySpecies(Species.UNOWN);

View File

@ -86,21 +86,29 @@ describe("Moves - Light Screen", () => {
game.move.select(moveToUse); game.move.select(moveToUse);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
const mockedDmg = getMockedMoveDamage(game.scene.getEnemyPokemon()!, game.scene.getPlayerPokemon()!, allMoves[moveToUse]); const mockedDmg = getMockedMoveDamage(
game.scene.getEnemyPokemon()!,
game.scene.getPlayerPokemon()!,
allMoves[moveToUse],
);
expect(mockedDmg).toBe(allMoves[moveToUse].power); expect(mockedDmg).toBe(allMoves[moveToUse].power);
}); });
it("does not affect critical hits", async () => { it("does not affect critical hits", async () => {
game.override.moveset([ Moves.FROST_BREATH ]); game.override.moveset([Moves.FROST_BREATH]);
const moveToUse = Moves.FROST_BREATH; const moveToUse = Moves.FROST_BREATH;
vi.spyOn(allMoves[Moves.FROST_BREATH], "accuracy", "get").mockReturnValue(100); vi.spyOn(allMoves[Moves.FROST_BREATH], "accuracy", "get").mockReturnValue(100);
await game.classicMode.startBattle([ Species.SHUCKLE ]); await game.classicMode.startBattle([Species.SHUCKLE]);
game.move.select(moveToUse); game.move.select(moveToUse);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
const mockedDmg = getMockedMoveDamage(game.scene.getEnemyPokemon()!, game.scene.getPlayerPokemon()!, allMoves[moveToUse]); const mockedDmg = getMockedMoveDamage(
game.scene.getEnemyPokemon()!,
game.scene.getPlayerPokemon()!,
allMoves[moveToUse],
);
expect(mockedDmg).toBe(allMoves[moveToUse].power); expect(mockedDmg).toBe(allMoves[moveToUse].power);
}); });
}); });
@ -121,13 +129,13 @@ const getMockedMoveDamage = (defender: Pokemon, attacker: Pokemon, move: Move) =
if (globalScene.arena.getTagOnSide(ArenaTagType.LIGHT_SCREEN, side)) { if (globalScene.arena.getTagOnSide(ArenaTagType.LIGHT_SCREEN, side)) {
if (move.getAttrs(CritOnlyAttr).length === 0) { if (move.getAttrs(CritOnlyAttr).length === 0) {
globalScene.arena.applyTagsForSide( globalScene.arena.applyTagsForSide(
ArenaTagType.LIGHT_SCREEN, ArenaTagType.LIGHT_SCREEN,
side, side,
false, false,
attacker, attacker,
move.category, move.category,
multiplierHolder, multiplierHolder,
); );
} }
} }

View File

@ -96,27 +96,35 @@ describe("Moves - Reflect", () => {
}); });
it("does not affect critical hits", async () => { it("does not affect critical hits", async () => {
game.override.moveset([ Moves.WICKED_BLOW ]); game.override.moveset([Moves.WICKED_BLOW]);
const moveToUse = Moves.WICKED_BLOW; const moveToUse = Moves.WICKED_BLOW;
await game.classicMode.startBattle([ Species.SHUCKLE ]); await game.classicMode.startBattle([Species.SHUCKLE]);
game.move.select(moveToUse); game.move.select(moveToUse);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
const mockedDmg = getMockedMoveDamage(game.scene.getEnemyPokemon()!, game.scene.getPlayerPokemon()!, allMoves[moveToUse]); const mockedDmg = getMockedMoveDamage(
game.scene.getEnemyPokemon()!,
game.scene.getPlayerPokemon()!,
allMoves[moveToUse],
);
expect(mockedDmg).toBe(allMoves[moveToUse].power); expect(mockedDmg).toBe(allMoves[moveToUse].power);
}); });
it("does not affect critical hits", async () => { it("does not affect critical hits", async () => {
game.override.moveset([ Moves.WICKED_BLOW ]); game.override.moveset([Moves.WICKED_BLOW]);
const moveToUse = Moves.WICKED_BLOW; const moveToUse = Moves.WICKED_BLOW;
await game.classicMode.startBattle([ Species.SHUCKLE ]); await game.classicMode.startBattle([Species.SHUCKLE]);
game.move.select(moveToUse); game.move.select(moveToUse);
await game.phaseInterceptor.to(TurnEndPhase); await game.phaseInterceptor.to(TurnEndPhase);
const mockedDmg = getMockedMoveDamage(game.scene.getEnemyPokemon()!, game.scene.getPlayerPokemon()!, allMoves[moveToUse]); const mockedDmg = getMockedMoveDamage(
game.scene.getEnemyPokemon()!,
game.scene.getPlayerPokemon()!,
allMoves[moveToUse],
);
expect(mockedDmg).toBe(allMoves[moveToUse].power); expect(mockedDmg).toBe(allMoves[moveToUse].power);
}); });
}); });

View File

@ -142,9 +142,6 @@ export async function runSelectMysteryEncounterOption(
uiHandler.unblockInput(); // input are blocked by 1s to prevent accidental input. Tests need to handle that uiHandler.unblockInput(); // input are blocked by 1s to prevent accidental input. Tests need to handle that
switch (optionNo) { switch (optionNo) {
default:
// no movement needed. Default cursor position
break;
case 2: case 2:
uiHandler.processInput(Button.RIGHT); uiHandler.processInput(Button.RIGHT);
break; break;
@ -155,6 +152,9 @@ export async function runSelectMysteryEncounterOption(
uiHandler.processInput(Button.RIGHT); uiHandler.processInput(Button.RIGHT);
uiHandler.processInput(Button.DOWN); uiHandler.processInput(Button.DOWN);
break; break;
default:
// no movement needed. Default cursor position
break;
} }
if (!isNullOrUndefined(secondaryOptionSelect?.pokemonNo)) { if (!isNullOrUndefined(secondaryOptionSelect?.pokemonNo)) {

View File

@ -218,8 +218,12 @@ describe("Fiery Fallout - Mystery Encounter", () => {
await runMysteryEncounterToEnd(game, 2); await runMysteryEncounterToEnd(game, 2);
const burnablePokemon = party.filter(pkm => pkm.isAllowedInBattle() && !pkm.getTypes().includes(PokemonType.FIRE)); const burnablePokemon = party.filter(
const notBurnablePokemon = party.filter(pkm => !pkm.isAllowedInBattle() || pkm.getTypes().includes(PokemonType.FIRE)); pkm => pkm.isAllowedInBattle() && !pkm.getTypes().includes(PokemonType.FIRE),
);
const notBurnablePokemon = party.filter(
pkm => !pkm.isAllowedInBattle() || pkm.getTypes().includes(PokemonType.FIRE),
);
expect(scene.currentBattle.mysteryEncounter?.dialogueTokens["burnedPokemon"]).toBe(i18next.t("pokemon:gengar")); expect(scene.currentBattle.mysteryEncounter?.dialogueTokens["burnedPokemon"]).toBe(i18next.t("pokemon:gengar"));
burnablePokemon.forEach(pkm => { burnablePokemon.forEach(pkm => {
expect(pkm.hp, `${pkm.name} should have received 20% damage: ${pkm.hp} / ${pkm.getMaxHp()} HP`).toBe( expect(pkm.hp, `${pkm.name} should have received 20% damage: ${pkm.hp} / ${pkm.getMaxHp()} HP`).toBe(

View File

@ -10,8 +10,11 @@ import { MenuManip } from "#test/settingMenu/helpers/menuManip";
import { beforeEach, describe, expect, it } from "vitest"; import { beforeEach, describe, expect, it } from "vitest";
describe("Test Rebinding", () => { describe("Test Rebinding", () => {
// biome-ignore lint/suspicious/noImplicitAnyLet: TODO
let config; let config;
// biome-ignore lint/suspicious/noImplicitAnyLet: TODO
let inGame; let inGame;
// biome-ignore lint/suspicious/noImplicitAnyLet: TODO
let inTheSettingMenu; let inTheSettingMenu;
const configs: Map<string, InterfaceConfig> = new Map(); const configs: Map<string, InterfaceConfig> = new Map();
const selectedDevice = { const selectedDevice = {

View File

@ -224,6 +224,7 @@ export default class GameWrapper {
return new Promise(resolve => { return new Promise(resolve => {
// need to remove that if later we want to test battle-anims // need to remove that if later we want to test battle-anims
const newUrl = url.includes("./battle-anims/") ? prependPath("./battle-anims/tackle.json") : prependPath(url); const newUrl = url.includes("./battle-anims/") ? prependPath("./battle-anims/tackle.json") : prependPath(url);
// biome-ignore lint/suspicious/noImplicitAnyLet: TODO
let raw; let raw;
try { try {
raw = fs.readFileSync(newUrl, { encoding: "utf8", flag: "r" }); raw = fs.readFileSync(newUrl, { encoding: "utf8", flag: "r" });

View File

@ -1,7 +1,9 @@
export const MockFetch = (input, _init) => { export const MockFetch = (input, _init) => {
const url = typeof input === "string" ? input : input.url; const url = typeof input === "string" ? input : input.url;
// biome-ignore lint/suspicious/noImplicitAnyLet: TODO
let responseHandler; let responseHandler;
// biome-ignore lint/suspicious/noImplicitAnyLet: TODO
let responseText; let responseText;
const handlers = { const handlers = {

View File

@ -24,11 +24,5 @@
"exclude": "**/*+.test.ts", "exclude": "**/*+.test.ts",
"out": "typedoc" "out": "typedoc"
}, },
"exclude": [ "exclude": ["node_modules", "dist", "vite.config.ts", "vitest.config.ts", "vitest.workspace.ts"]
"node_modules",
"dist",
"vite.config.ts",
"vitest.config.ts",
"vitest.workspace.ts"
]
} }