[QoL] Move Info Overlay (#1585)
* move info implemented for starter selection a move info box is displayed when editing the starter moveset. also menus have now onHover triggers. todo: - show ui when selecting TMs - show ui when selecting moves to remember (memory mushroom) * More Move Info Overlays Added overlays during Memory Mushroom use and when viewing TMs. Furthermore a settings option can enable/disable those overlays. * Added missing ko language entry ... though translation still remains necessary * updated ui also added overrides for item rewards * minor ui update moved values to the right in the tm move info box * fixed typedoc issues * removed settings in to prepare for merge * updated settings option added settings option to new settings implementation * minor changes removed unused graphic moved settings option to accessibility
This commit is contained in:
parent
c5689dfc96
commit
1c98106642
|
@ -80,6 +80,11 @@ export interface PokeballCounts {
|
|||
|
||||
export type AnySound = Phaser.Sound.WebAudioSound | Phaser.Sound.HTML5AudioSound | Phaser.Sound.NoAudioSound;
|
||||
|
||||
export interface InfoToggle {
|
||||
toggleInfo(force?: boolean): void;
|
||||
isActive(): boolean;
|
||||
}
|
||||
|
||||
export default class BattleScene extends SceneBase {
|
||||
public rexUI: UIPlugin;
|
||||
public inputController: InputsController;
|
||||
|
@ -97,6 +102,7 @@ export default class BattleScene extends SceneBase {
|
|||
public showArenaFlyout: boolean = true;
|
||||
public showLevelUpStats: boolean = true;
|
||||
public enableTutorials: boolean = import.meta.env.VITE_BYPASS_TUTORIAL === "1";
|
||||
public enableMoveInfo: boolean = true;
|
||||
public enableRetries: boolean = false;
|
||||
/**
|
||||
* Determines the condition for a notification should be shown for Candy Upgrades
|
||||
|
@ -209,6 +215,8 @@ export default class BattleScene extends SceneBase {
|
|||
public rngSeedOverride: string = "";
|
||||
public rngOffset: integer = 0;
|
||||
|
||||
private infoToggles: InfoToggle[] = [];
|
||||
|
||||
/**
|
||||
* Allows subscribers to listen for events
|
||||
*
|
||||
|
@ -682,6 +690,16 @@ export default class BattleScene extends SceneBase {
|
|||
: ret;
|
||||
}
|
||||
|
||||
// store info toggles to be accessible by the ui
|
||||
addInfoToggle(infoToggle: InfoToggle): void {
|
||||
this.infoToggles.push(infoToggle);
|
||||
}
|
||||
|
||||
// return the stored info toggles; used by ui-inputs
|
||||
getInfoToggles(activeOnly: boolean = false): InfoToggle[] {
|
||||
return activeOnly ? this.infoToggles.filter(t => t?.isActive()) : this.infoToggles;
|
||||
}
|
||||
|
||||
getPokemonById(pokemonId: integer): Pokemon {
|
||||
const findInParty = (party: Pokemon[]) => party.find(p => p.id === pokemonId);
|
||||
return findInParty(this.getParty()) || findInParty(this.getEnemyParty());
|
||||
|
|
|
@ -127,6 +127,7 @@ export class LoadingScene extends SceneBase {
|
|||
this.loadImage("summary_stats_overlay_exp", "ui");
|
||||
this.loadImage("summary_moves", "ui");
|
||||
this.loadImage("summary_moves_effect", "ui");
|
||||
this.loadImage("summary_moves_effect_type", "ui");
|
||||
this.loadImage("summary_moves_overlay_row", "ui");
|
||||
this.loadImage("summary_moves_overlay_pp", "ui");
|
||||
this.loadAtlas("summary_moves_cursor", "ui");
|
||||
|
|
|
@ -99,6 +99,10 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
name: "TM{{moveId}} - {{moveName}}",
|
||||
description: "Bringt einem Pokémon {{moveName}} bei",
|
||||
},
|
||||
"TmModifierTypeWithInfo": {
|
||||
name: "TM{{moveId}} - {{moveName}}",
|
||||
description: "Bringt einem Pokémon {{moveName}} bei\n(Halte C oder Shift für mehr Infos)",
|
||||
},
|
||||
"EvolutionItemModifierType": {
|
||||
description: "Erlaubt es bestimmten Pokémon sich zu entwickeln",
|
||||
},
|
||||
|
|
|
@ -99,6 +99,10 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
name: "TM{{moveId}} - {{moveName}}",
|
||||
description: "Teach {{moveName}} to a Pokémon",
|
||||
},
|
||||
"TmModifierTypeWithInfo": {
|
||||
name: "TM{{moveId}} - {{moveName}}",
|
||||
description: "Teach {{moveName}} to a Pokémon\n(Hold C or Shift for more info)",
|
||||
},
|
||||
"EvolutionItemModifierType": {
|
||||
description: "Causes certain Pokémon to evolve",
|
||||
},
|
||||
|
|
|
@ -99,6 +99,10 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
name: "MT{{moveId}} - {{moveName}}",
|
||||
description: "Enseña {{moveName}} a un Pokémon",
|
||||
},
|
||||
"TmModifierTypeWithInfo": {
|
||||
name: "MT{{moveId}} - {{moveName}}",
|
||||
description: "Enseña {{moveName}} a un Pokémon\n(Hold C or Shift for more info)",
|
||||
},
|
||||
"EvolutionItemModifierType": {
|
||||
description: "Hace que ciertos Pokémon evolucionen",
|
||||
},
|
||||
|
|
|
@ -99,6 +99,10 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
name: "CT{{moveId}} - {{moveName}}",
|
||||
description: "Apprend la capacité {{moveName}} à un Pokémon",
|
||||
},
|
||||
"TmModifierTypeWithInfo": {
|
||||
name: "CT{{moveId}} - {{moveName}}",
|
||||
description: "Apprend la capacité {{moveName}} à un Pokémon\n(Hold C or Shift for more info)",
|
||||
},
|
||||
"EvolutionItemModifierType": {
|
||||
description: "Permet à certains Pokémon d’évoluer",
|
||||
},
|
||||
|
|
|
@ -99,6 +99,10 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
name: "MT{{moveId}} - {{moveName}}",
|
||||
description: "Insegna {{moveName}} a un Pokémon",
|
||||
},
|
||||
"TmModifierTypeWithInfo": {
|
||||
name: "MT{{moveId}} - {{moveName}}",
|
||||
description: "Insegna {{moveName}} a un Pokémon\n(Hold C or Shift for more info)",
|
||||
},
|
||||
"EvolutionItemModifierType": {
|
||||
description: "Fa evolvere determinate specie di Pokémon",
|
||||
},
|
||||
|
|
|
@ -99,6 +99,10 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
name: "No.{{moveId}} {{moveName}}",
|
||||
description: "포켓몬에게 {{moveName}}[[를]] 가르침",
|
||||
},
|
||||
"TmModifierTypeWithInfo": {
|
||||
name: "No.{{moveId}} {{moveName}}",
|
||||
description: "포켓몬에게 {{moveName}}를(을) 가르침\n(Hold C or Shift for more info)",
|
||||
},
|
||||
"EvolutionItemModifierType": {
|
||||
description: "어느 특정 포켓몬을 진화",
|
||||
},
|
||||
|
|
|
@ -99,6 +99,10 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
name: "TM{{moveId}} - {{moveName}}",
|
||||
description: "Ensina {{moveName}} a um Pokémon",
|
||||
},
|
||||
"TmModifierTypeWithInfo": {
|
||||
name: "TM{{moveId}} - {{moveName}}",
|
||||
description: "Ensina {{moveName}} a um Pokémon\n(Hold C or Shift for more info)",
|
||||
},
|
||||
"EvolutionItemModifierType": {
|
||||
description: "Faz certos Pokémon evoluírem",
|
||||
},
|
||||
|
|
|
@ -99,6 +99,10 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
name: "招式学习器 {{moveId}} - {{moveName}}",
|
||||
description: "教会一只宝可梦{{moveName}}",
|
||||
},
|
||||
"TmModifierTypeWithInfo": {
|
||||
name: "招式学习器 {{moveId}} - {{moveName}}",
|
||||
description: "教会一只宝可梦{{moveName}}\n(Hold C or Shift for more info)",
|
||||
},
|
||||
"EvolutionItemModifierType": {
|
||||
description: "使某些宝可梦进化",
|
||||
},
|
||||
|
|
|
@ -98,6 +98,10 @@ export const modifierType: ModifierTypeTranslationEntries = {
|
|||
name: "招式學習器 {{moveId}} - {{moveName}}",
|
||||
description: "教會一隻寶可夢{{moveName}}",
|
||||
},
|
||||
TmModifierTypeWithInfo: {
|
||||
name: "TM{{moveId}} - {{moveName}}",
|
||||
description: "教會一隻寶可夢{{moveName}}\n(Hold C or Shift for more info)",
|
||||
},
|
||||
EvolutionItemModifierType: { description: "使某些寶可夢進化" },
|
||||
FormChangeItemModifierType: { description: "使某些寶可夢更改形態" },
|
||||
FusePokemonModifierType: {
|
||||
|
|
|
@ -23,6 +23,7 @@ import { ModifierTier } from "./modifier-tier";
|
|||
import { Nature, getNatureName, getNatureStatMultiplier } from "#app/data/nature";
|
||||
import i18next from "#app/plugins/i18n";
|
||||
import { getModifierTierTextTint } from "#app/ui/text";
|
||||
import * as Overrides from "../overrides";
|
||||
|
||||
const outputModifierData = false;
|
||||
const useMaxWeightForOutput = false;
|
||||
|
@ -721,7 +722,7 @@ export class TmModifierType extends PokemonModifierType {
|
|||
}
|
||||
|
||||
getDescription(scene: BattleScene): string {
|
||||
return i18next.t("modifierType:ModifierType.TmModifierType.description", { moveName: allMoves[this.moveId].name });
|
||||
return i18next.t(scene.enableMoveInfo ? "modifierType:ModifierType.TmModifierTypeWithInfo.description" : "modifierType:ModifierType.TmModifierType.description", { moveName: allMoves[this.moveId].name });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1673,6 +1674,14 @@ export function getPlayerModifierTypeOptions(count: integer, party: PlayerPokemo
|
|||
}
|
||||
options.push(candidate);
|
||||
});
|
||||
// OVERRIDE IF NECESSARY
|
||||
if (Overrides.ITEM_REWARD_OVERRIDE?.length) {
|
||||
options.forEach((mod, i) => {
|
||||
// @ts-ignore: keeps throwing don't use string as index error in typedoc run
|
||||
const override = modifierTypes[Overrides.ITEM_REWARD_OVERRIDE[i]]?.();
|
||||
mod.type = (override instanceof ModifierTypeGenerator ? override.generateType(party) : override) || mod.type;
|
||||
});
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
|
|
|
@ -110,3 +110,11 @@ export const OPP_MODIFIER_OVERRIDE: Array<ModifierOverride> = [];
|
|||
|
||||
export const STARTING_HELD_ITEMS_OVERRIDE: Array<ModifierOverride> = [];
|
||||
export const OPP_HELD_ITEMS_OVERRIDE: Array<ModifierOverride> = [];
|
||||
|
||||
/**
|
||||
* An array of items by keys as defined in the "modifierTypes" object in the "modifier/modifier-type.ts" file.
|
||||
* Items listed will replace the normal rolls.
|
||||
* If less items are listed than rolled, only some items will be replaced
|
||||
* If more items are listed than rolled, only the first X items will be shown, where X is the number of items rolled.
|
||||
*/
|
||||
export const ITEM_REWARD_OVERRIDE: Array<String> = [];
|
||||
|
|
|
@ -44,6 +44,7 @@ export const SettingKeys = {
|
|||
UI_Theme: "UI_THEME",
|
||||
Window_Type: "WINDOW_TYPE",
|
||||
Tutorials: "TUTORIALS",
|
||||
Move_Info: "MOVE_INFO",
|
||||
Enable_Retries: "ENABLE_RETRIES",
|
||||
Skip_Seen_Dialogues: "SKIP_SEEN_DIALOGUES",
|
||||
Candy_Upgrade_Notification: "CANDY_UPGRADE_NOTIFICATION",
|
||||
|
@ -132,6 +133,13 @@ export const Setting: Array<Setting> = [
|
|||
default: 1,
|
||||
type: SettingType.GENERAL
|
||||
},
|
||||
{
|
||||
key: SettingKeys.Move_Info,
|
||||
label: "Move Info",
|
||||
options: OFF_ON,
|
||||
default: 1,
|
||||
type: SettingType.ACCESSIBILITY
|
||||
},
|
||||
{
|
||||
key: SettingKeys.Enable_Retries,
|
||||
label: "Enable Retries",
|
||||
|
@ -312,6 +320,9 @@ export function setSetting(scene: BattleScene, setting: string, value: integer):
|
|||
case SettingKeys.Tutorials:
|
||||
scene.enableTutorials = Setting[index].options[value] === "On";
|
||||
break;
|
||||
case SettingKeys.Move_Info:
|
||||
scene.enableMoveInfo = Setting[index].options[value] === "On";
|
||||
break;
|
||||
case SettingKeys.Enable_Retries:
|
||||
scene.enableRetries = Setting[index].options[value] === "On";
|
||||
break;
|
||||
|
|
|
@ -114,6 +114,11 @@ export class UiInputs {
|
|||
}
|
||||
|
||||
buttonStats(pressed: boolean = true): void {
|
||||
// allow access to Button.STATS as a toggle for other elements
|
||||
for (const t of this.scene.getInfoToggles(true)) {
|
||||
t.toggleInfo(pressed);
|
||||
}
|
||||
// handle normal pokemon battle ui
|
||||
for (const p of this.scene.getField().filter(p => p?.isActive(true))) {
|
||||
p.toggleStats(pressed);
|
||||
}
|
||||
|
|
|
@ -14,15 +14,17 @@ export interface OptionSelectConfig {
|
|||
maxOptions?: integer;
|
||||
delay?: integer;
|
||||
noCancel?: boolean;
|
||||
supportHover?: boolean;
|
||||
}
|
||||
|
||||
export interface OptionSelectItem {
|
||||
label: string;
|
||||
handler: () => boolean;
|
||||
onHover?: () => void;
|
||||
keepOpen?: boolean;
|
||||
overrideSound?: boolean;
|
||||
item?: string;
|
||||
itemArgs?: any[]
|
||||
itemArgs?: any[];
|
||||
}
|
||||
|
||||
const scrollUpLabel = "↑";
|
||||
|
@ -193,6 +195,10 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (this.config?.supportHover) {
|
||||
// handle hover code if the element supports hover-handlers and the option has the optional hover-handler set.
|
||||
this.config?.options[this.cursor + (this.scrollCursor - (this.scrollCursor ? 1 : 0))]?.onHover?.();
|
||||
}
|
||||
}
|
||||
|
||||
if (success && playSound) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import BattleScene from "../battle-scene";
|
||||
import { getPlayerShopModifierTypeOptionsForWave, ModifierTypeOption } from "../modifier/modifier-type";
|
||||
import { getPlayerShopModifierTypeOptionsForWave, ModifierTypeOption, TmModifierType } from "../modifier/modifier-type";
|
||||
import { getPokeballAtlasKey, PokeballType } from "../data/pokeball";
|
||||
import { addTextObject, getModifierTierTextTint, getTextColor, TextStyle } from "./text";
|
||||
import AwaitableUiHandler from "./awaitable-ui-handler";
|
||||
|
@ -7,6 +7,8 @@ import { Mode } from "./ui";
|
|||
import { LockModifierTiersModifier, PokemonHeldItemModifier } from "../modifier/modifier";
|
||||
import { handleTutorial, Tutorial } from "../tutorial";
|
||||
import {Button} from "../enums/buttons";
|
||||
import MoveInfoOverlay from "./move-info-overlay";
|
||||
import { allMoves } from "../data/move";
|
||||
|
||||
export const SHOP_OPTIONS_ROW_LIMIT = 6;
|
||||
|
||||
|
@ -17,6 +19,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
private transferButtonContainer: Phaser.GameObjects.Container;
|
||||
private rerollCostText: Phaser.GameObjects.Text;
|
||||
private lockRarityButtonText: Phaser.GameObjects.Text;
|
||||
private moveInfoOverlay : MoveInfoOverlay;
|
||||
|
||||
private rowCursor: integer = 0;
|
||||
private player: boolean;
|
||||
|
@ -73,6 +76,21 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
this.lockRarityButtonText = addTextObject(this.scene, -4, -2, "Lock Rarities", TextStyle.PARTY);
|
||||
this.lockRarityButtonText.setOrigin(0, 0);
|
||||
this.lockRarityButtonContainer.add(this.lockRarityButtonText);
|
||||
|
||||
// prepare move overlay
|
||||
const overlayScale = 1;
|
||||
this.moveInfoOverlay = new MoveInfoOverlay(this.scene, {
|
||||
delayVisibility: true,
|
||||
scale: overlayScale,
|
||||
onSide: true,
|
||||
right: true,
|
||||
x: 1,
|
||||
y: -MoveInfoOverlay.getHeight(overlayScale, true) -1,
|
||||
width: (this.scene.game.canvas.width / 6) - 2,
|
||||
});
|
||||
ui.add(this.moveInfoOverlay);
|
||||
// register the overlay to receive toggle events
|
||||
this.scene.addInfoToggle(this.moveInfoOverlay);
|
||||
}
|
||||
|
||||
show(args: any[]): boolean {
|
||||
|
@ -293,6 +311,8 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
|
||||
this.cursorObj.setScale(this.rowCursor === 1 ? 2 : this.rowCursor >= 2 ? 1.5 : 1);
|
||||
|
||||
// the modifier selection has been updated, always hide the overlay
|
||||
this.moveInfoOverlay.clear();
|
||||
if (this.rowCursor) {
|
||||
const sliceWidth = (this.scene.game.canvas.width / 6) / (options.length + 2);
|
||||
if (this.rowCursor < 2) {
|
||||
|
@ -300,7 +320,13 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
|||
} else {
|
||||
this.cursorObj.setPosition(sliceWidth * (cursor + 1) + (sliceWidth * 0.5) - 16, (-this.scene.game.canvas.height / 12 - this.scene.game.canvas.height / 32) - (-16 + 28 * (this.rowCursor - (this.shopOptionsRows.length - 1))));
|
||||
}
|
||||
ui.showText(options[this.cursor].modifierTypeOption.type.getDescription(this.scene));
|
||||
|
||||
const type = options[this.cursor].modifierTypeOption.type;
|
||||
ui.showText(type.getDescription(this.scene));
|
||||
if (type instanceof TmModifierType) {
|
||||
// prepare the move overlay to be shown with the toggle
|
||||
this.moveInfoOverlay.show(allMoves[type.moveId]);
|
||||
}
|
||||
} else if (!cursor) {
|
||||
this.cursorObj.setPosition(6, this.lockRarityButtonContainer.visible ? -72 : -60);
|
||||
ui.showText("Spend money to reroll your item options.");
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
import BattleScene, {InfoToggle} from "../battle-scene";
|
||||
import { TextStyle, addTextObject } from "./text";
|
||||
import { addWindow } from "./ui-theme";
|
||||
import * as Utils from "../utils";
|
||||
import Move, { MoveCategory } from "../data/move";
|
||||
import { Type } from "../data/type";
|
||||
import i18next from "i18next";
|
||||
|
||||
export interface MoveInfoOverlaySettings {
|
||||
delayVisibility?: boolean; // if true, showing the overlay will only set it to active and populate the fields and the handler using this field has to manually call setVisible later.
|
||||
scale?:number; // scale the box? A scale of 0.5 is recommended
|
||||
top?: boolean; // should the effect box be on top?
|
||||
right?: boolean; // should the effect box be on the right?
|
||||
onSide?: boolean; // should the effect be on the side? ignores top argument if true
|
||||
//location and width of the component; unaffected by scaling
|
||||
x?: number;
|
||||
y?: number;
|
||||
width?: number; // default is always half the screen, regardless of scale
|
||||
}
|
||||
|
||||
const EFF_HEIGHT = 46;
|
||||
const EFF_WIDTH = 82;
|
||||
const DESC_HEIGHT = 46;
|
||||
const BORDER = 8;
|
||||
const GLOBAL_SCALE = 6;
|
||||
|
||||
export default class MoveInfoOverlay extends Phaser.GameObjects.Container implements InfoToggle {
|
||||
public active: boolean = false;
|
||||
|
||||
private move: Move;
|
||||
|
||||
private desc: Phaser.GameObjects.Text;
|
||||
private descScroll : Phaser.Tweens.Tween = null;
|
||||
|
||||
private val: Phaser.GameObjects.Container;
|
||||
private pp: Phaser.GameObjects.Text;
|
||||
private pow: Phaser.GameObjects.Text;
|
||||
private acc: Phaser.GameObjects.Text;
|
||||
private typ: Phaser.GameObjects.Sprite;
|
||||
private cat: Phaser.GameObjects.Sprite;
|
||||
|
||||
private options : MoveInfoOverlaySettings;
|
||||
|
||||
constructor(scene: BattleScene, options?: MoveInfoOverlaySettings) {
|
||||
if (options?.onSide) {
|
||||
options.top = false;
|
||||
}
|
||||
super(scene, options?.x, options?.y);
|
||||
const scale = options?.scale || 1; // set up the scale
|
||||
this.setScale(scale);
|
||||
this.options = options || {};
|
||||
|
||||
// prepare the description box
|
||||
const width = (options?.width || MoveInfoOverlay.getWidth(scale, scene)) / scale; // divide by scale as we always want this to be half a window wide
|
||||
const descBg = addWindow(scene, (options?.onSide && !options?.right ? EFF_WIDTH : 0), options?.top ? EFF_HEIGHT : 0, width - (options?.onSide ? EFF_WIDTH : 0), DESC_HEIGHT);
|
||||
descBg.setOrigin(0, 0);
|
||||
this.add(descBg);
|
||||
|
||||
// set up the description; wordWrap uses true pixels, unaffected by any scaling, while other values are affected
|
||||
this.desc = addTextObject(scene, (options?.onSide && !options?.right ? EFF_WIDTH : 0) + BORDER, (options?.top ? EFF_HEIGHT : 0) + BORDER - 2, "", TextStyle.BATTLE_INFO, { wordWrap: { width: (width - (BORDER - 2) * 2 - (options?.onSide ? EFF_WIDTH : 0)) * GLOBAL_SCALE } });
|
||||
|
||||
// limit the text rendering, required for scrolling later on
|
||||
const maskPointOrigin = {
|
||||
x: (options?.x || 0),
|
||||
y: (options?.y || 0),
|
||||
};
|
||||
if (maskPointOrigin.x < 0) {
|
||||
maskPointOrigin.x += this.scene.game.canvas.width / GLOBAL_SCALE;
|
||||
}
|
||||
if (maskPointOrigin.y < 0) {
|
||||
maskPointOrigin.y += this.scene.game.canvas.height / GLOBAL_SCALE;
|
||||
}
|
||||
|
||||
const moveDescriptionTextMaskRect = this.scene.make.graphics();
|
||||
moveDescriptionTextMaskRect.fillStyle(0xFF0000);
|
||||
moveDescriptionTextMaskRect.fillRect(
|
||||
maskPointOrigin.x + ((options?.onSide && !options?.right ? EFF_WIDTH : 0) + BORDER) * scale, maskPointOrigin.y + ((options?.top ? EFF_HEIGHT : 0) + BORDER - 2) * scale,
|
||||
width - ((options?.onSide ? EFF_WIDTH : 0) - BORDER * 2) * scale, (DESC_HEIGHT - (BORDER - 2) * 2) * scale);
|
||||
moveDescriptionTextMaskRect.setScale(6);
|
||||
const moveDescriptionTextMask = this.createGeometryMask(moveDescriptionTextMaskRect);
|
||||
|
||||
this.add(this.desc);
|
||||
this.desc.setMask(moveDescriptionTextMask);
|
||||
|
||||
// prepare the effect box
|
||||
this.val = new Phaser.GameObjects.Container(scene, options?.right ? width - EFF_WIDTH : 0, options?.top || options?.onSide ? 0 : DESC_HEIGHT);
|
||||
this.add(this.val);
|
||||
|
||||
const valuesBg = addWindow(scene, 0, 0, EFF_WIDTH, EFF_HEIGHT);
|
||||
valuesBg.setOrigin(0, 0);
|
||||
this.val.add(valuesBg);
|
||||
|
||||
this.typ = this.scene.add.sprite(25, EFF_HEIGHT - 35,`types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}` , "unknown");
|
||||
this.typ.setScale(0.8);
|
||||
this.val.add(this.typ);
|
||||
|
||||
this.cat = this.scene.add.sprite(57, EFF_HEIGHT - 35, "categories", "physical");
|
||||
this.val.add(this.cat);
|
||||
|
||||
const ppTxt = addTextObject(scene, 12, EFF_HEIGHT - 25, "PP", TextStyle.MOVE_INFO_CONTENT);
|
||||
ppTxt.setOrigin(0.0, 0.5);
|
||||
ppTxt.setText(i18next.t("fightUiHandler:pp"));
|
||||
this.val.add(ppTxt);
|
||||
|
||||
this.pp = addTextObject(scene, 70, EFF_HEIGHT - 25, "--", TextStyle.MOVE_INFO_CONTENT);
|
||||
this.pp.setOrigin(1, 0.5);
|
||||
this.val.add(this.pp);
|
||||
|
||||
const powTxt = addTextObject(scene, 12, EFF_HEIGHT - 17, "POWER", TextStyle.MOVE_INFO_CONTENT);
|
||||
powTxt.setOrigin(0.0, 0.5);
|
||||
powTxt.setText(i18next.t("fightUiHandler:power"));
|
||||
this.val.add(powTxt);
|
||||
|
||||
this.pow = addTextObject(scene, 70, EFF_HEIGHT - 17, "---", TextStyle.MOVE_INFO_CONTENT);
|
||||
this.pow.setOrigin(1, 0.5);
|
||||
this.val.add(this.pow);
|
||||
|
||||
const accTxt = addTextObject(scene, 12, EFF_HEIGHT - 9, "ACC", TextStyle.MOVE_INFO_CONTENT);
|
||||
accTxt.setOrigin(0.0, 0.5);
|
||||
accTxt.setText(i18next.t("fightUiHandler:accuracy"));
|
||||
this.val.add(accTxt);
|
||||
|
||||
this.acc = addTextObject(scene, 70, EFF_HEIGHT - 9, "---", TextStyle.MOVE_INFO_CONTENT);
|
||||
this.acc.setOrigin(1, 0.5);
|
||||
this.val.add(this.acc);
|
||||
|
||||
// hide this component for now
|
||||
this.setVisible(false);
|
||||
}
|
||||
|
||||
// show this component with infos for the specific move
|
||||
show(move : Move):boolean {
|
||||
if (!(this.scene as BattleScene).enableMoveInfo) {
|
||||
return; // move infos have been disabled
|
||||
}
|
||||
this.move = move;
|
||||
this.pow.setText(move.power >= 0 ? move.power.toString() : "---");
|
||||
this.acc.setText(move.accuracy >= 0 ? move.accuracy.toString() : "---");
|
||||
this.pp.setText(move.pp >= 0 ? move.pp.toString() : "---");
|
||||
this.typ.setTexture(`types${Utils.verifyLang(i18next.language) ? `_${i18next.language}` : ""}`, Type[move.type].toLowerCase());
|
||||
this.cat.setFrame(MoveCategory[move.category].toLowerCase());
|
||||
|
||||
this.desc.setText(move?.effect || "");
|
||||
|
||||
// stop previous scrolling effects
|
||||
if (this.descScroll) {
|
||||
this.descScroll.remove();
|
||||
this.descScroll = null;
|
||||
}
|
||||
|
||||
// determine if we need to add new scrolling effects
|
||||
const moveDescriptionLineCount = Math.floor(this.desc.displayHeight * (96 / 72) / 14.83);
|
||||
if (moveDescriptionLineCount > 3) {
|
||||
// generate scrolling effects
|
||||
this.descScroll = this.scene.tweens.add({
|
||||
targets: this.desc,
|
||||
delay: Utils.fixedInt(2000),
|
||||
loop: -1,
|
||||
hold: Utils.fixedInt(2000),
|
||||
duration: Utils.fixedInt((moveDescriptionLineCount - 3) * 2000),
|
||||
y: `-=${14.83 * (72 / 96) * (moveDescriptionLineCount - 3)}`
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.options.delayVisibility) {
|
||||
this.setVisible(true);
|
||||
}
|
||||
this.active = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.setVisible(false);
|
||||
this.active = false;
|
||||
}
|
||||
|
||||
toggleInfo(force?: boolean): void {
|
||||
this.setVisible(force ?? !this.visible);
|
||||
}
|
||||
|
||||
isActive(): boolean {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
// width of this element
|
||||
static getWidth(scale:number, scene: BattleScene):number {
|
||||
return scene.game.canvas.width / GLOBAL_SCALE / 2;
|
||||
}
|
||||
|
||||
// height of this element
|
||||
static getHeight(scale:number, onSide?: boolean):number {
|
||||
return (onSide ? Math.max(EFF_HEIGHT, DESC_HEIGHT) : (EFF_HEIGHT + DESC_HEIGHT)) * scale;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ import { addWindow } from "./ui-theme";
|
|||
import { SpeciesFormChangeItemTrigger } from "../data/pokemon-forms";
|
||||
import { getVariantTint } from "#app/data/variant";
|
||||
import {Button} from "../enums/buttons";
|
||||
import MoveInfoOverlay from "./move-info-overlay";
|
||||
|
||||
const defaultMessage = "Choose a Pokémon.";
|
||||
|
||||
|
@ -73,6 +74,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
private partySlots: PartySlot[];
|
||||
private partyCancelButton: PartyCancelButton;
|
||||
private partyMessageBox: Phaser.GameObjects.NineSlice;
|
||||
private moveInfoOverlay: MoveInfoOverlay;
|
||||
|
||||
private optionsMode: boolean;
|
||||
private optionsScroll: boolean;
|
||||
|
@ -179,6 +181,17 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
this.iconAnimHandler = new PokemonIconAnimHandler();
|
||||
this.iconAnimHandler.setup(this.scene);
|
||||
|
||||
// prepare move overlay. in case it appears to be too big, set the overlayScale to .5
|
||||
const overlayScale = 1;
|
||||
this.moveInfoOverlay = new MoveInfoOverlay(this.scene, {
|
||||
scale: overlayScale,
|
||||
top: true,
|
||||
x: 1,
|
||||
y: -MoveInfoOverlay.getHeight(overlayScale) - 1, //this.scene.game.canvas.height / 6 - MoveInfoOverlay.getHeight(overlayScale) - 29,
|
||||
width: this.scene.game.canvas.width / 12 - 30,
|
||||
});
|
||||
ui.add(this.moveInfoOverlay);
|
||||
|
||||
this.options = [];
|
||||
|
||||
this.partySlots = [];
|
||||
|
@ -191,6 +204,9 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
|
||||
super.show(args);
|
||||
|
||||
// reset the infoOverlay
|
||||
this.moveInfoOverlay.clear();
|
||||
|
||||
this.partyUiMode = args[0] as PartyUiMode;
|
||||
|
||||
this.fieldIndex = args.length > 1 ? args[1] as integer : -1;
|
||||
|
@ -244,6 +260,8 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
ui.playSelect();
|
||||
return true;
|
||||
} else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER && option !== PartyOption.CANCEL) {
|
||||
// clear overlay on cancel
|
||||
this.moveInfoOverlay.clear();
|
||||
const filterResult = (this.selectFilter as PokemonSelectFilter)(pokemon);
|
||||
if (filterResult === null) {
|
||||
this.selectCallback(this.cursor, option);
|
||||
|
@ -408,6 +426,19 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
success = this.setCursor(this.optionsCursor < this.options.length - 1 ? this.optionsCursor + 1 : 0); /** Move cursor */
|
||||
break;
|
||||
}
|
||||
|
||||
// show move description
|
||||
if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER) {
|
||||
const option = this.options[this.optionsCursor];
|
||||
const pokemon = this.scene.getParty()[this.cursor];
|
||||
const move = allMoves[pokemon.getLearnableLevelMoves()[option]];
|
||||
if (move) {
|
||||
this.moveInfoOverlay.show(move);
|
||||
} else {
|
||||
// or hide the overlay, in case it's the cancel button
|
||||
this.moveInfoOverlay.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (button === Button.ACTION) {
|
||||
|
@ -625,6 +656,11 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
? pokemon.getLearnableLevelMoves()
|
||||
: null;
|
||||
|
||||
if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER && learnableLevelMoves?.length) {
|
||||
// show the move overlay with info for the first move
|
||||
this.moveInfoOverlay.show(allMoves[learnableLevelMoves[0]]);
|
||||
}
|
||||
|
||||
const itemModifiers = this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER
|
||||
? this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
||||
&& (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === pokemon.id) as PokemonHeldItemModifier[]
|
||||
|
@ -874,6 +910,8 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
}
|
||||
|
||||
clearOptions() {
|
||||
// hide the overlay
|
||||
this.moveInfoOverlay.clear();
|
||||
this.optionsMode = false;
|
||||
this.optionsScroll = false;
|
||||
this.optionsScrollCursor = 0;
|
||||
|
@ -895,6 +933,8 @@ export default class PartyUiHandler extends MessageUiHandler {
|
|||
|
||||
clear() {
|
||||
super.clear();
|
||||
// hide the overlay
|
||||
this.moveInfoOverlay.clear();
|
||||
this.partyContainer.setVisible(false);
|
||||
this.clearPartySlots();
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import { StatsContainer } from "./stats-container";
|
|||
import { TextStyle, addBBCodeTextObject, addTextObject } from "./text";
|
||||
import { Mode } from "./ui";
|
||||
import { addWindow } from "./ui-theme";
|
||||
import MoveInfoOverlay from "./move-info-overlay";
|
||||
|
||||
export type StarterSelectCallback = (starters: Starter[]) => void;
|
||||
|
||||
|
@ -192,6 +193,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
private starterSelectMessageBoxContainer: Phaser.GameObjects.Container;
|
||||
private statsContainer: StatsContainer;
|
||||
private pokemonFormText: Phaser.GameObjects.Text;
|
||||
private moveInfoOverlay : MoveInfoOverlay;
|
||||
|
||||
private genMode: boolean;
|
||||
private statsMode: boolean;
|
||||
|
@ -661,6 +663,15 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
this.message.setOrigin(0, 0);
|
||||
this.starterSelectMessageBoxContainer.add(this.message);
|
||||
|
||||
const overlayScale = 1; // scale for the move info. "2/3" might be another good option...
|
||||
this.moveInfoOverlay = new MoveInfoOverlay(this.scene, {
|
||||
scale: overlayScale,
|
||||
top: true,
|
||||
x: 1,
|
||||
y: this.scene.game.canvas.height / 6 - MoveInfoOverlay.getHeight(overlayScale) - 29,
|
||||
});
|
||||
this.starterSelectContainer.add(this.moveInfoOverlay);
|
||||
|
||||
const date = new Date();
|
||||
date.setUTCHours(0, 0, 0, 0);
|
||||
|
||||
|
@ -1058,6 +1069,8 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
const showSwapOptions = (moveset: StarterMoveset) => {
|
||||
ui.setMode(Mode.STARTER_SELECT).then(() => {
|
||||
ui.showText(i18next.t("starterSelectUiHandler:selectMoveSwapOut"), null, () => {
|
||||
this.moveInfoOverlay.show(allMoves[moveset[0]]);
|
||||
|
||||
ui.setModeWithoutClear(Mode.OPTION_SELECT, {
|
||||
options: moveset.map((m: Moves, i: number) => {
|
||||
const option: OptionSelectItem = {
|
||||
|
@ -1065,8 +1078,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
handler: () => {
|
||||
ui.setMode(Mode.STARTER_SELECT).then(() => {
|
||||
ui.showText(`${i18next.t("starterSelectUiHandler:selectMoveSwapWith")} ${allMoves[m].name}.`, null, () => {
|
||||
const possibleMoves = this.speciesStarterMoves.filter((sm: Moves) => sm !== m);
|
||||
this.moveInfoOverlay.show(allMoves[possibleMoves[0]]);
|
||||
|
||||
ui.setModeWithoutClear(Mode.OPTION_SELECT, {
|
||||
options: this.speciesStarterMoves.filter((sm: Moves) => sm !== m).map(sm => {
|
||||
options: possibleMoves.map(sm => {
|
||||
// make an option for each available starter move
|
||||
const option = {
|
||||
label: allMoves[sm].name,
|
||||
|
@ -1074,7 +1090,10 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
this.switchMoveHandler(i, sm, m);
|
||||
showSwapOptions(this.starterMoveset);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
onHover: () => {
|
||||
this.moveInfoOverlay.show(allMoves[sm]);
|
||||
},
|
||||
};
|
||||
return option;
|
||||
}).concat({
|
||||
|
@ -1082,25 +1101,37 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
|||
handler: () => {
|
||||
showSwapOptions(this.starterMoveset);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
onHover: () => {
|
||||
this.moveInfoOverlay.clear();
|
||||
},
|
||||
}),
|
||||
supportHover: true,
|
||||
maxOptions: 8,
|
||||
yOffset: 19
|
||||
});
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
},
|
||||
onHover: () => {
|
||||
this.moveInfoOverlay.show(allMoves[m]);
|
||||
},
|
||||
};
|
||||
return option;
|
||||
}).concat({
|
||||
label: i18next.t("menu:cancel"),
|
||||
handler: () => {
|
||||
this.moveInfoOverlay.clear();
|
||||
this.clearText();
|
||||
ui.setMode(Mode.STARTER_SELECT);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
onHover: () => {
|
||||
this.moveInfoOverlay.clear();
|
||||
},
|
||||
}),
|
||||
supportHover: true,
|
||||
maxOptions: 8,
|
||||
yOffset: 19
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue