From aa90a9ff2d13ef087d687f7b76323b31817a368e Mon Sep 17 00:00:00 2001 From: Adrian T <68144167+torranx@users.noreply.github.com> Date: Fri, 12 Jul 2024 02:17:02 +0800 Subject: [PATCH] [QoL] Highlight targets of multitarget moves instead of immediate execution (#2863) * show targets for move targeting multiple pokemon * dont allow selecting target if multiple * fix targeting * cleanup * more cleanup * only highlight targets is move is not status * fix tests failing * fix tests * change "immediately" to "auto" * nevermind just remove auto * remove status move condition --- src/phases.ts | 9 ++-- src/test/utils/gameManager.ts | 12 ++++- src/ui/target-select-ui-handler.ts | 78 ++++++++++++++++-------------- 3 files changed, 59 insertions(+), 40 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index 144a2625896..963535d052a 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -1973,6 +1973,9 @@ export class CommandPhase extends FieldPhase { turnCommand.targets = [this.fieldIndex]; } console.log(moveTargets, playerPokemon.name); + if (moveTargets.targets.length > 1 && moveTargets.multiple) { + this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); + } if (moveTargets.targets.length <= 1 || moveTargets.multiple) { turnCommand.move.targets = moveTargets.targets; } else if (playerPokemon.getTag(BattlerTagType.CHARGING) && playerPokemon.getMoveQueue().length >= 1) { @@ -2222,13 +2225,13 @@ export class SelectTargetPhase extends PokemonPhase { const turnCommand = this.scene.currentBattle.turnCommands[this.fieldIndex]; const move = turnCommand.move?.move; - this.scene.ui.setMode(Mode.TARGET_SELECT, this.fieldIndex, move, (cursor: integer) => { + this.scene.ui.setMode(Mode.TARGET_SELECT, this.fieldIndex, move, (targets: BattlerIndex[]) => { this.scene.ui.setMode(Mode.MESSAGE); - if (cursor === -1) { + if (targets.length < 1) { this.scene.currentBattle.turnCommands[this.fieldIndex] = null; this.scene.unshiftPhase(new CommandPhase(this.scene, this.fieldIndex)); } else { - turnCommand.targets = [cursor]; + turnCommand.targets = targets; } if (turnCommand.command === Command.BALL && this.fieldIndex) { this.scene.currentBattle.turnCommands[this.fieldIndex - 1].skip = true; diff --git a/src/test/utils/gameManager.ts b/src/test/utils/gameManager.ts index 84d39024dc9..ac18daaaada 100644 --- a/src/test/utils/gameManager.ts +++ b/src/test/utils/gameManager.ts @@ -8,7 +8,8 @@ import { LoginPhase, NewBattlePhase, SelectStarterPhase, - TitlePhase, TurnInitPhase, + SelectTargetPhase, + TitlePhase, TurnEndPhase, TurnInitPhase, TurnStartPhase, } from "#app/phases"; import BattleScene from "#app/battle-scene.js"; @@ -170,6 +171,15 @@ export default class GameManager { this.onNextPrompt("CommandPhase", Mode.FIGHT, () => { (this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false); }); + + // Confirm target selection if move is multi-target + this.onNextPrompt("SelectTargetPhase", Mode.TARGET_SELECT, () => { + const handler = this.scene.ui.getHandler() as TargetSelectUiHandler; + const move = (this.scene.getCurrentPhase() as SelectTargetPhase).getPokemon().getMoveset()[movePosition].getMove(); + if (move.isMultiTarget()) { + handler.processInput(Button.ACTION); + } + }, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(TurnEndPhase)); } /** diff --git a/src/ui/target-select-ui-handler.ts b/src/ui/target-select-ui-handler.ts index 772500e8901..48799473343 100644 --- a/src/ui/target-select-ui-handler.ts +++ b/src/ui/target-select-ui-handler.ts @@ -6,17 +6,20 @@ import * as Utils from "../utils"; import { getMoveTargets } from "../data/move"; import {Button} from "#enums/buttons"; import { Moves } from "#enums/moves"; +import Pokemon from "#app/field/pokemon.js"; -export type TargetSelectCallback = (cursor: integer) => void; +export type TargetSelectCallback = (targets: BattlerIndex[]) => void; export default class TargetSelectUiHandler extends UiHandler { private fieldIndex: integer; private move: Moves; private targetSelectCallback: TargetSelectCallback; + private isMultipleTargets: boolean = false; private targets: BattlerIndex[]; + private targetsHighlighted: Pokemon[]; private targetFlashTween: Phaser.Tweens.Tween; - private targetBattleInfoMoveTween: Phaser.Tweens.Tween; + private targetBattleInfoMoveTween: Phaser.Tweens.Tween[] = []; constructor(scene: BattleScene) { super(scene, Mode.TARGET_SELECT); @@ -37,13 +40,15 @@ export default class TargetSelectUiHandler extends UiHandler { this.move = args[1] as Moves; this.targetSelectCallback = args[2] as TargetSelectCallback; - this.targets = getMoveTargets(this.scene.getPlayerField()[this.fieldIndex], this.move).targets; + const moveTargets = getMoveTargets(this.scene.getPlayerField()[this.fieldIndex], this.move); + this.targets = moveTargets.targets; + this.isMultipleTargets = moveTargets.multiple ?? false; if (!this.targets.length) { return false; } - this.setCursor(this.targets.indexOf(this.cursor) > -1 ? this.cursor : this.targets[0]); + this.setCursor(this.targets.includes(this.cursor) ? this.cursor : this.targets[0]); return true; } @@ -54,8 +59,11 @@ export default class TargetSelectUiHandler extends UiHandler { let success = false; if (button === Button.ACTION || button === Button.CANCEL) { - this.targetSelectCallback(button === Button.ACTION ? this.cursor : -1); + const targetIndexes: BattlerIndex[] = this.isMultipleTargets ? this.targets : [this.cursor]; + this.targetSelectCallback(button === Button.ACTION ? targetIndexes : []); success = true; + } else if (this.isMultipleTargets) { + success = false; } else { switch (button) { case Button.UP: @@ -89,73 +97,71 @@ export default class TargetSelectUiHandler extends UiHandler { } setCursor(cursor: integer): boolean { - const lastCursor = this.cursor; + const singleTarget = this.scene.getField()[cursor]; + const multipleTargets = this.targets.map(index => this.scene.getField()[index]); + + this.targetsHighlighted = this.isMultipleTargets ? multipleTargets : [ singleTarget ]; const ret = super.setCursor(cursor); if (this.targetFlashTween) { this.targetFlashTween.stop(); - const lastTarget = this.scene.getField()[lastCursor]; - if (lastTarget) { - lastTarget.setAlpha(1); + for (const pokemon of multipleTargets) { + pokemon.setAlpha(1); } } - const target = this.scene.getField()[cursor]; - this.targetFlashTween = this.scene.tweens.add({ - targets: [ target ], + targets: this.targetsHighlighted, alpha: 0, loop: -1, duration: Utils.fixedInt(250), ease: "Sine.easeIn", yoyo: true, onUpdate: t => { - if (target) { + for (const target of this.targetsHighlighted) { target.setAlpha(t.getValue()); } } }); - - if (this.targetBattleInfoMoveTween) { - this.targetBattleInfoMoveTween.stop(); - const lastTarget = this.scene.getField()[lastCursor]; - if (lastTarget) { - lastTarget.getBattleInfo().resetY(); + if (this.targetBattleInfoMoveTween.length >= 1) { + this.targetBattleInfoMoveTween.filter(t => t !== undefined).forEach(tween => tween.stop()); + for (const pokemon of multipleTargets) { + pokemon.getBattleInfo().resetY(); } } - const targetBattleInfo = target.getBattleInfo(); + const targetsBattleInfo = this.targetsHighlighted.map(target => target.getBattleInfo()); - this.targetBattleInfoMoveTween = this.scene.tweens.add({ - targets: [ targetBattleInfo ], - y: { start: targetBattleInfo.getBaseY(), to: targetBattleInfo.getBaseY() + 1 }, - loop: -1, - duration: Utils.fixedInt(250), - ease: "Linear", - yoyo: true + targetsBattleInfo.map(info => { + this.targetBattleInfoMoveTween.push(this.scene.tweens.add({ + targets: [ info ], + y: { start: info.getBaseY(), to: info.getBaseY() + 1 }, + loop: -1, + duration: Utils.fixedInt(250), + ease: "Linear", + yoyo: true + })); }); return ret; } eraseCursor() { - const target = this.scene.getField()[this.cursor]; if (this.targetFlashTween) { this.targetFlashTween.stop(); this.targetFlashTween = null; } - if (target) { - target.setAlpha(1); + for (const pokemon of this.targetsHighlighted) { + pokemon.setAlpha(1); } - const targetBattleInfo = target.getBattleInfo(); - if (this.targetBattleInfoMoveTween) { - this.targetBattleInfoMoveTween.stop(); - this.targetBattleInfoMoveTween = null; + if (this.targetBattleInfoMoveTween.length >= 1) { + this.targetBattleInfoMoveTween.filter(t => t !== undefined).forEach(tween => tween.stop()); + this.targetBattleInfoMoveTween = []; } - if (targetBattleInfo) { - targetBattleInfo.resetY(); + for (const pokemon of this.targetsHighlighted) { + pokemon.getBattleInfo().resetY(); } }