From 8383df1855b25087596102b10a5a10ca04f82101 Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Thu, 14 Aug 2025 23:30:14 -0400 Subject: [PATCH] Reverted changes to positional tag battle flyout --- .../positional-tags/load-positional-tag.ts | 9 +- .../positional-tags/positional-tag-manager.ts | 11 -- src/enums/arena-event-type.ts | 5 - src/events/arena.ts | 52 ------ src/ui/arena-flyout.ts | 154 +----------------- test/ui/flyouts/arena-flyout.test.ts | 38 +---- 6 files changed, 4 insertions(+), 265 deletions(-) diff --git a/src/data/positional-tags/load-positional-tag.ts b/src/data/positional-tags/load-positional-tag.ts index 41b112b84c2..dc3a67879b8 100644 --- a/src/data/positional-tags/load-positional-tag.ts +++ b/src/data/positional-tags/load-positional-tag.ts @@ -1,7 +1,5 @@ -import { globalScene } from "#app/global-scene"; import { DelayedAttackTag, type PositionalTag, WishTag } from "#data/positional-tags/positional-tag"; import { PositionalTagType } from "#enums/positional-tag-type"; -import { PositionalTagAddedEvent } from "#events/arena"; import type { ObjectValues } from "#types/type-helpers"; import type { Constructor } from "#utils/common"; @@ -22,12 +20,7 @@ export function loadPositionalTag(data: serializedP * This function does not perform any checking if the added tag is valid. */ export function loadPositionalTag(tag: SerializedPositionalTag): PositionalTag; -export function loadPositionalTag(tag: SerializedPositionalTag): PositionalTag { - // Update the global arena flyout - globalScene.arena.eventTarget.dispatchEvent(new PositionalTagAddedEvent(tag)); - - // Create the new tag - const { tagType, ...rest } = tag; +export function loadPositionalTag({ tagType, ...rest }: SerializedPositionalTag): PositionalTag { const tagClass = posTagConstructorMap[tagType]; // @ts-expect-error - tagType always corresponds to the proper constructor for `rest` return new tagClass(rest); diff --git a/src/data/positional-tags/positional-tag-manager.ts b/src/data/positional-tags/positional-tag-manager.ts index b56c9686fbb..7bf4d4995c6 100644 --- a/src/data/positional-tags/positional-tag-manager.ts +++ b/src/data/positional-tags/positional-tag-manager.ts @@ -1,9 +1,7 @@ -import { globalScene } from "#app/global-scene"; import { loadPositionalTag } from "#data/positional-tags/load-positional-tag"; import type { PositionalTag } from "#data/positional-tags/positional-tag"; import type { BattlerIndex } from "#enums/battler-index"; import type { PositionalTagType } from "#enums/positional-tag-type"; -import { PositionalTagRemovedEvent } from "#events/arena"; /** A manager for the {@linkcode PositionalTag}s in the arena. */ export class PositionalTagManager { @@ -51,16 +49,7 @@ export class PositionalTagManager { if (tag.shouldTrigger()) { tag.trigger(); } - this.emitRemove(tag); } this.tags = leftoverTags; } - - /** - * Emit a {@linkcode PositionalTagRemovedEvent} whenever a tag is removed from the field. - * @param tag - The {@linkcode PositionalTag} being removed - */ - private emitRemove(tag: PositionalTag): void { - globalScene.arena.eventTarget.dispatchEvent(new PositionalTagRemovedEvent(tag.tagType, tag.targetIndex)); - } } diff --git a/src/enums/arena-event-type.ts b/src/enums/arena-event-type.ts index c35828e9470..07e8f00d649 100644 --- a/src/enums/arena-event-type.ts +++ b/src/enums/arena-event-type.ts @@ -20,11 +20,6 @@ export const ArenaEventType = { ARENA_TAG_ADDED: "onArenaTagAdded", /** Emitted when an existing {@linkcode ArenaTag} is removed */ ARENA_TAG_REMOVED: "onArenaTagRemoved", - - /** Emitted when a new {@linkcode PositionalTag} is added */ - POSITIONAL_TAG_ADDED: "onPositionalTagAdded", - /** Emitted when an existing {@linkcode PositionalTag} is removed */ - POSITIONAL_TAG_REMOVED: "onPositionalTagRemoved", } as const; export type ArenaEventType = ObjectValues; diff --git a/src/events/arena.ts b/src/events/arena.ts index 6674a5278cc..ca5828c54b6 100644 --- a/src/events/arena.ts +++ b/src/events/arena.ts @@ -1,12 +1,7 @@ -import type { SerializedPositionalTag } from "#data/positional-tags/load-positional-tag"; -// biome-ignore lint/correctness/noUnusedImports: TSDoc -import type { PositionalTag } from "#data/positional-tags/positional-tag"; import type { TerrainType } from "#data/terrain"; import { ArenaEventType } from "#enums/arena-event-type"; import type { ArenaTagSide } from "#enums/arena-tag-side"; import type { ArenaTagType } from "#enums/arena-tag-type"; -import type { BattlerIndex } from "#enums/battler-index"; -import type { PositionalTagType } from "#enums/positional-tag-type"; import type { WeatherType } from "#enums/weather-type"; /** @@ -128,50 +123,3 @@ export class ArenaTagRemovedEvent extends ArenaEvent { this.side = side; } } - -/** - * Container class for {@linkcode ArenaEventType.POSITIONAL_TAG_ADDED} events. \ - * Emitted whenever a new {@linkcode PositionalTag} is spawned and added to the arena. - * @eventProperty - */ -export class PositionalTagAddedEvent extends ArenaEvent { - declare type: typeof ArenaEventType.POSITIONAL_TAG_ADDED; - - /** The {@linkcode SerializedPositionalTag} being added to the arena. */ - public tag: SerializedPositionalTag; - - /** The {@linkcode PositionalTagType} of the tag being added. */ - public tagType: PositionalTagType; - /** The {@linkcode BattlerIndex} targeted by the newly created tag. */ - public targetIndex: BattlerIndex; - /** The tag's current duration. */ - public duration: number; - - constructor(tag: SerializedPositionalTag) { - super(ArenaEventType.POSITIONAL_TAG_ADDED); - - this.tag = tag; - } -} - -/** - * Container class for {@linkcode ArenaEventType.POSITIONAL_TAG_REMOVED} events. \ - * Emitted whenever a currently-active {@linkcode PositionalTag} triggers (or disappears) - * and is removed from the arena. - * @eventProperty - */ -export class PositionalTagRemovedEvent extends ArenaEvent { - declare type: typeof ArenaEventType.POSITIONAL_TAG_REMOVED; - - /** The {@linkcode PositionalTagType} of the tag being deleted. */ - public tagType: PositionalTagType; - /** The {@linkcode BattlerIndex} targeted by the newly removed tag. */ - public targetIndex: BattlerIndex; - - constructor(tagType: PositionalTagType, targetIndex: BattlerIndex) { - super(ArenaEventType.POSITIONAL_TAG_ADDED); - - this.tagType = tagType; - this.targetIndex = targetIndex; - } -} diff --git a/src/ui/arena-flyout.ts b/src/ui/arena-flyout.ts index 828f7c1506d..ab0501b1798 100644 --- a/src/ui/arena-flyout.ts +++ b/src/ui/arena-flyout.ts @@ -1,28 +1,15 @@ import { globalScene } from "#app/global-scene"; // biome-ignore-start lint/correctness/noUnusedImports: TSDocs import type { ArenaTag } from "#data/arena-tag"; -import type { SerializedPositionalTag } from "#data/positional-tags/load-positional-tag"; -import type { PositionalTag } from "#data/positional-tags/positional-tag"; import { type Terrain, TerrainType } from "#data/terrain"; import type { Weather } from "#data/weather"; import { ArenaEventType } from "#enums/arena-event-type"; // biome-ignore-end lint/correctness/noUnusedImports: TSDocs import { ArenaTagSide } from "#enums/arena-tag-side"; import { ArenaTagType } from "#enums/arena-tag-type"; -import { BattlerIndex } from "#enums/battler-index"; -import { FieldPosition } from "#enums/field-position"; -import { MoveId } from "#enums/move-id"; -import type { PositionalTagType } from "#enums/positional-tag-type"; import { TextStyle } from "#enums/text-style"; import { WeatherType } from "#enums/weather-type"; -import type { - ArenaTagAddedEvent, - ArenaTagRemovedEvent, - PositionalTagAddedEvent, - PositionalTagRemovedEvent, - TerrainChangedEvent, - WeatherChangedEvent, -} from "#events/arena"; +import type { ArenaTagAddedEvent, ArenaTagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#events/arena"; import { BattleSceneEventType } from "#events/battle-scene"; import { addTextObject } from "#ui/text"; import { TimeOfDayWidget } from "#ui/time-of-day-widget"; @@ -71,18 +58,6 @@ interface ArenaTagInfo { tagType?: ArenaTagType; } -/** Container for info about pending {@linkcode PositionalTag}s. */ -interface PositionalTagInfo { - /** The localized name of the effect. */ - name: string; - /** The {@linkcode BattlerIndex} that the effect is slated to affect. */ - targetIndex: BattlerIndex; - /** The current duration of the effect. */ - duration: number; - /** The tag's {@linkcode PositionalTagType}. */ - tagType: PositionalTagType; -} - // #endregion interfaces /** @@ -137,19 +112,13 @@ export class ArenaFlyout extends Phaser.GameObjects.Container { /** Container for all {@linkcode ArenaTag}s observed by this object. */ private arenaTags: ArenaTagInfo[] = []; - /** Container for all {@linkcode PositionalTag}s observed by this object. */ - private positionalTags: PositionalTagInfo[] = []; - // Store callbacks in variables so they can be unsubscribed from when destroyed private readonly onNewArenaEvent = () => this.onNewArena(); private readonly onTurnEndEvent = () => this.onTurnEnd(); private readonly onWeatherChangedEvent = (event: WeatherChangedEvent) => this.onWeatherChanged(event); private readonly onTerrainChangedEvent = (event: TerrainChangedEvent) => this.onTerrainChanged(event); private readonly onArenaTagAddedEvent = (event: ArenaTagAddedEvent) => this.onArenaTagAdded(event); private readonly onArenaTagRemovedEvent = (event: ArenaTagRemovedEvent) => this.onArenaTagRemoved(event); - private readonly onPositionalTagAddedEvent = (event: PositionalTagAddedEvent) => this.onPositionalTagAdded(event); - // biome-ignore format: Keeps lines in 1 piece - private readonly onPositionalTagRemovedEvent = (event: PositionalTagRemovedEvent) => this.onPositionalTagRemoved(event); constructor() { super(globalScene, 0, 0); @@ -267,26 +236,20 @@ export class ArenaFlyout extends Phaser.GameObjects.Container { */ private onNewArena() { this.arenaTags = []; - this.positionalTags = []; // Subscribe to required events available on battle start - // biome-ignore-start format: Keeps lines in 1 piece globalScene.arena.eventTarget.addEventListener(ArenaEventType.WEATHER_CHANGED, this.onWeatherChangedEvent); globalScene.arena.eventTarget.addEventListener(ArenaEventType.TERRAIN_CHANGED, this.onTerrainChangedEvent); globalScene.arena.eventTarget.addEventListener(ArenaEventType.ARENA_TAG_ADDED, this.onArenaTagAddedEvent); globalScene.arena.eventTarget.addEventListener(ArenaEventType.ARENA_TAG_REMOVED, this.onArenaTagRemovedEvent); - globalScene.arena.eventTarget.addEventListener(ArenaEventType.POSITIONAL_TAG_ADDED, this.onPositionalTagAddedEvent); - globalScene.arena.eventTarget.addEventListener(ArenaEventType.POSITIONAL_TAG_REMOVED, this.onPositionalTagRemovedEvent); - // biome-ignore-end format: Keeps lines in 1 piece } /** - * Iterate through all currently present field effects and decrement their durations. + * Iterate through all currently present tags effects and decrement their durations. */ private onTurnEnd() { // Remove all objects with positive max durations and whose durations have expired. this.arenaTags = this.arenaTags.filter(info => info.maxDuration === 0 || --info.duration >= 0); - this.positionalTags = this.positionalTags.filter(info => --info.duration > 0); this.updateFieldText(); } @@ -339,7 +302,6 @@ export class ArenaFlyout extends Phaser.GameObjects.Container { */ private onArenaTagRemoved(event: ArenaTagRemovedEvent): void { const foundIndex = this.arenaTags.findIndex(info => info.tagType === event.tagType && info.side === event.side); - console.log(this.positionalTags, event); if (foundIndex > -1) { // If the tag was being tracked, remove it @@ -350,42 +312,6 @@ export class ArenaFlyout extends Phaser.GameObjects.Container { // #endregion ArenaTags - // #region PositionalTags - - /** - * Add a recently-created {@linkcode PositionalTag} to the flyout. - * @param event - The {@linkcode PositionalTagAddedEvent} having been emitted - */ - private onPositionalTagAdded(event: PositionalTagAddedEvent): void { - const name = this.getPositionalTagDisplayName(event.tag); - - this.positionalTags.push({ - name, - targetIndex: event.tag.targetIndex, - duration: event.tag.turnCount, - tagType: event.tag.tagType, - }); - this.updateFieldText(); - } - - /** - * Remove a recently-activated {@linkcode PositionalTag} from the flyout. - * @param event - The {@linkcode PositionalTagRemovedEvent} having been emitted - */ - private onPositionalTagRemoved(event: PositionalTagRemovedEvent): void { - const foundIndex = this.positionalTags.findIndex( - info => info.tagType === event.tagType && info.targetIndex === event.targetIndex, - ); - - if (foundIndex > -1) { - // If the tag was being tracked, remove it - this.positionalTags.splice(foundIndex, 1); - this.updateFieldText(); - } - } - - // #endregion PositionalTags - // #region Weather/Terrain /** @@ -458,10 +384,6 @@ export class ArenaFlyout extends Phaser.GameObjects.Container { globalScene.arena.eventTarget.removeEventListener(ArenaEventType.TERRAIN_CHANGED, this.onTerrainChanged); globalScene.arena.eventTarget.removeEventListener(ArenaEventType.ARENA_TAG_ADDED, this.onArenaTagAddedEvent); globalScene.arena.eventTarget.removeEventListener(ArenaEventType.ARENA_TAG_REMOVED, this.onArenaTagRemovedEvent); - // biome-ignore format: Keeps lines in 1 piece - globalScene.arena.eventTarget.removeEventListener(ArenaEventType.POSITIONAL_TAG_ADDED, this.onPositionalTagAddedEvent); - // biome-ignore format: Keeps lines in 1 piece - globalScene.arena.eventTarget.removeEventListener(ArenaEventType.POSITIONAL_TAG_REMOVED, this.onPositionalTagRemovedEvent); super.destroy(fromScene); } @@ -489,15 +411,6 @@ export class ArenaFlyout extends Phaser.GameObjects.Container { this.flyoutTextField.text += this.getTagText(this.terrainInfo); } - // Sort and add all positional tags - this.positionalTags.sort( - // Sort based on tag name, breaking ties by ascending target index. - (infoA, infoB) => infoA.name.localeCompare(infoB.name) || infoA.targetIndex - infoB.targetIndex, - ); - for (const tag of this.positionalTags) { - this.getPositionalTagTextObj(tag).text += this.getPosTagText(tag); - } - // Sort and update all arena tag text this.arenaTags.sort((infoA, infoB) => infoA.duration - infoB.duration); for (const tag of this.arenaTags) { @@ -505,24 +418,6 @@ export class ArenaFlyout extends Phaser.GameObjects.Container { } } - /** - * Helper method to retrieve the flyout text for a given {@linkcode PositionalTag}. - * @param info - The {@linkcode PositionalTagInfo} whose text is being updated - * @returns The text to be added to the container - */ - private getPosTagText(info: PositionalTagInfo): string { - // Avoud showing slot target for single battles - if (!globalScene.currentBattle.double) { - return `${info.name} (${info.duration})\n`; - } - - const targetPos = battlerIndexToFieldPosition(info.targetIndex); - const posText = this.localizeEffectName(FieldPosition[targetPos]); - - // Ex: "Future Sight (Center, 2)" - return `${info.name} (${posText}, ${info.duration})\n`; - } - /** * Helper method to retrieve the flyout text for a given effect's info. * @param info - The {@linkcode ArenaTagInfo}, {@linkcode TerrainInfo} or {@linkcode WeatherInfo} being updated @@ -555,24 +450,6 @@ export class ArenaFlyout extends Phaser.GameObjects.Container { } } - /** - * Choose which text object needs to be updated depending on the current tag's target. - * @param info - The {@linkcode PositionalTagInfo} being displayed - * @returns The {@linkcode Phaser.GameObjects.Text} to be updated. - */ - private getPositionalTagTextObj(info: PositionalTagInfo): Phaser.GameObjects.Text { - switch (info.targetIndex) { - case BattlerIndex.PLAYER: - case BattlerIndex.PLAYER_2: - return this.flyoutTextPlayer; - case BattlerIndex.ENEMY: - case BattlerIndex.ENEMY_2: - return this.flyoutTextEnemy; - case BattlerIndex.ATTACKER: - throw new Error("BattlerIndex.ATTACKER used as tag target index for arena flyout!"); - } - } - // # endregion Text display functions // #region Utilities @@ -589,32 +466,5 @@ export class ArenaFlyout extends Phaser.GameObjects.Container { return resultName; } - /** - * Return the localized name of a given {@linkcode PositionalTag}. - * @param tag - The raw serialized data for the given tag - * @returns The localized text to be displayed on-screen. - */ - private getPositionalTagDisplayName(tag: SerializedPositionalTag): string { - let tagName: string; - if ("sourceMove" in tag) { - // Delayed attacks will use the source move's name; other effects use type directly - tagName = MoveId[tag.sourceMove]; - } else { - tagName = tag.tagType; - } - - return this.localizeEffectName(tagName); - } - // #endregion Utility emthods } - -/** - * Convert a {@linkcode BattlerIndex} into a field position. - * @param index - The {@linkcode BattlerIndex} to convert - * @returns The resultant field position. - */ -function battlerIndexToFieldPosition(index: BattlerIndex): FieldPosition { - const pos = globalScene.getField()[index]?.fieldPosition; - return pos; -} diff --git a/test/ui/flyouts/arena-flyout.test.ts b/test/ui/flyouts/arena-flyout.test.ts index ed05cca5da0..2094b79baf1 100644 --- a/test/ui/flyouts/arena-flyout.test.ts +++ b/test/ui/flyouts/arena-flyout.test.ts @@ -1,15 +1,12 @@ -import type { SerializedPositionalTag } from "#data/positional-tags/load-positional-tag"; import { AbilityId } from "#enums/ability-id"; -import { BattlerIndex } from "#enums/battler-index"; import { MoveId } from "#enums/move-id"; -import { PositionalTagType } from "#enums/positional-tag-type"; import { SpeciesId } from "#enums/species-id"; import { GameManager } from "#test/test-utils/game-manager"; import { mockI18next } from "#test/test-utils/test-utils"; import type { ArenaFlyout } from "#ui/arena-flyout"; import type i18next from "i18next"; import Phaser from "phaser"; -import { afterAll, beforeAll, beforeEach, describe, expect, it, type MockInstance, vi } from "vitest"; +import { afterAll, beforeAll, beforeEach, describe, expect, it, type MockInstance } from "vitest"; describe("UI - Arena Flyout", () => { let phaserGame: Phaser.Game; @@ -57,7 +54,6 @@ describe("UI - Arena Flyout", () => { // Helper type to get around unexportedness type infoType = Parameters<(typeof flyout)["getTagText"]>[0]; - type posTagInfo = (typeof flyout)["positionalTags"][number]; describe("getTagText", () => { it.each<{ info: Pick; text: string }>([ @@ -68,36 +64,4 @@ describe("UI - Arena Flyout", () => { expect(got).toBe(text); }); }); - - describe("getPositionalTagDisplayName", () => { - it.each([ - { tag: { tagType: PositionalTagType.WISH }, name: "arenaFlyout:wish" }, - { - tag: { sourceMove: MoveId.FUTURE_SIGHT, tagType: PositionalTagType.DELAYED_ATTACK }, - name: "arenaFlyout:futureSight", - }, - { - tag: { sourceMove: MoveId.DOOM_DESIRE, tagType: PositionalTagType.DELAYED_ATTACK }, - name: "arenaFlyout:doomDesire", - }, - ])("should get the name of a Positional Tag", ({ tag, name }) => { - const got = flyout["getPositionalTagDisplayName"](tag as SerializedPositionalTag); - expect(got).toBe(name); - }); - }); - - describe("getPosTagText", () => { - it.each<{ tag: Pick; output: string; double?: boolean }>([ - { tag: { duration: 2, name: "Wish", targetIndex: BattlerIndex.PLAYER }, output: "Wish (2)" }, - { - tag: { duration: 1, name: "Future Sight", targetIndex: BattlerIndex.ENEMY_2 }, - double: true, - output: "Future Sight (arenaFlyout:right, 1)", - }, - ])("should produce the correct text", ({ tag, output, double = false }) => { - vi.spyOn(game.scene.currentBattle, "double", "get").mockReturnValue(double); - const text = flyout["getPosTagText"](tag as posTagInfo); - expect(text).toBe(output + "\n"); - }); - }); });