diff --git a/src/battle-scene-events.ts b/src/battle-scene-events.ts index 128fd5b5ceb..74fac97d2b7 100644 --- a/src/battle-scene-events.ts +++ b/src/battle-scene-events.ts @@ -1,4 +1,5 @@ import Move from "./data/move"; +import { BerryModifier } from "./modifier/modifier"; /** Alias for all {@linkcode BattleScene} events */ export enum BattleSceneEventType { @@ -13,6 +14,12 @@ export enum BattleSceneEventType { * @see {@linkcode MoveUsedEvent} */ MOVE_USED = "onMoveUsed", + /** + * Triggers when a berry gets successfully used + * @see {@linkcode BerryUsedEvent} + */ + BERRY_USED = "onBerryUsed", + /** * Triggers on the first turn of a new battle * @see {@linkcode TurnInitEvent} @@ -23,6 +30,7 @@ export enum BattleSceneEventType { * @see {@linkcode TurnEndEvent} */ TURN_END = "onTurnEnd", + /** * Triggers when a new {@linkcode Arena} is created during initialization * @see {@linkcode NewArenaEvent} @@ -50,7 +58,7 @@ export class CandyUpgradeNotificationChangedEvent extends Event { */ export class MoveUsedEvent extends Event { /** The ID of the {@linkcode Pokemon} that used the {@linkcode Move} */ - public userId: number; + public pokemonId: number; /** The {@linkcode Move} used */ public move: Move; /** The amount of PP used on the {@linkcode Move} this turn */ @@ -58,11 +66,25 @@ export class MoveUsedEvent extends Event { constructor(userId: number, move: Move, ppUsed: number) { super(BattleSceneEventType.MOVE_USED); - this.userId = userId; + this.pokemonId = userId; this.move = move; this.ppUsed = ppUsed; } } +/** + * Container class for {@linkcode BattleSceneEventType.BERRY_USED} events + * @extends Event +*/ +export class BerryUsedEvent extends Event { + /** The {@linkcode BerryModifier} being used */ + public berryModifier: BerryModifier; + constructor(berry: BerryModifier) { + super(BattleSceneEventType.BERRY_USED); + + this.berryModifier = berry; + } +} + /** * Container class for {@linkcode BattleSceneEventType.TURN_INIT} events * @extends Event diff --git a/src/phases.ts b/src/phases.ts index 110c4155849..c9c93ab414d 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -61,7 +61,7 @@ import { Abilities } from "./data/enums/abilities"; import * as Overrides from "./overrides"; import { TextStyle, addTextObject } from "./ui/text"; import { Type } from "./data/type"; -import { MoveUsedEvent, TurnEndEvent, TurnInitEvent } from "./battle-scene-events"; +import { BerryUsedEvent, MoveUsedEvent, TurnEndEvent, TurnInitEvent } from "./battle-scene-events"; export class LoginPhase extends Phase { @@ -2244,6 +2244,7 @@ export class BerryPhase extends FieldPhase { berryModifier.consumed = false; } } + this.scene.eventTarget.dispatchEvent(new BerryUsedEvent(berryModifier)); // Announce a berry was used } this.scene.updateModifiers(pokemon.isPlayer()); diff --git a/src/ui/arena-flyout.ts b/src/ui/arena-flyout.ts index 73660ca4457..77996625fed 100644 --- a/src/ui/arena-flyout.ts +++ b/src/ui/arena-flyout.ts @@ -81,11 +81,11 @@ export default class ArenaFlyout extends Phaser.GameObjects.Container { private readonly fieldEffectInfo: ArenaEffectInfo[] = []; // Stores callbacks in a variable so they can be unsubscribed from when destroyed - private onNewArenaEvent = (event: Event) => this.onNewArena(event); - private onTurnInitEvent = (event: Event) => this.onTurnInit(event); - private onTurnEndEvent = (event: Event) => this.onTurnEnd(event); + private readonly onNewArenaEvent = (event: Event) => this.onNewArena(event); + private readonly onTurnInitEvent = (event: Event) => this.onTurnInit(event); + private readonly onTurnEndEvent = (event: Event) => this.onTurnEnd(event); - private onFieldEffectChangedEvent = (event: Event) => this.onFieldEffectChanged(event); + private readonly onFieldEffectChangedEvent = (event: Event) => this.onFieldEffectChanged(event); constructor(scene: Phaser.Scene) { super(scene, 0, 0); @@ -379,6 +379,6 @@ export default class ArenaFlyout extends Phaser.GameObjects.Container { this.battleScene.arena.eventTarget.removeEventListener(ArenaEventType.TAG_ADDED, this.onFieldEffectChangedEvent); this.battleScene.arena.eventTarget.removeEventListener(ArenaEventType.TAG_REMOVED, this.onFieldEffectChangedEvent); - super.destroy(); + super.destroy(fromScene); } } diff --git a/src/ui/battle-flyout.ts b/src/ui/battle-flyout.ts index 3add54920b0..9a9e3ef46a9 100644 --- a/src/ui/battle-flyout.ts +++ b/src/ui/battle-flyout.ts @@ -4,7 +4,9 @@ import * as Utils from "../utils"; import BattleScene from "#app/battle-scene.js"; import { UiTheme } from "#app/enums/ui-theme.js"; import Move from "#app/data/move.js"; -import { BattleSceneEventType, MoveUsedEvent } from "#app/battle-scene-events.js"; +import { BattleSceneEventType, BerryUsedEvent, MoveUsedEvent } from "#app/battle-scene-events.js"; +import { BerryType } from "#app/data/enums/berry-type.js"; +import { Moves } from "#app/data/enums/moves.js"; /** Container for info about a {@linkcode Move} */ interface MoveInfo { @@ -53,7 +55,9 @@ export default class BattleFlyout extends Phaser.GameObjects.Container { /** The array of {@linkcode MoveInfo} used to track moves for the {@linkcode Pokemon} linked to the flyout */ private moveInfo: MoveInfo[] = new Array(); - private readonly onMoveUsed = (event) => this.updateInfo(event); + // Stores callbacks in a variable so they can be unsubscribed from when destroyed + private readonly onMoveUsedEvent = (event: Event) => this.onMoveUsed(event); + private readonly onBerryUsedEvent = (event: Event) => this.onBerryUsed(event); constructor(scene: Phaser.Scene, player: boolean) { super(scene, 0, 0); @@ -109,11 +113,12 @@ export default class BattleFlyout extends Phaser.GameObjects.Container { this.name = `Flyout ${this.pokemon.name}`; this.flyoutParent.name = `Flyout Parent ${this.pokemon.name}`; - this.battleScene.eventTarget.addEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsed); + this.battleScene.eventTarget.addEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsedEvent); + this.battleScene.eventTarget.addEventListener(BattleSceneEventType.BERRY_USED, this.onBerryUsedEvent); } /** Sets and formats the text property for all {@linkcode Phaser.GameObjects.Text} in the flyoutText array */ - setText() { + private setText() { for (let i = 0; i < this.flyoutText.length; i++) { const flyoutText = this.flyoutText[i]; const moveInfo = this.moveInfo[i]; @@ -122,21 +127,23 @@ export default class BattleFlyout extends Phaser.GameObjects.Container { continue; } - const currentPp = Math.max(moveInfo.maxPp - moveInfo.ppUsed, 0); + const currentPp = moveInfo.maxPp - moveInfo.ppUsed; flyoutText.text = `${moveInfo.move.name} ${currentPp}/${moveInfo.maxPp}`; } } /** Updates all of the {@linkcode MoveInfo} objects in the moveInfo array */ - updateInfo(event: Event) { + private onMoveUsed(event: Event) { const moveUsedEvent = event as MoveUsedEvent; - if (!moveUsedEvent || moveUsedEvent.userId !== this.pokemon?.id) { + if (!moveUsedEvent + || moveUsedEvent.pokemonId !== this.pokemon?.id + || moveUsedEvent.move.id === Moves.STRUGGLE) { // Ignore Struggle return; } const foundInfo = this.moveInfo.find(x => x?.move.id === moveUsedEvent.move.id); if (foundInfo) { - foundInfo.ppUsed += moveUsedEvent.ppUsed; + foundInfo.ppUsed = Math.min(foundInfo.ppUsed + moveUsedEvent.ppUsed, foundInfo.maxPp); } else { this.moveInfo.push({move: moveUsedEvent.move, maxPp: moveUsedEvent.move.pp, ppUsed: moveUsedEvent.ppUsed}); } @@ -144,6 +151,23 @@ export default class BattleFlyout extends Phaser.GameObjects.Container { this.setText(); } + private onBerryUsed(event: Event) { + const berryUsedEvent = event as BerryUsedEvent; + if (!berryUsedEvent + || berryUsedEvent.berryModifier.pokemonId !== this.pokemon?.id + || berryUsedEvent.berryModifier.berryType !== BerryType.LEPPA) { // We only care about Leppa berries + return; + } + + const foundInfo = this.moveInfo.find(info => info.ppUsed === info.maxPp); + if (!foundInfo) { // This will only happen on a de-sync of PP tracking + return; + } + foundInfo.ppUsed = Math.max(foundInfo.ppUsed - 10, 0); + + this.setText(); + } + /** Animates the flyout to either show or hide it by applying a fade and translation */ toggleFlyout(visible: boolean): void { this.scene.tweens.add({ @@ -156,8 +180,9 @@ export default class BattleFlyout extends Phaser.GameObjects.Container { } destroy(fromScene?: boolean): void { - this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsed); + this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.MOVE_USED, this.onMoveUsedEvent); + this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.BERRY_USED, this.onBerryUsedEvent); - super.destroy(); + super.destroy(fromScene); } }