mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-16 21:32:18 +02:00
Give IV-Scanner a menu and a toggle
This commit is contained in:
parent
7935f28089
commit
1db10e952b
@ -1,5 +1,5 @@
|
|||||||
import * as ModifierTypes from './modifier-type';
|
import * as ModifierTypes from './modifier-type';
|
||||||
import { LearnMovePhase, LevelUpPhase, PokemonHealPhase } from "../phases";
|
import { LearnMovePhase, LevelUpPhase, PokemonHealPhase, ScanIvsPhase, CommandPhase } from "../phases";
|
||||||
import BattleScene from "../battle-scene";
|
import BattleScene from "../battle-scene";
|
||||||
import { getLevelTotalExp } from "../data/exp";
|
import { getLevelTotalExp } from "../data/exp";
|
||||||
import { PokeballType } from "../data/pokeball";
|
import { PokeballType } from "../data/pokeball";
|
||||||
@ -21,6 +21,13 @@ import { Nature } from '#app/data/nature';
|
|||||||
import { BattlerTagType } from '#app/data/enums/battler-tag-type';
|
import { BattlerTagType } from '#app/data/enums/battler-tag-type';
|
||||||
import * as Overrides from '../overrides';
|
import * as Overrides from '../overrides';
|
||||||
import { ModifierType, modifierTypes } from './modifier-type';
|
import { ModifierType, modifierTypes } from './modifier-type';
|
||||||
|
import { Mode } from '#app/ui/ui.js';
|
||||||
|
import i18next from 'i18next';
|
||||||
|
import { BattleType } from '#app/battle.js';
|
||||||
|
import { battleMessageUiHandler } from '#app/locales/de/battle-message-ui-handler.js';
|
||||||
|
import BattleMessageUiHandler from '#app/ui/battle-message-ui-handler.js';
|
||||||
|
import Button from 'phaser3-rex-plugins/plugins/button';
|
||||||
|
import { CommonAnim, CommonBattleAnim } from '#app/data/battle-anims.js';
|
||||||
|
|
||||||
export type ModifierPredicate = (modifier: Modifier) => boolean;
|
export type ModifierPredicate = (modifier: Modifier) => boolean;
|
||||||
|
|
||||||
@ -70,6 +77,16 @@ export class ModifierBar extends Phaser.GameObjects.Container {
|
|||||||
if (this.modifierCache && this.modifierCache.length > iconOverflowIndex)
|
if (this.modifierCache && this.modifierCache.length > iconOverflowIndex)
|
||||||
thisArg.updateModifierOverflowVisibility(false);
|
thisArg.updateModifierOverflowVisibility(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pseudo-Click Events.
|
||||||
|
Pseudo because POINTER_DOWN is when input is down.
|
||||||
|
TODO: A real click is when mouse is down, and goes up
|
||||||
|
while still inside the element's X and Y.
|
||||||
|
*/
|
||||||
|
icon.on(Phaser.Input.Events.POINTER_DOWN, () => {
|
||||||
|
modifier.onClick(this.scene);
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let icon of this.getAll())
|
for (let icon of this.getAll())
|
||||||
@ -110,6 +127,8 @@ export abstract class Modifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract apply(args: any[]): boolean | Promise<boolean>;
|
abstract apply(args: any[]): boolean | Promise<boolean>;
|
||||||
|
|
||||||
|
onClick(scene: Phaser.Scene) {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class PersistentModifier extends Modifier {
|
export abstract class PersistentModifier extends Modifier {
|
||||||
@ -1925,6 +1944,10 @@ export class IvScannerModifier extends PersistentModifier {
|
|||||||
super(type, stackCount);
|
super(type, stackCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Whether the IV-Scanner, should auto-prompt each wave.
|
||||||
|
public shouldAutoPrompt: boolean = true;
|
||||||
|
private isForceScanning: boolean = false;
|
||||||
|
|
||||||
match(modifier: Modifier): boolean {
|
match(modifier: Modifier): boolean {
|
||||||
return modifier instanceof IvScannerModifier;
|
return modifier instanceof IvScannerModifier;
|
||||||
}
|
}
|
||||||
@ -1940,6 +1963,133 @@ export class IvScannerModifier extends PersistentModifier {
|
|||||||
getMaxStackCount(scene: BattleScene): integer {
|
getMaxStackCount(scene: BattleScene): integer {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Opens the menu for the IV Scanner
|
||||||
|
// Does not implement own sanity checks.
|
||||||
|
openIvScannerMenu(scene: BattleScene): void {
|
||||||
|
// Only if not a Trainer
|
||||||
|
if (scene.currentBattle.battleType !== BattleType.WILD) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We shall prevent this phase being stacked through clicks.
|
||||||
|
if (scene.getCurrentPhase() instanceof ScanIvsPhase)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
// Interrupt the current phase, if it is our turn
|
||||||
|
if (!(scene.getCurrentPhase() instanceof CommandPhase)) {
|
||||||
|
//console.log("Not our turn!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var commandPhase = scene.getCurrentPhase() as CommandPhase;
|
||||||
|
const enemyField = scene.getEnemyField();
|
||||||
|
|
||||||
|
var scanOptions = [];
|
||||||
|
|
||||||
|
// Create buttons for every enemy Pokemon
|
||||||
|
enemyField.map(pokemon => {
|
||||||
|
scanOptions.push({
|
||||||
|
label: `Scan: ${pokemon.name}`,
|
||||||
|
handler: () => {
|
||||||
|
scene.ui.revertMode(); // hide commandPhase controls
|
||||||
|
|
||||||
|
// Show prompt
|
||||||
|
// Handler to close the IV Prompt
|
||||||
|
|
||||||
|
scene.ui.setMode(Mode.MESSAGE);
|
||||||
|
scene.ui.clearText();
|
||||||
|
|
||||||
|
scene.ui.showText(`${pokemon.name}`, null, () => {
|
||||||
|
new CommonBattleAnim(CommonAnim.LOCK_ON, pokemon, pokemon).play(scene, () => {
|
||||||
|
scene.ui.getMessageHandler().promptIvs(pokemon.id, pokemon.ivs, Math.min(this.getStackCount() * 2, 6))
|
||||||
|
|
||||||
|
// promptIvs has its own Action Handler, and once that is executed, the promise is resolved
|
||||||
|
.then(() => {
|
||||||
|
scene.ui.showText(null, 0);
|
||||||
|
// go back to our commandPhase prompt
|
||||||
|
scene.ui.setMode(Mode.COMMAND, commandPhase.getFieldIndex());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
keepOpen: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const ivOptions = [
|
||||||
|
{
|
||||||
|
// Label automatically changes text.
|
||||||
|
label: `Toggle ${this.shouldAutoPrompt ? "OFF" : "ON"}`,
|
||||||
|
handler: () => {
|
||||||
|
scene.ui.revertMode();
|
||||||
|
// Message Confirmation Mode
|
||||||
|
scene.ui.setMode(Mode.MESSAGE);
|
||||||
|
|
||||||
|
// Toggle
|
||||||
|
this.shouldAutoPrompt = !this.shouldAutoPrompt;
|
||||||
|
|
||||||
|
let textToShow = `IV-Scanner auto-prompt\nhas been toggled ${this.shouldAutoPrompt ? "ON" : "OFF"}`;
|
||||||
|
|
||||||
|
scene.ui.showText(textToShow, null, () => {
|
||||||
|
scene.ui.showText(null, 0);
|
||||||
|
// go back to our commandPhase prompt
|
||||||
|
scene.ui.setMode(Mode.COMMAND, commandPhase.getFieldIndex());
|
||||||
|
}, null, true);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Prevents the container from closing after selecting
|
||||||
|
keepOpen: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Auto put in the Pokemon Scan options right here!
|
||||||
|
// Thanks to the --> ...
|
||||||
|
...scanOptions.map(option => ({
|
||||||
|
...option,
|
||||||
|
})),
|
||||||
|
|
||||||
|
{
|
||||||
|
label: i18next.t('menuUiHandler:cancel'),
|
||||||
|
handler: () => {
|
||||||
|
scene.ui.revertMode(); // closes the container ui
|
||||||
|
|
||||||
|
scene.ui.setMode(Mode.COMMAND, commandPhase.getFieldIndex());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const ivOptionsConfig = {
|
||||||
|
xOffset: 98,
|
||||||
|
options: ivOptions
|
||||||
|
};
|
||||||
|
|
||||||
|
scene.ui.setOverlayMode(Mode.MENU_OPTION_SELECT, ivOptionsConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Click Event for the IV-Scanner
|
||||||
|
onClick(scene: BattleScene): void {
|
||||||
|
this.openIvScannerMenu(scene);
|
||||||
|
|
||||||
|
// Put in queue at the top.
|
||||||
|
//scene.unshiftPhase(scene.getCurrentPhase());
|
||||||
|
|
||||||
|
// Add a Phase for every enemy.
|
||||||
|
/*enemyField.map(
|
||||||
|
p => {
|
||||||
|
var iv = new ScanIvsPhase(scene, p.getBattlerIndex(), Math.min(this.getStackCount() * 2, 6))
|
||||||
|
scene.unshiftPhase(iv);
|
||||||
|
}
|
||||||
|
);*/
|
||||||
|
|
||||||
|
// Interrupt the CommandPhase
|
||||||
|
//scene.shiftPhase();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ExtraModifierModifier extends PersistentModifier {
|
export class ExtraModifierModifier extends PersistentModifier {
|
||||||
|
@ -4828,6 +4828,12 @@ export class ScanIvsPhase extends PokemonPhase {
|
|||||||
|
|
||||||
const pokemon = this.getPokemon();
|
const pokemon = this.getPokemon();
|
||||||
|
|
||||||
|
const ivScannerModifier = this.scene.findModifier(m => m instanceof IvScannerModifier) as IvScannerModifier;
|
||||||
|
|
||||||
|
// Only show if auto-prompt is enabled.
|
||||||
|
if (!ivScannerModifier.shouldAutoPrompt)
|
||||||
|
return this.end()
|
||||||
|
|
||||||
this.scene.ui.showText(i18next.t('battle:ivScannerUseQuestion', { pokemonName: pokemon.name }), null, () => {
|
this.scene.ui.showText(i18next.t('battle:ivScannerUseQuestion', { pokemonName: pokemon.name }), null, () => {
|
||||||
this.scene.ui.setMode(Mode.CONFIRM, () => {
|
this.scene.ui.setMode(Mode.CONFIRM, () => {
|
||||||
this.scene.ui.setMode(Mode.MESSAGE);
|
this.scene.ui.setMode(Mode.MESSAGE);
|
||||||
|
@ -7,12 +7,16 @@ import { Mode } from "./ui";
|
|||||||
import UiHandler from "./ui-handler";
|
import UiHandler from "./ui-handler";
|
||||||
import { addWindow } from "./ui-theme";
|
import { addWindow } from "./ui-theme";
|
||||||
import {Button} from "../enums/buttons";
|
import {Button} from "../enums/buttons";
|
||||||
|
import { IvScannerModifier } from "#app/modifier/modifier.js";
|
||||||
|
|
||||||
export default class BallUiHandler extends UiHandler {
|
export default class BallUiHandler extends UiHandler {
|
||||||
private pokeballSelectContainer: Phaser.GameObjects.Container;
|
private pokeballSelectContainer: Phaser.GameObjects.Container;
|
||||||
private pokeballSelectBg: Phaser.GameObjects.NineSlice;
|
private pokeballSelectBg: Phaser.GameObjects.NineSlice;
|
||||||
|
private optionsText: Phaser.GameObjects.Text;
|
||||||
private countsText: Phaser.GameObjects.Text;
|
private countsText: Phaser.GameObjects.Text;
|
||||||
|
|
||||||
|
private ivScannerAdded = false;
|
||||||
|
|
||||||
private cursorObj: Phaser.GameObjects.Image;
|
private cursorObj: Phaser.GameObjects.Image;
|
||||||
|
|
||||||
constructor(scene: BattleScene) {
|
constructor(scene: BattleScene) {
|
||||||
@ -32,14 +36,17 @@ export default class BallUiHandler extends UiHandler {
|
|||||||
|
|
||||||
let optionsTextContent = '';
|
let optionsTextContent = '';
|
||||||
|
|
||||||
for (let pb = 0; pb < Object.keys(this.scene.pokeballCounts).length; pb++)
|
// For every Pokeball, add them to the text content.
|
||||||
|
for (let pb = 0; pb < Object.keys(this.scene.pokeballCounts).length; pb++) {
|
||||||
optionsTextContent += `${getPokeballName(pb)}\n`;
|
optionsTextContent += `${getPokeballName(pb)}\n`;
|
||||||
optionsTextContent += 'Cancel';
|
}
|
||||||
const optionsText = addTextObject(this.scene, 0, 0, optionsTextContent, TextStyle.WINDOW, { align: 'right', maxLines: 6 });
|
optionsTextContent += 'Cancel'; // Warning, "Cancel", is used in a RegExp.
|
||||||
optionsText.setOrigin(0, 0);
|
|
||||||
optionsText.setPositionRelative(this.pokeballSelectBg, 42, 9);
|
this.optionsText = addTextObject(this.scene, 0, 0, optionsTextContent, TextStyle.WINDOW, { align: 'right', maxLines: 6 });
|
||||||
optionsText.setLineSpacing(12);
|
this.optionsText.setOrigin(0, 0);
|
||||||
this.pokeballSelectContainer.add(optionsText);
|
this.optionsText.setPositionRelative(this.pokeballSelectBg, 42, 9);
|
||||||
|
this.optionsText.setLineSpacing(12);
|
||||||
|
this.pokeballSelectContainer.add(this.optionsText);
|
||||||
|
|
||||||
this.countsText = addTextObject(this.scene, 0, 0, '', TextStyle.WINDOW, { maxLines: 5 });
|
this.countsText = addTextObject(this.scene, 0, 0, '', TextStyle.WINDOW, { maxLines: 5 });
|
||||||
this.countsText.setPositionRelative(this.pokeballSelectBg, 18, 9);
|
this.countsText.setPositionRelative(this.pokeballSelectBg, 18, 9);
|
||||||
@ -49,9 +56,33 @@ export default class BallUiHandler extends UiHandler {
|
|||||||
this.setCursor(0);
|
this.setCursor(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updatePositions(): void {
|
||||||
|
this.optionsText.setPositionRelative(this.pokeballSelectBg, 42, 9);
|
||||||
|
this.countsText.setPositionRelative(this.pokeballSelectBg, 18, 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
addIvScanner(): void {
|
||||||
|
if (this.ivScannerAdded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.ivScannerAdded = true;
|
||||||
|
this.optionsText.setText(
|
||||||
|
this.optionsText.text.replace(new RegExp("Cancel", "g"), "IV-Scanner\nCancel")
|
||||||
|
);
|
||||||
|
this.optionsText.setMaxLines(7);
|
||||||
|
|
||||||
|
this.pokeballSelectBg.height = 112 + 12;
|
||||||
|
this.updatePositions();
|
||||||
|
}
|
||||||
|
|
||||||
show(args: any[]): boolean {
|
show(args: any[]): boolean {
|
||||||
super.show(args);
|
super.show(args);
|
||||||
|
|
||||||
|
const ivScannerModifier = this.scene.findModifier(m => m instanceof IvScannerModifier) as IvScannerModifier;
|
||||||
|
if (ivScannerModifier) {
|
||||||
|
this.addIvScanner();
|
||||||
|
}
|
||||||
|
|
||||||
this.updateCounts();
|
this.updateCounts();
|
||||||
this.pokeballSelectContainer.setVisible(true);
|
this.pokeballSelectContainer.setVisible(true);
|
||||||
this.setCursor(this.cursor);
|
this.setCursor(this.cursor);
|
||||||
@ -65,6 +96,7 @@ export default class BallUiHandler extends UiHandler {
|
|||||||
let success = false;
|
let success = false;
|
||||||
|
|
||||||
const pokeballTypeCount = Object.keys(this.scene.pokeballCounts).length;
|
const pokeballTypeCount = Object.keys(this.scene.pokeballCounts).length;
|
||||||
|
let maxLines = this.optionsText.style.maxLines;
|
||||||
|
|
||||||
if (button === Button.ACTION || button === Button.CANCEL) {
|
if (button === Button.ACTION || button === Button.CANCEL) {
|
||||||
const commandPhase = this.scene.getCurrentPhase() as CommandPhase;
|
const commandPhase = this.scene.getCurrentPhase() as CommandPhase;
|
||||||
@ -78,6 +110,15 @@ export default class BallUiHandler extends UiHandler {
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
ui.playError();
|
ui.playError();
|
||||||
|
|
||||||
|
} else if (button === Button.ACTION && this.cursor < (pokeballTypeCount+1) && this.ivScannerAdded) {
|
||||||
|
this.scene.ui.revertMode();
|
||||||
|
ui.setMode(Mode.COMMAND, commandPhase.getFieldIndex());
|
||||||
|
|
||||||
|
const ivScannerModifier = this.scene.findModifier(m => m instanceof IvScannerModifier) as IvScannerModifier;
|
||||||
|
ivScannerModifier.openIvScannerMenu(this.scene);
|
||||||
|
|
||||||
|
success = true;
|
||||||
} else {
|
} else {
|
||||||
ui.setMode(Mode.COMMAND, commandPhase.getFieldIndex());
|
ui.setMode(Mode.COMMAND, commandPhase.getFieldIndex());
|
||||||
success = true;
|
success = true;
|
||||||
@ -85,10 +126,10 @@ export default class BallUiHandler extends UiHandler {
|
|||||||
} else {
|
} else {
|
||||||
switch (button) {
|
switch (button) {
|
||||||
case Button.UP:
|
case Button.UP:
|
||||||
success = this.setCursor(this.cursor ? this.cursor - 1 : pokeballTypeCount);
|
success = this.setCursor(this.cursor ? this.cursor - 1 : (maxLines-1));
|
||||||
break;
|
break;
|
||||||
case Button.DOWN:
|
case Button.DOWN:
|
||||||
success = this.setCursor(this.cursor < pokeballTypeCount ? this.cursor + 1 : 0);
|
success = this.setCursor(this.cursor < (maxLines-1) ? this.cursor + 1 : 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user