diff --git a/src/battle-scene.ts b/src/battle-scene.ts index cbaf07d579c..7a55a7ed571 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -28,7 +28,6 @@ import { ExpShareModifier, FusePokemonModifier, HealingBoosterModifier, - ModifierBar, MultipleParticipantExpBonusModifier, PersistentModifier, PokemonExpBoosterModifier, @@ -186,6 +185,7 @@ import { hasExpSprite } from "./sprites/sprite-utils"; import { timedEventManager } from "./global-event-manager"; import { starterColors } from "./global-vars/starter-colors"; import { startingWave } from "./starting-wave"; +import { ModifierBar } from "./modifier/modifier-bar"; const DEBUG_RNG = false; diff --git a/src/modifier/modifier-bar.ts b/src/modifier/modifier-bar.ts new file mode 100644 index 00000000000..994c6960c63 --- /dev/null +++ b/src/modifier/modifier-bar.ts @@ -0,0 +1,105 @@ +import { globalScene } from "#app/global-scene"; +import { type Modifier, type PersistentModifier, PokemonHeldItemModifier } from "./modifier"; + +const iconOverflowIndex = 24; + +export const modifierSortFunc = (a: Modifier, b: Modifier): number => { + const itemNameMatch = a.type.name.localeCompare(b.type.name); + const typeNameMatch = a.constructor.name.localeCompare(b.constructor.name); + const aId = a instanceof PokemonHeldItemModifier && a.pokemonId ? a.pokemonId : 4294967295; + const bId = b instanceof PokemonHeldItemModifier && b.pokemonId ? b.pokemonId : 4294967295; + + //First sort by pokemonID + if (aId < bId) { + return 1; + } + if (aId > bId) { + return -1; + } + if (aId === bId) { + //Then sort by item type + if (typeNameMatch === 0) { + return itemNameMatch; + //Finally sort by item name + } + return typeNameMatch; + } + return 0; +}; + +export class ModifierBar extends Phaser.GameObjects.Container { + private player: boolean; + private modifierCache: PersistentModifier[]; + + constructor(enemy?: boolean) { + super(globalScene, 1 + (enemy ? 302 : 0), 2); + + this.player = !enemy; + this.setScale(0.5); + } + + /** + * Method to update content displayed in {@linkcode ModifierBar} + * @param {PersistentModifier[]} modifiers - The list of modifiers to be displayed in the {@linkcode ModifierBar} + * @param {boolean} hideHeldItems - If set to "true", only modifiers not assigned to a Pokémon are displayed + */ + updateModifiers(modifiers: PersistentModifier[], hideHeldItems = false) { + this.removeAll(true); + + const visibleIconModifiers = modifiers.filter(m => m.isIconVisible()); + const nonPokemonSpecificModifiers = visibleIconModifiers + .filter(m => !(m as PokemonHeldItemModifier).pokemonId) + .sort(modifierSortFunc); + const pokemonSpecificModifiers = visibleIconModifiers + .filter(m => (m as PokemonHeldItemModifier).pokemonId) + .sort(modifierSortFunc); + + const sortedVisibleIconModifiers = hideHeldItems + ? nonPokemonSpecificModifiers + : nonPokemonSpecificModifiers.concat(pokemonSpecificModifiers); + + sortedVisibleIconModifiers.forEach((modifier: PersistentModifier, i: number) => { + const icon = modifier.getIcon(); + if (i >= iconOverflowIndex) { + icon.setVisible(false); + } + this.add(icon); + this.setModifierIconPosition(icon, sortedVisibleIconModifiers.length); + icon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 32, 24), Phaser.Geom.Rectangle.Contains); + icon.on("pointerover", () => { + globalScene.ui.showTooltip(modifier.type.name, modifier.type.getDescription()); + if (this.modifierCache && this.modifierCache.length > iconOverflowIndex) { + this.updateModifierOverflowVisibility(true); + } + }); + icon.on("pointerout", () => { + globalScene.ui.hideTooltip(); + if (this.modifierCache && this.modifierCache.length > iconOverflowIndex) { + this.updateModifierOverflowVisibility(false); + } + }); + }); + + for (const icon of this.getAll()) { + this.sendToBack(icon); + } + + this.modifierCache = modifiers; + } + + updateModifierOverflowVisibility(ignoreLimit: boolean) { + const modifierIcons = this.getAll().reverse(); + for (const modifier of modifierIcons.map(m => m as Phaser.GameObjects.Container).slice(iconOverflowIndex)) { + modifier.setVisible(ignoreLimit); + } + } + + setModifierIconPosition(icon: Phaser.GameObjects.Container, modifierCount: number) { + const rowIcons: number = 12 + 6 * Math.max(Math.ceil(Math.min(modifierCount, 24) / 12) - 2, 0); + + const x = ((this.getIndex(icon) % rowIcons) * 26) / (rowIcons / 12); + const y = Math.floor(this.getIndex(icon) / rowIcons) * 20; + + icon.setPosition(this.player ? x : -x, y); + } +} diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 2ec849be799..cf0bdec0ee0 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -57,109 +57,6 @@ import { globalScene } from "#app/global-scene"; export type ModifierPredicate = (modifier: Modifier) => boolean; -const iconOverflowIndex = 24; - -export const modifierSortFunc = (a: Modifier, b: Modifier): number => { - const itemNameMatch = a.type.name.localeCompare(b.type.name); - const typeNameMatch = a.constructor.name.localeCompare(b.constructor.name); - const aId = a instanceof PokemonHeldItemModifier && a.pokemonId ? a.pokemonId : 4294967295; - const bId = b instanceof PokemonHeldItemModifier && b.pokemonId ? b.pokemonId : 4294967295; - - //First sort by pokemonID - if (aId < bId) { - return 1; - } - if (aId > bId) { - return -1; - } - if (aId === bId) { - //Then sort by item type - if (typeNameMatch === 0) { - return itemNameMatch; - //Finally sort by item name - } - return typeNameMatch; - } - return 0; -}; - -export class ModifierBar extends Phaser.GameObjects.Container { - private player: boolean; - private modifierCache: PersistentModifier[]; - - constructor(enemy?: boolean) { - super(globalScene, 1 + (enemy ? 302 : 0), 2); - - this.player = !enemy; - this.setScale(0.5); - } - - /** - * Method to update content displayed in {@linkcode ModifierBar} - * @param {PersistentModifier[]} modifiers - The list of modifiers to be displayed in the {@linkcode ModifierBar} - * @param {boolean} hideHeldItems - If set to "true", only modifiers not assigned to a Pokémon are displayed - */ - updateModifiers(modifiers: PersistentModifier[], hideHeldItems = false) { - this.removeAll(true); - - const visibleIconModifiers = modifiers.filter(m => m.isIconVisible()); - const nonPokemonSpecificModifiers = visibleIconModifiers - .filter(m => !(m as PokemonHeldItemModifier).pokemonId) - .sort(modifierSortFunc); - const pokemonSpecificModifiers = visibleIconModifiers - .filter(m => (m as PokemonHeldItemModifier).pokemonId) - .sort(modifierSortFunc); - - const sortedVisibleIconModifiers = hideHeldItems - ? nonPokemonSpecificModifiers - : nonPokemonSpecificModifiers.concat(pokemonSpecificModifiers); - - sortedVisibleIconModifiers.forEach((modifier: PersistentModifier, i: number) => { - const icon = modifier.getIcon(); - if (i >= iconOverflowIndex) { - icon.setVisible(false); - } - this.add(icon); - this.setModifierIconPosition(icon, sortedVisibleIconModifiers.length); - icon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 32, 24), Phaser.Geom.Rectangle.Contains); - icon.on("pointerover", () => { - globalScene.ui.showTooltip(modifier.type.name, modifier.type.getDescription()); - if (this.modifierCache && this.modifierCache.length > iconOverflowIndex) { - this.updateModifierOverflowVisibility(true); - } - }); - icon.on("pointerout", () => { - globalScene.ui.hideTooltip(); - if (this.modifierCache && this.modifierCache.length > iconOverflowIndex) { - this.updateModifierOverflowVisibility(false); - } - }); - }); - - for (const icon of this.getAll()) { - this.sendToBack(icon); - } - - this.modifierCache = modifiers; - } - - updateModifierOverflowVisibility(ignoreLimit: boolean) { - const modifierIcons = this.getAll().reverse(); - for (const modifier of modifierIcons.map(m => m as Phaser.GameObjects.Container).slice(iconOverflowIndex)) { - modifier.setVisible(ignoreLimit); - } - } - - setModifierIconPosition(icon: Phaser.GameObjects.Container, modifierCount: number) { - const rowIcons: number = 12 + 6 * Math.max(Math.ceil(Math.min(modifierCount, 24) / 12) - 2, 0); - - const x = ((this.getIndex(icon) % rowIcons) * 26) / (rowIcons / 12); - const y = Math.floor(this.getIndex(icon) / rowIcons) * 20; - - icon.setPosition(this.player ? x : -x, y); - } -} - export abstract class Modifier { public type: ModifierType; diff --git a/src/ui/run-info-ui-handler.ts b/src/ui/run-info-ui-handler.ts index 8487533f465..ae2b949de84 100644 --- a/src/ui/run-info-ui-handler.ts +++ b/src/ui/run-info-ui-handler.ts @@ -27,6 +27,7 @@ import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; import { getBiomeName } from "#app/data/balance/biomes"; import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { globalScene } from "#app/global-scene"; +import { modifierSortFunc } from "#app/modifier/modifier-bar"; /** * RunInfoUiMode indicates possible overlays of RunInfoUiHandler. @@ -891,7 +892,7 @@ export default class RunInfoUiHandler extends UiHandler { } } if (heldItemsList.length > 0) { - (heldItemsList as Modifier.PokemonHeldItemModifier[]).sort(Modifier.modifierSortFunc); + (heldItemsList as Modifier.PokemonHeldItemModifier[]).sort(modifierSortFunc); let row = 0; for (const [index, item] of heldItemsList.entries()) { if (index > 36) { diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index f93a1826b3e..3f1e726ca0c 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -33,7 +33,7 @@ import { getVariantTint } from "#app/sprites/variant"; import { Button } from "#enums/buttons"; import type { Ability } from "#app/data/abilities/ability-class"; import i18next from "i18next"; -import { modifierSortFunc } from "#app/modifier/modifier"; +import { modifierSortFunc } from "#app/modifier/modifier-bar"; import { PlayerGender } from "#enums/player-gender"; import { Stat, PERMANENT_STATS, getStatKey } from "#enums/stat"; import { Nature } from "#enums/nature"; diff --git a/src/ui/target-select-ui-handler.ts b/src/ui/target-select-ui-handler.ts index 5e14e5f7771..ba55d63ada7 100644 --- a/src/ui/target-select-ui-handler.ts +++ b/src/ui/target-select-ui-handler.ts @@ -6,9 +6,9 @@ import { getMoveTargets } from "../data/moves/move"; import { Button } from "#enums/buttons"; import type { Moves } from "#enums/moves"; import type Pokemon from "#app/field/pokemon"; -import type { ModifierBar } from "#app/modifier/modifier"; import { SubstituteTag } from "#app/data/battler-tags"; import { globalScene } from "#app/global-scene"; +import type { ModifierBar } from "#app/modifier/modifier-bar"; export type TargetSelectCallback = (targets: BattlerIndex[]) => void;