2024-02-22 04:57:49 +00:00
|
|
|
import { CommandPhase } from "../phases";
|
2023-04-11 05:24:55 +01:00
|
|
|
import BattleScene, { Button } from "../battle-scene";
|
2024-03-01 01:08:50 +00:00
|
|
|
import { PlayerPokemon, PokemonMove } from "../field/pokemon";
|
2023-04-20 20:46:05 +01:00
|
|
|
import { addTextObject, TextStyle } from "./text";
|
2023-03-28 19:54:52 +01:00
|
|
|
import { Command } from "./command-ui-handler";
|
|
|
|
import MessageUiHandler from "./message-ui-handler";
|
2023-04-06 03:22:03 +01:00
|
|
|
import { Mode } from "./ui";
|
2023-04-11 06:31:18 +01:00
|
|
|
import * as Utils from "../utils";
|
2024-01-10 04:34:43 +00:00
|
|
|
import { PokemonFormChangeItemModifier, PokemonHeldItemModifier, SwitchEffectTransferModifier } from "../modifier/modifier";
|
2024-01-13 17:24:24 +00:00
|
|
|
import { allMoves } from "../data/move";
|
|
|
|
import { Moves } from "../data/enums/moves";
|
2023-07-05 05:29:22 +01:00
|
|
|
import { getGenderColor, getGenderSymbol } from "../data/gender";
|
|
|
|
import { StatusEffect } from "../data/status-effect";
|
2024-03-01 01:08:50 +00:00
|
|
|
import PokemonIconAnimHandler, { PokemonIconAnimMode } from "./pokemon-icon-anim-handler";
|
2023-12-14 17:55:11 +00:00
|
|
|
import { pokemonEvolutions } from "../data/pokemon-evolutions";
|
2023-12-21 03:22:15 +00:00
|
|
|
import { addWindow } from "./window";
|
2024-01-10 04:34:43 +00:00
|
|
|
import { SpeciesFormChangeItemTrigger } from "../data/pokemon-forms";
|
2023-03-28 19:54:52 +01:00
|
|
|
|
|
|
|
const defaultMessage = 'Choose a Pokémon.';
|
|
|
|
|
2023-04-06 03:22:03 +01:00
|
|
|
export enum PartyUiMode {
|
|
|
|
SWITCH,
|
2023-04-06 05:15:33 +01:00
|
|
|
FAINT_SWITCH,
|
|
|
|
POST_BATTLE_SWITCH,
|
2023-04-11 06:31:18 +01:00
|
|
|
MODIFIER,
|
2023-04-11 16:04:39 +01:00
|
|
|
MOVE_MODIFIER,
|
2023-07-05 04:11:31 +01:00
|
|
|
TM_MODIFIER,
|
2023-11-08 22:30:07 +00:00
|
|
|
REMEMBER_MOVE_MODIFIER,
|
2023-04-21 19:05:16 +01:00
|
|
|
MODIFIER_TRANSFER,
|
2023-11-04 04:32:12 +00:00
|
|
|
SPLICE,
|
2023-04-11 06:31:18 +01:00
|
|
|
RELEASE
|
2023-04-06 03:22:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export enum PartyOption {
|
2023-04-21 19:05:16 +01:00
|
|
|
CANCEL = -1,
|
2023-04-06 03:22:03 +01:00
|
|
|
SEND_OUT,
|
2023-04-29 00:26:41 +01:00
|
|
|
PASS_BATON,
|
2023-04-06 03:22:03 +01:00
|
|
|
APPLY,
|
2023-07-05 04:11:31 +01:00
|
|
|
TEACH,
|
2023-04-21 19:05:16 +01:00
|
|
|
TRANSFER,
|
2023-11-04 04:32:12 +00:00
|
|
|
SPLICE,
|
2023-04-06 03:22:03 +01:00
|
|
|
SUMMARY,
|
2024-01-10 04:34:43 +00:00
|
|
|
UNPAUSE_EVOLUTION,
|
2023-04-11 06:31:18 +01:00
|
|
|
RELEASE,
|
2023-11-07 23:43:48 +00:00
|
|
|
SCROLL_UP = 1000,
|
|
|
|
SCROLL_DOWN = 1001,
|
2024-01-10 04:34:43 +00:00
|
|
|
FORM_CHANGE_ITEM = 2000,
|
|
|
|
MOVE_1 = 3000,
|
2023-04-11 16:04:39 +01:00
|
|
|
MOVE_2,
|
|
|
|
MOVE_3,
|
2023-04-21 19:05:16 +01:00
|
|
|
MOVE_4
|
2023-04-06 03:22:03 +01:00
|
|
|
}
|
|
|
|
|
2023-04-11 16:04:39 +01:00
|
|
|
export type PartySelectCallback = (cursor: integer, option: PartyOption) => void;
|
2023-04-21 19:05:16 +01:00
|
|
|
export type PartyModifierTransferSelectCallback = (fromCursor: integer, index: integer, toCursor?: integer) => void;
|
2023-11-04 04:32:12 +00:00
|
|
|
export type PartyModifierSpliceSelectCallback = (fromCursor: integer, toCursor?: integer) => void;
|
2023-04-11 16:04:39 +01:00
|
|
|
export type PokemonSelectFilter = (pokemon: PlayerPokemon) => string;
|
2023-04-21 19:05:16 +01:00
|
|
|
export type PokemonModifierTransferSelectFilter = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => string;
|
2023-04-11 16:04:39 +01:00
|
|
|
export type PokemonMoveSelectFilter = (pokemonMove: PokemonMove) => string;
|
|
|
|
|
2023-03-28 19:54:52 +01:00
|
|
|
export default class PartyUiHandler extends MessageUiHandler {
|
2023-04-06 03:22:03 +01:00
|
|
|
private partyUiMode: PartyUiMode;
|
2023-05-18 16:11:06 +01:00
|
|
|
private fieldIndex: integer;
|
2023-04-06 03:22:03 +01:00
|
|
|
|
2023-05-18 16:11:06 +01:00
|
|
|
private partyBg: Phaser.GameObjects.Image;
|
2023-03-28 19:54:52 +01:00
|
|
|
private partyContainer: Phaser.GameObjects.Container;
|
|
|
|
private partySlotsContainer: Phaser.GameObjects.Container;
|
|
|
|
private partySlots: PartySlot[];
|
|
|
|
private partyCancelButton: PartyCancelButton;
|
2023-12-21 03:22:15 +00:00
|
|
|
private partyMessageBox: Phaser.GameObjects.NineSlice;
|
2023-03-28 19:54:52 +01:00
|
|
|
|
2023-04-05 13:35:15 +01:00
|
|
|
private optionsMode: boolean;
|
2023-11-07 23:43:48 +00:00
|
|
|
private optionsScroll: boolean;
|
|
|
|
private optionsCursor: integer = 0;
|
|
|
|
private optionsScrollCursor: integer = 0;
|
|
|
|
private optionsScrollTotal: integer = 0;
|
2023-04-05 13:35:15 +01:00
|
|
|
private optionsContainer: Phaser.GameObjects.Container;
|
2024-01-10 04:34:43 +00:00
|
|
|
private optionsBg: Phaser.GameObjects.NineSlice;
|
2023-04-05 13:35:15 +01:00
|
|
|
private optionsCursorObj: Phaser.GameObjects.Image;
|
2023-04-06 03:22:03 +01:00
|
|
|
private options: integer[];
|
2023-04-21 19:05:16 +01:00
|
|
|
|
|
|
|
private transferMode: boolean;
|
|
|
|
private transferOptionCursor: integer;
|
|
|
|
private transferCursor: integer;
|
2023-04-05 13:35:15 +01:00
|
|
|
|
2023-03-28 19:54:52 +01:00
|
|
|
private lastCursor: integer = 0;
|
2023-04-21 19:05:16 +01:00
|
|
|
private selectCallback: PartySelectCallback | PartyModifierTransferSelectCallback;
|
|
|
|
private selectFilter: PokemonSelectFilter | PokemonModifierTransferSelectFilter;
|
2023-04-11 16:04:39 +01:00
|
|
|
private moveSelectFilter: PokemonMoveSelectFilter;
|
2023-07-05 04:11:31 +01:00
|
|
|
private tmMoveId: Moves;
|
2023-03-28 19:54:52 +01:00
|
|
|
|
2023-12-07 05:52:20 +00:00
|
|
|
private iconAnimHandler: PokemonIconAnimHandler;
|
|
|
|
|
2023-03-28 19:54:52 +01:00
|
|
|
private static FilterAll = (_pokemon: PlayerPokemon) => null;
|
|
|
|
|
|
|
|
public static FilterNonFainted = (pokemon: PlayerPokemon) => {
|
2023-05-18 16:11:06 +01:00
|
|
|
if (pokemon.isFainted())
|
2023-03-28 19:54:52 +01:00
|
|
|
return `${pokemon.name} has no energy\nleft to battle!`;
|
|
|
|
return null;
|
|
|
|
};
|
|
|
|
|
2023-04-11 16:04:39 +01:00
|
|
|
private static FilterAllMoves = (_pokemonMove: PokemonMove) => null;
|
|
|
|
|
2023-04-21 19:05:16 +01:00
|
|
|
public static FilterItemMaxStacks = (pokemon: PlayerPokemon, modifier: PokemonHeldItemModifier) => {
|
2024-02-17 05:40:03 +00:00
|
|
|
const matchingModifier = pokemon.scene.findModifier(m => m instanceof PokemonHeldItemModifier && m.pokemonId === pokemon.id && m.matchType(modifier)) as PokemonHeldItemModifier;
|
2023-12-09 05:33:29 +00:00
|
|
|
if (matchingModifier && matchingModifier.stackCount === matchingModifier.getMaxStackCount(pokemon.scene))
|
2023-04-21 19:05:16 +01:00
|
|
|
return `${pokemon.name} has too many\nof this item!`;
|
|
|
|
return null;
|
|
|
|
};
|
|
|
|
|
2023-03-28 19:54:52 +01:00
|
|
|
public static NoEffectMessage = 'It won\'t have any effect.';
|
|
|
|
|
|
|
|
constructor(scene: BattleScene) {
|
|
|
|
super(scene, Mode.PARTY);
|
|
|
|
}
|
|
|
|
|
|
|
|
setup() {
|
|
|
|
const ui = this.getUi();
|
|
|
|
|
|
|
|
const partyContainer = this.scene.add.container(0, 0);
|
|
|
|
partyContainer.setVisible(false);
|
|
|
|
ui.add(partyContainer);
|
|
|
|
|
|
|
|
this.partyContainer = partyContainer;
|
|
|
|
|
2023-05-18 16:11:06 +01:00
|
|
|
this.partyBg = this.scene.add.image(0, 0, 'party_bg');
|
|
|
|
partyContainer.add(this.partyBg);
|
2023-03-28 19:54:52 +01:00
|
|
|
|
2023-05-18 16:11:06 +01:00
|
|
|
this.partyBg.setOrigin(0, 1);
|
2023-03-28 19:54:52 +01:00
|
|
|
|
|
|
|
const partySlotsContainer = this.scene.add.container(0, 0);
|
|
|
|
partyContainer.add(partySlotsContainer);
|
|
|
|
|
|
|
|
this.partySlotsContainer = partySlotsContainer;
|
|
|
|
|
|
|
|
const partyMessageBoxContainer = this.scene.add.container(0, -32);
|
|
|
|
partyContainer.add(partyMessageBoxContainer);
|
|
|
|
|
2023-12-21 03:22:15 +00:00
|
|
|
const partyMessageBox = addWindow(this.scene, 1, 31, 262, 30);
|
2023-03-28 19:54:52 +01:00
|
|
|
partyMessageBox.setOrigin(0, 1);
|
|
|
|
partyMessageBoxContainer.add(partyMessageBox);
|
|
|
|
|
|
|
|
this.partyMessageBox = partyMessageBox;
|
|
|
|
|
|
|
|
const partyMessageText = addTextObject(this.scene, 8, 10, defaultMessage, TextStyle.WINDOW, { maxLines: 2 });
|
|
|
|
|
|
|
|
partyMessageText.setOrigin(0, 0);
|
|
|
|
partyMessageBoxContainer.add(partyMessageText);
|
|
|
|
|
|
|
|
this.message = partyMessageText;
|
|
|
|
|
|
|
|
const partyCancelButton = new PartyCancelButton(this.scene, 291, -16);
|
|
|
|
partyContainer.add(partyCancelButton);
|
|
|
|
|
|
|
|
this.partyCancelButton = partyCancelButton;
|
|
|
|
|
2023-04-05 13:35:15 +01:00
|
|
|
this.optionsContainer = this.scene.add.container((this.scene.game.canvas.width / 6) - 1, -1);
|
|
|
|
partyContainer.add(this.optionsContainer);
|
|
|
|
|
2023-12-07 05:52:20 +00:00
|
|
|
this.iconAnimHandler = new PokemonIconAnimHandler();
|
|
|
|
this.iconAnimHandler.setup(this.scene);
|
|
|
|
|
2023-04-06 03:22:03 +01:00
|
|
|
this.options = [];
|
|
|
|
|
2023-03-28 19:54:52 +01:00
|
|
|
this.partySlots = [];
|
|
|
|
}
|
|
|
|
|
2023-12-30 23:41:25 +00:00
|
|
|
show(args: any[]): boolean {
|
2023-04-06 15:05:12 +01:00
|
|
|
if (!args.length || this.active)
|
2023-12-30 23:41:25 +00:00
|
|
|
return false;
|
2023-04-06 03:22:03 +01:00
|
|
|
|
2023-03-28 19:54:52 +01:00
|
|
|
super.show(args);
|
|
|
|
|
2023-04-06 03:22:03 +01:00
|
|
|
this.partyUiMode = args[0] as PartyUiMode;
|
|
|
|
|
2023-05-18 16:11:06 +01:00
|
|
|
this.fieldIndex = args.length > 1 ? args[1] as integer : -1;
|
|
|
|
|
2023-10-25 14:12:39 +01:00
|
|
|
this.selectCallback = args.length > 2 && args[2] instanceof Function ? args[2] : undefined;
|
2023-05-18 16:11:06 +01:00
|
|
|
this.selectFilter = args.length > 3 && args[3] instanceof Function
|
|
|
|
? args[3] as PokemonSelectFilter
|
2023-03-28 19:54:52 +01:00
|
|
|
: PartyUiHandler.FilterAll;
|
2023-05-18 16:11:06 +01:00
|
|
|
this.moveSelectFilter = args.length > 4 && args[4] instanceof Function
|
|
|
|
? args[4] as PokemonMoveSelectFilter
|
2023-04-11 16:04:39 +01:00
|
|
|
: PartyUiHandler.FilterAllMoves;
|
2023-07-05 04:11:31 +01:00
|
|
|
this.tmMoveId = args.length > 5 && args[5] ? args[5] : Moves.NONE;
|
|
|
|
|
|
|
|
this.partyContainer.setVisible(true);
|
|
|
|
this.partyBg.setTexture(`party_bg${this.scene.currentBattle.double ? '_double' : ''}`);
|
|
|
|
this.populatePartySlots();
|
|
|
|
this.setCursor(this.cursor < 6 ? this.cursor : 0);
|
2023-12-30 23:41:25 +00:00
|
|
|
|
|
|
|
return true;
|
2023-03-28 19:54:52 +01:00
|
|
|
}
|
|
|
|
|
2023-11-12 05:31:40 +00:00
|
|
|
processInput(button: Button): boolean {
|
2023-03-28 19:54:52 +01:00
|
|
|
const ui = this.getUi();
|
|
|
|
|
|
|
|
if (this.pendingPrompt)
|
2023-11-12 05:31:40 +00:00
|
|
|
return false;
|
2023-03-28 19:54:52 +01:00
|
|
|
|
|
|
|
if (this.awaitingActionInput) {
|
2023-11-12 05:31:40 +00:00
|
|
|
if ((button === Button.ACTION || button === Button.CANCEL) && this.onActionInput) {
|
|
|
|
ui.playSelect();
|
|
|
|
const originalOnActionInput = this.onActionInput;
|
|
|
|
this.onActionInput = null;
|
|
|
|
originalOnActionInput();
|
|
|
|
this.awaitingActionInput = false;
|
|
|
|
return true;
|
2023-03-28 19:54:52 +01:00
|
|
|
}
|
2023-11-12 05:31:40 +00:00
|
|
|
return false;
|
2023-03-28 19:54:52 +01:00
|
|
|
}
|
|
|
|
|
2023-04-05 13:35:15 +01:00
|
|
|
let success = false;
|
|
|
|
|
|
|
|
if (this.optionsMode) {
|
2023-04-11 05:24:55 +01:00
|
|
|
if (button === Button.ACTION) {
|
2023-04-06 03:22:03 +01:00
|
|
|
const option = this.options[this.optionsCursor];
|
2023-04-11 06:31:18 +01:00
|
|
|
const pokemon = this.scene.getParty()[this.cursor];
|
2023-04-21 19:05:16 +01:00
|
|
|
if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER && !this.transferMode && option !== PartyOption.CANCEL) {
|
|
|
|
this.startTransfer();
|
|
|
|
this.clearOptions();
|
|
|
|
ui.playSelect();
|
2023-11-12 05:31:40 +00:00
|
|
|
return true;
|
2023-11-08 22:30:07 +00:00
|
|
|
} else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER && option !== PartyOption.CANCEL) {
|
|
|
|
let filterResult = (this.selectFilter as PokemonSelectFilter)(pokemon);
|
|
|
|
if (filterResult === null) {
|
|
|
|
this.selectCallback(this.cursor, option);
|
|
|
|
this.clearOptions();
|
|
|
|
} else {
|
|
|
|
this.clearOptions();
|
|
|
|
this.showText(filterResult as string, null, () => this.showText(null, 0), null, true);
|
|
|
|
}
|
|
|
|
ui.playSelect();
|
2023-11-12 05:31:40 +00:00
|
|
|
return true;
|
2024-01-10 04:34:43 +00:00
|
|
|
} else if ((option !== PartyOption.SUMMARY && option !== PartyOption.UNPAUSE_EVOLUTION && option !== PartyOption.RELEASE && option !== PartyOption.CANCEL)
|
2023-04-11 16:04:39 +01:00
|
|
|
|| (option === PartyOption.RELEASE && this.partyUiMode === PartyUiMode.RELEASE)) {
|
2023-04-21 19:05:16 +01:00
|
|
|
let filterResult: string;
|
2023-11-04 04:32:12 +00:00
|
|
|
if (option !== PartyOption.TRANSFER && option !== PartyOption.SPLICE) {
|
2023-04-21 19:05:16 +01:00
|
|
|
filterResult = (this.selectFilter as PokemonSelectFilter)(pokemon);
|
2023-11-10 21:41:02 +00:00
|
|
|
if (filterResult === null && this.partyUiMode === PartyUiMode.MOVE_MODIFIER)
|
2023-04-21 19:05:16 +01:00
|
|
|
filterResult = this.moveSelectFilter(pokemon.moveset[this.optionsCursor]);
|
|
|
|
} else {
|
2023-11-07 23:43:48 +00:00
|
|
|
const transferPokemon = this.scene.getParty()[this.transferCursor];
|
2023-04-21 19:05:16 +01:00
|
|
|
const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
2023-11-07 23:43:48 +00:00
|
|
|
&& (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === transferPokemon.id) as PokemonHeldItemModifier[];
|
2023-04-21 19:05:16 +01:00
|
|
|
filterResult = (this.selectFilter as PokemonModifierTransferSelectFilter)(pokemon, itemModifiers[this.transferOptionCursor]);
|
|
|
|
}
|
2023-04-05 13:35:15 +01:00
|
|
|
if (filterResult === null) {
|
2023-11-04 04:32:12 +00:00
|
|
|
if (this.partyUiMode !== PartyUiMode.SPLICE)
|
|
|
|
this.clearOptions();
|
2023-04-05 13:35:15 +01:00
|
|
|
if (this.selectCallback) {
|
2023-04-21 19:05:16 +01:00
|
|
|
if (option === PartyOption.TRANSFER) {
|
|
|
|
(this.selectCallback as PartyModifierTransferSelectCallback)(this.transferCursor, this.transferOptionCursor, this.cursor);
|
|
|
|
this.clearTransfer();
|
2023-11-04 04:32:12 +00:00
|
|
|
} else if (this.partyUiMode === PartyUiMode.SPLICE) {
|
|
|
|
if (option === PartyOption.SPLICE) {
|
|
|
|
(this.selectCallback as PartyModifierSpliceSelectCallback)(this.transferCursor, this.cursor);
|
|
|
|
this.clearTransfer();
|
|
|
|
} else
|
|
|
|
this.startTransfer();
|
|
|
|
this.clearOptions();
|
2023-04-21 19:05:16 +01:00
|
|
|
} else if (option === PartyOption.RELEASE)
|
2023-04-11 14:41:11 +01:00
|
|
|
this.doRelease(this.cursor);
|
|
|
|
else {
|
|
|
|
const selectCallback = this.selectCallback;
|
2023-04-11 06:31:18 +01:00
|
|
|
this.selectCallback = null;
|
2023-04-11 16:04:39 +01:00
|
|
|
selectCallback(this.cursor, option);
|
2023-04-11 06:31:18 +01:00
|
|
|
}
|
2024-01-10 04:34:43 +00:00
|
|
|
} else {
|
|
|
|
if (option >= PartyOption.FORM_CHANGE_ITEM && this.scene.getCurrentPhase() instanceof CommandPhase) {
|
|
|
|
switch (this.partyUiMode) {
|
|
|
|
case PartyUiMode.SWITCH:
|
|
|
|
case PartyUiMode.FAINT_SWITCH:
|
|
|
|
case PartyUiMode.POST_BATTLE_SWITCH:
|
|
|
|
let formChangeItemModifiers = this.scene.findModifiers(m => m instanceof PokemonFormChangeItemModifier && m.pokemonId === pokemon.id) as PokemonFormChangeItemModifier[];
|
|
|
|
if (formChangeItemModifiers.find(m => m.active))
|
|
|
|
formChangeItemModifiers = formChangeItemModifiers.filter(m => m.active);
|
|
|
|
const modifier = formChangeItemModifiers[option - PartyOption.FORM_CHANGE_ITEM];
|
|
|
|
modifier.active = !modifier.active;
|
|
|
|
this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeItemTrigger, false, true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (this.cursor)
|
|
|
|
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.POKEMON, this.cursor, option === PartyOption.PASS_BATON);
|
|
|
|
}
|
2023-07-05 04:11:31 +01:00
|
|
|
if (this.partyUiMode !== PartyUiMode.MODIFIER && this.partyUiMode !== PartyUiMode.TM_MODIFIER && this.partyUiMode !== PartyUiMode.MOVE_MODIFIER)
|
2023-04-10 00:15:21 +01:00
|
|
|
ui.playSelect();
|
2023-11-12 05:31:40 +00:00
|
|
|
return true;
|
2023-04-05 13:35:15 +01:00
|
|
|
} else {
|
|
|
|
this.clearOptions();
|
2023-04-23 03:14:53 +01:00
|
|
|
this.showText(filterResult as string, null, () => this.showText(null, 0), null, true);
|
2023-04-05 13:35:15 +01:00
|
|
|
}
|
2023-04-06 03:22:03 +01:00
|
|
|
} else if (option === PartyOption.SUMMARY) {
|
2023-03-28 19:54:52 +01:00
|
|
|
ui.playSelect();
|
2023-04-11 06:31:18 +01:00
|
|
|
ui.setModeWithoutClear(Mode.SUMMARY, pokemon).then(() => this.clearOptions());
|
2023-11-12 05:31:40 +00:00
|
|
|
return true;
|
2024-01-10 04:34:43 +00:00
|
|
|
} else if (option === PartyOption.UNPAUSE_EVOLUTION) {
|
2023-12-14 17:55:11 +00:00
|
|
|
this.clearOptions();
|
|
|
|
ui.playSelect();
|
|
|
|
pokemon.pauseEvolutions = false;
|
|
|
|
this.showText(`Evolutions have been unpaused for ${pokemon.name}.`, null, () => this.showText(null, 0), null, true);
|
2023-04-11 14:41:11 +01:00
|
|
|
} else if (option === PartyOption.RELEASE) {
|
|
|
|
this.clearOptions();
|
|
|
|
ui.playSelect();
|
2023-05-18 16:11:06 +01:00
|
|
|
if (this.cursor >= this.scene.currentBattle.getBattlerCount()) {
|
2023-04-11 14:41:11 +01:00
|
|
|
this.showText(`Do you really want to release ${pokemon.name}?`, null, () => {
|
|
|
|
ui.setModeWithoutClear(Mode.CONFIRM, () => {
|
|
|
|
ui.setMode(Mode.PARTY);
|
|
|
|
this.doRelease(this.cursor);
|
|
|
|
}, () => {
|
|
|
|
ui.setMode(Mode.PARTY);
|
2023-04-23 03:14:53 +01:00
|
|
|
this.showText(null, 0);
|
2023-04-11 14:41:11 +01:00
|
|
|
});
|
|
|
|
});
|
|
|
|
} else
|
2023-10-18 23:01:15 +01:00
|
|
|
this.showText('You can\'t release a Pokémon that\'s in battle!', null, () => this.showText(null, 0), null, true);
|
2023-11-12 05:31:40 +00:00
|
|
|
return true;
|
2023-04-06 03:22:03 +01:00
|
|
|
} else if (option === PartyOption.CANCEL)
|
2023-11-12 05:31:40 +00:00
|
|
|
return this.processInput(Button.CANCEL);
|
2023-04-11 05:24:55 +01:00
|
|
|
} else if (button === Button.CANCEL) {
|
2023-04-05 13:35:15 +01:00
|
|
|
this.clearOptions();
|
|
|
|
ui.playSelect();
|
2023-11-12 05:31:40 +00:00
|
|
|
return true;
|
2023-11-08 22:30:07 +00:00
|
|
|
} else {
|
2023-04-11 05:24:55 +01:00
|
|
|
switch (button) {
|
|
|
|
case Button.UP:
|
2023-04-06 03:22:03 +01:00
|
|
|
success = this.setCursor(this.optionsCursor ? this.optionsCursor - 1 : this.options.length - 1);
|
2023-04-05 13:35:15 +01:00
|
|
|
break;
|
2023-04-11 05:24:55 +01:00
|
|
|
case Button.DOWN:
|
2023-04-06 03:22:03 +01:00
|
|
|
success = this.setCursor(this.optionsCursor < this.options.length - 1 ? this.optionsCursor + 1 : 0);
|
2023-04-05 13:35:15 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2023-04-11 05:24:55 +01:00
|
|
|
if (button === Button.ACTION) {
|
2023-04-05 13:35:15 +01:00
|
|
|
if (this.cursor < 6) {
|
|
|
|
this.showOptions();
|
2023-03-28 19:54:52 +01:00
|
|
|
ui.playSelect();
|
2023-04-06 05:15:33 +01:00
|
|
|
} else if (this.partyUiMode === PartyUiMode.FAINT_SWITCH)
|
2023-04-05 13:35:15 +01:00
|
|
|
ui.playError();
|
|
|
|
else
|
2023-11-12 05:31:40 +00:00
|
|
|
return this.processInput(Button.CANCEL);
|
|
|
|
return true;
|
2023-04-11 05:24:55 +01:00
|
|
|
} else if (button === Button.CANCEL) {
|
2023-11-04 04:32:12 +00:00
|
|
|
if ((this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER || this.partyUiMode === PartyUiMode.SPLICE) && this.transferMode) {
|
2023-04-21 19:05:16 +01:00
|
|
|
this.clearTransfer();
|
|
|
|
ui.playSelect();
|
|
|
|
} else if (this.partyUiMode !== PartyUiMode.FAINT_SWITCH) {
|
2023-04-05 13:35:15 +01:00
|
|
|
if (this.selectCallback) {
|
|
|
|
const selectCallback = this.selectCallback;
|
|
|
|
this.selectCallback = null;
|
2023-04-11 16:04:39 +01:00
|
|
|
selectCallback(6, PartyOption.CANCEL);
|
2023-04-05 13:35:15 +01:00
|
|
|
ui.playSelect();
|
|
|
|
} else {
|
2023-10-20 16:38:41 +01:00
|
|
|
ui.setMode(Mode.COMMAND, this.fieldIndex);
|
2023-04-05 13:35:15 +01:00
|
|
|
ui.playSelect();
|
|
|
|
}
|
2023-03-28 19:54:52 +01:00
|
|
|
}
|
2023-11-12 05:31:40 +00:00
|
|
|
|
|
|
|
return true;
|
2023-03-28 19:54:52 +01:00
|
|
|
}
|
|
|
|
|
2023-04-05 13:35:15 +01:00
|
|
|
const slotCount = this.partySlots.length;
|
|
|
|
|
2023-04-11 05:24:55 +01:00
|
|
|
switch (button) {
|
|
|
|
case Button.UP:
|
2023-04-05 13:35:15 +01:00
|
|
|
success = this.setCursor(this.cursor ? this.cursor < 6 ? this.cursor - 1 : slotCount - 1 : 6);
|
|
|
|
break;
|
2023-04-11 05:24:55 +01:00
|
|
|
case Button.DOWN:
|
2023-04-05 13:35:15 +01:00
|
|
|
success = this.setCursor(this.cursor < 6 ? this.cursor < slotCount - 1 ? this.cursor + 1 : 6 : 0);
|
|
|
|
break;
|
2023-04-11 05:24:55 +01:00
|
|
|
case Button.LEFT:
|
2023-05-18 16:11:06 +01:00
|
|
|
if (this.cursor >= this.scene.currentBattle.getBattlerCount() && this.cursor < 6)
|
2023-04-05 13:35:15 +01:00
|
|
|
success = this.setCursor(0);
|
|
|
|
break;
|
2023-04-11 05:24:55 +01:00
|
|
|
case Button.RIGHT:
|
2023-05-18 16:11:06 +01:00
|
|
|
const battlerCount = this.scene.currentBattle.getBattlerCount();
|
2024-01-10 04:34:43 +00:00
|
|
|
if (slotCount > battlerCount && this.cursor < battlerCount)
|
2023-05-18 16:11:06 +01:00
|
|
|
success = this.setCursor(this.lastCursor < 6 ? this.lastCursor || battlerCount : battlerCount);
|
2023-04-05 13:35:15 +01:00
|
|
|
break;
|
|
|
|
}
|
2023-03-28 19:54:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (success)
|
|
|
|
ui.playSelect();
|
2023-11-12 05:31:40 +00:00
|
|
|
|
|
|
|
return success;
|
2023-03-28 19:54:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
populatePartySlots() {
|
2023-04-14 23:21:33 +01:00
|
|
|
const party = this.scene.getParty();
|
2023-03-28 19:54:52 +01:00
|
|
|
|
|
|
|
if (this.cursor < 6 && this.cursor >= party.length)
|
|
|
|
this.cursor = party.length - 1;
|
|
|
|
else if (this.cursor === 6)
|
|
|
|
this.partyCancelButton.select();
|
|
|
|
|
|
|
|
for (let p in party) {
|
|
|
|
const slotIndex = parseInt(p);
|
2023-12-07 05:52:20 +00:00
|
|
|
const partySlot = new PartySlot(this.scene, slotIndex, party[p], this.iconAnimHandler, this.partyUiMode, this.tmMoveId);
|
2023-03-28 19:54:52 +01:00
|
|
|
this.scene.add.existing(partySlot);
|
|
|
|
this.partySlotsContainer.add(partySlot);
|
|
|
|
this.partySlots.push(partySlot);
|
|
|
|
if (this.cursor === slotIndex)
|
|
|
|
partySlot.select();
|
|
|
|
}
|
|
|
|
}
|
2023-04-05 13:35:15 +01:00
|
|
|
|
|
|
|
setCursor(cursor: integer): boolean {
|
|
|
|
let changed: boolean;
|
|
|
|
|
|
|
|
if (this.optionsMode) {
|
|
|
|
changed = this.optionsCursor !== cursor;
|
2023-11-07 23:43:48 +00:00
|
|
|
let isScroll = false;
|
|
|
|
if (changed && this.optionsScroll) {
|
|
|
|
if (Math.abs(cursor - this.optionsCursor) === this.options.length - 1) {
|
|
|
|
this.optionsScrollCursor = cursor ? this.optionsScrollTotal - 8 : 0;
|
|
|
|
this.updateOptions();
|
|
|
|
} else {
|
|
|
|
const isDown = cursor && cursor > this.optionsCursor;
|
|
|
|
if (isDown) {
|
|
|
|
if (this.options[cursor] === PartyOption.SCROLL_DOWN) {
|
|
|
|
isScroll = true;
|
|
|
|
this.optionsScrollCursor++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!cursor && this.optionsScrollCursor) {
|
|
|
|
isScroll = true;
|
|
|
|
this.optionsScrollCursor--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isScroll && this.optionsScrollCursor === 1)
|
|
|
|
this.optionsScrollCursor += isDown ? 1 : -1;
|
|
|
|
}
|
|
|
|
}
|
2024-02-21 20:47:44 +00:00
|
|
|
if (isScroll)
|
2023-11-07 23:43:48 +00:00
|
|
|
this.updateOptions();
|
2024-02-21 20:47:44 +00:00
|
|
|
else
|
2023-11-07 23:43:48 +00:00
|
|
|
this.optionsCursor = cursor;
|
2023-04-05 13:35:15 +01:00
|
|
|
if (!this.optionsCursorObj) {
|
|
|
|
this.optionsCursorObj = this.scene.add.image(0, 0, 'cursor');
|
|
|
|
this.optionsCursorObj.setOrigin(0, 0);
|
|
|
|
this.optionsContainer.add(this.optionsCursorObj);
|
|
|
|
}
|
2024-01-10 04:34:43 +00:00
|
|
|
this.optionsCursorObj.setPosition(8 - this.optionsBg.displayWidth, -19 - (16 * ((this.options.length - 1) - this.optionsCursor)));
|
2023-04-05 13:35:15 +01:00
|
|
|
} else {
|
|
|
|
changed = this.cursor !== cursor;
|
|
|
|
if (changed) {
|
|
|
|
this.lastCursor = this.cursor;
|
|
|
|
this.cursor = cursor;
|
|
|
|
if (this.lastCursor < 6)
|
|
|
|
this.partySlots[this.lastCursor].deselect();
|
|
|
|
else if (this.lastCursor === 6)
|
|
|
|
this.partyCancelButton.deselect();
|
|
|
|
if (cursor < 6)
|
|
|
|
this.partySlots[cursor].select();
|
|
|
|
else if (cursor === 6)
|
|
|
|
this.partyCancelButton.select();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
2023-04-23 03:14:53 +01:00
|
|
|
showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer) {
|
|
|
|
if (text === null)
|
|
|
|
text = defaultMessage;
|
|
|
|
|
|
|
|
if (text?.indexOf('\n') === -1) {
|
2023-12-21 03:22:15 +00:00
|
|
|
this.partyMessageBox.setSize(262, 30);
|
2023-04-23 03:14:53 +01:00
|
|
|
this.message.setY(10);
|
|
|
|
} else {
|
2023-12-21 03:22:15 +00:00
|
|
|
this.partyMessageBox.setSize(262, 42);
|
2023-04-23 03:14:53 +01:00
|
|
|
this.message.setY(-5);
|
|
|
|
}
|
|
|
|
|
|
|
|
super.showText(text, delay, callback, callbackDelay, prompt, promptDelay);
|
|
|
|
}
|
|
|
|
|
2023-04-05 13:35:15 +01:00
|
|
|
showOptions() {
|
|
|
|
if (this.cursor === 6)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this.optionsMode = true;
|
|
|
|
|
2023-04-21 19:05:16 +01:00
|
|
|
let optionsMessage = 'Do what with this Pokémon?';
|
|
|
|
|
|
|
|
switch (this.partyUiMode) {
|
|
|
|
case PartyUiMode.MOVE_MODIFIER:
|
|
|
|
optionsMessage = 'Select a move.';
|
|
|
|
break;
|
|
|
|
case PartyUiMode.MODIFIER_TRANSFER:
|
|
|
|
if (!this.transferMode)
|
|
|
|
optionsMessage = 'Select a held item to transfer.';
|
|
|
|
break;
|
2023-11-04 04:32:12 +00:00
|
|
|
case PartyUiMode.SPLICE:
|
|
|
|
if (!this.transferMode)
|
|
|
|
optionsMessage = 'Select another Pokémon to splice.';
|
|
|
|
break;
|
2023-04-21 19:05:16 +01:00
|
|
|
}
|
|
|
|
|
2023-04-23 03:14:53 +01:00
|
|
|
this.showText(optionsMessage, 0);
|
2023-04-21 19:05:16 +01:00
|
|
|
|
2023-11-07 23:43:48 +00:00
|
|
|
this.updateOptions();
|
|
|
|
|
2024-01-10 04:34:43 +00:00
|
|
|
this.partyMessageBox.setSize(262 - Math.max(this.optionsBg.displayWidth - 56, 0), 30);
|
2023-12-21 03:22:15 +00:00
|
|
|
|
2023-11-07 23:43:48 +00:00
|
|
|
this.setCursor(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
updateOptions(): void {
|
2023-04-11 16:04:39 +01:00
|
|
|
const pokemon = this.scene.getParty()[this.cursor];
|
2023-04-06 03:22:03 +01:00
|
|
|
|
2023-11-08 22:30:07 +00:00
|
|
|
const learnableLevelMoves = this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER
|
|
|
|
? pokemon.getLearnableLevelMoves()
|
|
|
|
: null;
|
|
|
|
|
2023-04-21 19:05:16 +01:00
|
|
|
const itemModifiers = this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER
|
2023-06-01 00:54:57 +01:00
|
|
|
? this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier
|
|
|
|
&& (m as PokemonHeldItemModifier).getTransferrable(true) && (m as PokemonHeldItemModifier).pokemonId === pokemon.id) as PokemonHeldItemModifier[]
|
2023-04-21 19:05:16 +01:00
|
|
|
: null;
|
|
|
|
|
2023-11-07 23:43:48 +00:00
|
|
|
if (this.options.length) {
|
|
|
|
this.options.splice(0, this.options.length);
|
|
|
|
this.optionsContainer.removeAll(true);
|
|
|
|
this.eraseOptionsCursor();
|
|
|
|
}
|
|
|
|
|
2024-01-10 04:34:43 +00:00
|
|
|
let formChangeItemModifiers: PokemonFormChangeItemModifier[];
|
|
|
|
|
2023-11-08 22:30:07 +00:00
|
|
|
if (this.partyUiMode !== PartyUiMode.MOVE_MODIFIER && this.partyUiMode !== PartyUiMode.REMEMBER_MOVE_MODIFIER && (this.transferMode || this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER)) {
|
2023-04-11 16:04:39 +01:00
|
|
|
switch (this.partyUiMode) {
|
|
|
|
case PartyUiMode.SWITCH:
|
|
|
|
case PartyUiMode.FAINT_SWITCH:
|
|
|
|
case PartyUiMode.POST_BATTLE_SWITCH:
|
2023-05-18 16:11:06 +01:00
|
|
|
if (this.cursor >= this.scene.currentBattle.getBattlerCount()) {
|
2023-04-11 16:04:39 +01:00
|
|
|
this.options.push(PartyOption.SEND_OUT);
|
2023-04-29 00:26:41 +01:00
|
|
|
if (this.partyUiMode !== PartyUiMode.FAINT_SWITCH
|
2023-05-18 16:11:06 +01:00
|
|
|
&& this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier
|
|
|
|
&& (m as SwitchEffectTransferModifier).pokemonId === this.scene.getPlayerField()[this.fieldIndex].id))
|
2023-04-29 00:26:41 +01:00
|
|
|
this.options.push(PartyOption.PASS_BATON);
|
|
|
|
}
|
2024-01-10 04:34:43 +00:00
|
|
|
if (this.scene.getCurrentPhase() instanceof CommandPhase) {
|
|
|
|
formChangeItemModifiers = this.scene.findModifiers(m => m instanceof PokemonFormChangeItemModifier && m.pokemonId === pokemon.id) as PokemonFormChangeItemModifier[];
|
|
|
|
if (formChangeItemModifiers.find(m => m.active))
|
|
|
|
formChangeItemModifiers = formChangeItemModifiers.filter(m => m.active);
|
|
|
|
for (let i = 0; i < formChangeItemModifiers.length; i++)
|
|
|
|
this.options.push(PartyOption.FORM_CHANGE_ITEM + i);
|
|
|
|
}
|
2023-04-11 16:04:39 +01:00
|
|
|
break;
|
|
|
|
case PartyUiMode.MODIFIER:
|
|
|
|
this.options.push(PartyOption.APPLY);
|
|
|
|
break;
|
2023-07-05 04:11:31 +01:00
|
|
|
case PartyUiMode.TM_MODIFIER:
|
|
|
|
this.options.push(PartyOption.TEACH);
|
|
|
|
break;
|
2023-04-21 19:05:16 +01:00
|
|
|
case PartyUiMode.MODIFIER_TRANSFER:
|
|
|
|
this.options.push(PartyOption.TRANSFER);
|
|
|
|
break;
|
2023-11-04 04:32:12 +00:00
|
|
|
case PartyUiMode.SPLICE:
|
|
|
|
if (this.transferMode) {
|
|
|
|
if (this.cursor !== this.transferCursor)
|
|
|
|
this.options.push(PartyOption.SPLICE);
|
|
|
|
} else
|
|
|
|
this.options.push(PartyOption.APPLY);
|
|
|
|
break;
|
2023-04-11 16:04:39 +01:00
|
|
|
case PartyUiMode.RELEASE:
|
|
|
|
this.options.push(PartyOption.RELEASE);
|
|
|
|
break;
|
|
|
|
}
|
2023-04-11 14:41:11 +01:00
|
|
|
|
2023-04-11 16:04:39 +01:00
|
|
|
this.options.push(PartyOption.SUMMARY);
|
|
|
|
|
2023-12-14 17:55:11 +00:00
|
|
|
if (pokemon.pauseEvolutions && pokemonEvolutions.hasOwnProperty(pokemon.species.speciesId))
|
2024-01-10 04:34:43 +00:00
|
|
|
this.options.push(PartyOption.UNPAUSE_EVOLUTION);
|
2023-12-14 17:55:11 +00:00
|
|
|
|
2023-04-11 16:04:39 +01:00
|
|
|
if (this.partyUiMode === PartyUiMode.SWITCH)
|
|
|
|
this.options.push(PartyOption.RELEASE);
|
2023-04-21 19:05:16 +01:00
|
|
|
} else if (this.partyUiMode === PartyUiMode.MOVE_MODIFIER) {
|
2023-04-11 16:04:39 +01:00
|
|
|
for (let m = 0; m < pokemon.moveset.length; m++)
|
|
|
|
this.options.push(PartyOption.MOVE_1 + m);
|
2023-11-08 22:30:07 +00:00
|
|
|
} else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER) {
|
|
|
|
const learnableMoves = pokemon.getLearnableLevelMoves();
|
|
|
|
for (let m = 0; m < learnableMoves.length; m++)
|
|
|
|
this.options.push(m);
|
2023-04-21 19:05:16 +01:00
|
|
|
} else {
|
|
|
|
for (let im = 0; im < itemModifiers.length; im++)
|
|
|
|
this.options.push(im);
|
2023-04-11 16:04:39 +01:00
|
|
|
}
|
2023-04-11 14:41:11 +01:00
|
|
|
|
2023-11-07 23:43:48 +00:00
|
|
|
this.optionsScrollTotal = this.options.length;
|
|
|
|
let optionStartIndex = this.optionsScrollCursor;
|
|
|
|
let optionEndIndex = Math.min(this.optionsScrollTotal, optionStartIndex + (!optionStartIndex || this.optionsScrollCursor + 8 >= this.optionsScrollTotal ? 8 : 7));
|
|
|
|
|
|
|
|
this.optionsScroll = this.optionsScrollTotal > 9;
|
|
|
|
|
|
|
|
if (this.optionsScroll) {
|
|
|
|
this.options.splice(optionEndIndex, this.optionsScrollTotal);
|
|
|
|
this.options.splice(0, optionStartIndex);
|
|
|
|
if (optionStartIndex)
|
|
|
|
this.options.unshift(PartyOption.SCROLL_UP);
|
|
|
|
if (optionEndIndex < this.optionsScrollTotal)
|
|
|
|
this.options.push(PartyOption.SCROLL_DOWN);
|
|
|
|
}
|
|
|
|
|
2023-04-11 14:41:11 +01:00
|
|
|
this.options.push(PartyOption.CANCEL);
|
2023-04-05 13:35:15 +01:00
|
|
|
|
2024-01-10 04:34:43 +00:00
|
|
|
this.optionsBg = addWindow(this.scene, 0, 0, 0, 16 * this.options.length + 13);
|
|
|
|
this.optionsBg.setOrigin(1, 1);
|
2023-11-07 23:43:48 +00:00
|
|
|
|
2024-01-10 04:34:43 +00:00
|
|
|
this.optionsContainer.add(this.optionsBg);
|
2023-11-07 23:43:48 +00:00
|
|
|
|
|
|
|
optionStartIndex = 0;
|
|
|
|
optionEndIndex = this.options.length;
|
|
|
|
|
2024-01-10 04:34:43 +00:00
|
|
|
let widestOptionWidth = 0;
|
|
|
|
let optionTexts: Phaser.GameObjects.Text[] = [];
|
|
|
|
|
2023-11-07 23:43:48 +00:00
|
|
|
for (let o = optionStartIndex; o < optionEndIndex; o++) {
|
2023-04-11 16:04:39 +01:00
|
|
|
const option = this.options[this.options.length - (o + 1)];
|
2023-11-09 03:30:22 +00:00
|
|
|
let altText = false;
|
2023-04-11 16:04:39 +01:00
|
|
|
let optionName: string;
|
2023-11-08 22:30:07 +00:00
|
|
|
if ((this.partyUiMode !== PartyUiMode.REMEMBER_MOVE_MODIFIER && (this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER || this.transferMode)) || option === PartyOption.CANCEL) {
|
2023-04-21 19:05:16 +01:00
|
|
|
switch (option) {
|
|
|
|
case PartyOption.MOVE_1:
|
|
|
|
case PartyOption.MOVE_2:
|
|
|
|
case PartyOption.MOVE_3:
|
|
|
|
case PartyOption.MOVE_4:
|
|
|
|
optionName = pokemon.moveset[option - PartyOption.MOVE_1].getName();
|
|
|
|
break;
|
|
|
|
default:
|
2024-01-10 04:34:43 +00:00
|
|
|
if (formChangeItemModifiers && option >= PartyOption.FORM_CHANGE_ITEM) {
|
|
|
|
const modifier = formChangeItemModifiers[option - PartyOption.FORM_CHANGE_ITEM];
|
|
|
|
optionName = `${modifier.active ? 'Deactivate' : 'Activate'} ${modifier.type.name}`;
|
|
|
|
} else
|
|
|
|
optionName = Utils.toReadableString(PartyOption[option]);
|
2023-04-21 19:05:16 +01:00
|
|
|
break;
|
|
|
|
}
|
2023-11-07 23:43:48 +00:00
|
|
|
} else if (option === PartyOption.SCROLL_UP)
|
|
|
|
optionName = '↑';
|
|
|
|
else if (option === PartyOption.SCROLL_DOWN)
|
|
|
|
optionName = '↓';
|
2023-11-08 22:30:07 +00:00
|
|
|
else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER) {
|
|
|
|
const move = learnableLevelMoves[option];
|
|
|
|
optionName = allMoves[move].name;
|
2023-11-09 04:37:12 +00:00
|
|
|
altText = !pokemon.getSpeciesForm().getLevelMoves().find(plm => plm[1] === move);
|
2023-11-08 22:30:07 +00:00
|
|
|
} else {
|
2023-04-21 19:05:16 +01:00
|
|
|
const itemModifier = itemModifiers[option];
|
|
|
|
optionName = itemModifier.type.name;
|
|
|
|
if (itemModifier.stackCount > 1)
|
|
|
|
optionName += ` (${itemModifier.stackCount})`;
|
2023-04-11 16:04:39 +01:00
|
|
|
}
|
|
|
|
|
2023-04-05 13:35:15 +01:00
|
|
|
const yCoord = -6 - 16 * o;
|
2024-01-10 04:34:43 +00:00
|
|
|
const optionText = addTextObject(this.scene, 0, yCoord - 16, optionName, TextStyle.WINDOW);
|
2023-11-09 03:30:22 +00:00
|
|
|
if (altText) {
|
|
|
|
optionText.setColor('#40c8f8');
|
|
|
|
optionText.setShadowColor('#006090')
|
|
|
|
}
|
2023-04-05 13:35:15 +01:00
|
|
|
optionText.setOrigin(0, 0);
|
|
|
|
|
2024-01-10 04:34:43 +00:00
|
|
|
optionTexts.push(optionText);
|
|
|
|
|
|
|
|
widestOptionWidth = Math.max(optionText.displayWidth, widestOptionWidth);
|
|
|
|
|
2023-04-05 13:35:15 +01:00
|
|
|
this.optionsContainer.add(optionText);
|
|
|
|
}
|
2024-01-10 04:34:43 +00:00
|
|
|
|
|
|
|
this.optionsBg.width = Math.max(widestOptionWidth + 24, 94);
|
|
|
|
for (let optionText of optionTexts)
|
|
|
|
optionText.x = 15 - this.optionsBg.width;
|
2023-04-05 13:35:15 +01:00
|
|
|
}
|
|
|
|
|
2023-04-21 19:05:16 +01:00
|
|
|
startTransfer(): void {
|
|
|
|
this.transferMode = true;
|
|
|
|
this.transferCursor = this.cursor;
|
2023-11-08 22:30:07 +00:00
|
|
|
this.transferOptionCursor = this.getOptionsCursorWithScroll();
|
2023-04-21 19:05:16 +01:00
|
|
|
|
|
|
|
this.partySlots[this.transferCursor].setTransfer(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
clearTransfer(): void {
|
|
|
|
this.transferMode = false;
|
|
|
|
this.partySlots[this.transferCursor].setTransfer(false);
|
|
|
|
}
|
|
|
|
|
2023-04-11 14:41:11 +01:00
|
|
|
doRelease(slotIndex: integer): void {
|
|
|
|
this.showText(this.getReleaseMessage(this.scene.getParty()[slotIndex].name), null, () => {
|
|
|
|
this.clearPartySlots();
|
|
|
|
this.scene.removePartyMemberModifiers(slotIndex);
|
2023-04-14 04:50:48 +01:00
|
|
|
const releasedPokemon = this.scene.getParty().splice(slotIndex, 1)[0];
|
|
|
|
releasedPokemon.destroy();
|
2023-04-11 14:41:11 +01:00
|
|
|
this.populatePartySlots();
|
|
|
|
if (this.cursor >= this.scene.getParty().length)
|
|
|
|
this.setCursor(this.cursor - 1);
|
|
|
|
if (this.partyUiMode === PartyUiMode.RELEASE) {
|
|
|
|
const selectCallback = this.selectCallback;
|
|
|
|
this.selectCallback = null;
|
2023-04-11 16:04:39 +01:00
|
|
|
selectCallback(this.cursor, PartyOption.RELEASE);
|
2023-12-20 05:35:41 +00:00
|
|
|
}
|
|
|
|
this.showText(null, 0);
|
2023-04-11 14:41:11 +01:00
|
|
|
}, null, true);
|
|
|
|
}
|
|
|
|
|
2023-04-11 06:31:18 +01:00
|
|
|
getReleaseMessage(pokemonName: string): string {
|
|
|
|
const rand = Utils.randInt(128);
|
2023-04-11 14:41:11 +01:00
|
|
|
if (rand < 20)
|
2023-04-11 06:31:18 +01:00
|
|
|
return `Goodbye, ${pokemonName}!`;
|
2023-04-11 14:41:11 +01:00
|
|
|
else if (rand < 40)
|
|
|
|
return `Byebye, ${pokemonName}!`;
|
|
|
|
else if (rand < 60)
|
2023-04-11 06:31:18 +01:00
|
|
|
return `Farewell, ${pokemonName}!`;
|
2023-04-11 14:41:11 +01:00
|
|
|
else if (rand < 80)
|
|
|
|
return `So long, ${pokemonName}!`;
|
|
|
|
else if (rand < 100)
|
2023-04-11 06:31:18 +01:00
|
|
|
return `This is where we part, ${pokemonName}!`;
|
|
|
|
else if (rand < 108)
|
|
|
|
return `I'll miss you, ${pokemonName}!`;
|
|
|
|
else if (rand < 116)
|
|
|
|
return `I'll never forget you, ${pokemonName}!`;
|
|
|
|
else if (rand < 124)
|
|
|
|
return `Until we meet again, ${pokemonName}!`;
|
|
|
|
else if (rand < 127)
|
|
|
|
return `Sayonara, ${pokemonName}!`
|
|
|
|
else
|
|
|
|
return `Smell ya later, ${pokemonName}!`;
|
|
|
|
}
|
|
|
|
|
2023-11-08 22:30:07 +00:00
|
|
|
getOptionsCursorWithScroll(): integer {
|
|
|
|
return this.optionsCursor + this.optionsScrollCursor + (this.options && this.options[0] === PartyOption.SCROLL_UP ? -1 : 0);
|
|
|
|
}
|
|
|
|
|
2023-04-05 13:35:15 +01:00
|
|
|
clearOptions() {
|
|
|
|
this.optionsMode = false;
|
2023-11-07 23:43:48 +00:00
|
|
|
this.optionsScroll = false;
|
|
|
|
this.optionsScrollCursor = 0;
|
|
|
|
this.optionsScrollTotal = 0;
|
2023-04-06 03:22:03 +01:00
|
|
|
this.options.splice(0, this.options.length);
|
2023-04-05 13:35:15 +01:00
|
|
|
this.optionsContainer.removeAll(true);
|
|
|
|
this.eraseOptionsCursor();
|
|
|
|
|
2023-12-21 03:22:15 +00:00
|
|
|
this.partyMessageBox.setSize(262, 30);
|
2023-04-23 03:14:53 +01:00
|
|
|
this.showText(null, 0);
|
2023-04-05 13:35:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
eraseOptionsCursor() {
|
|
|
|
if (this.optionsCursorObj)
|
|
|
|
this.optionsCursorObj.destroy();
|
|
|
|
this.optionsCursorObj = null;
|
|
|
|
}
|
2023-03-28 19:54:52 +01:00
|
|
|
|
|
|
|
clear() {
|
|
|
|
super.clear();
|
|
|
|
this.partyContainer.setVisible(false);
|
|
|
|
this.clearPartySlots();
|
|
|
|
}
|
|
|
|
|
|
|
|
clearPartySlots() {
|
|
|
|
this.partySlots.splice(0, this.partySlots.length);
|
|
|
|
this.partySlotsContainer.removeAll(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class PartySlot extends Phaser.GameObjects.Container {
|
|
|
|
private selected: boolean;
|
2023-04-21 19:05:16 +01:00
|
|
|
private transfer: boolean;
|
2023-03-28 19:54:52 +01:00
|
|
|
private slotIndex: integer;
|
|
|
|
private pokemon: PlayerPokemon;
|
|
|
|
|
|
|
|
private slotBg: Phaser.GameObjects.Image;
|
|
|
|
private slotPb: Phaser.GameObjects.Sprite;
|
|
|
|
|
2023-12-07 05:52:20 +00:00
|
|
|
private pokemonIcon: Phaser.GameObjects.Sprite;
|
|
|
|
private iconAnimHandler: PokemonIconAnimHandler;
|
|
|
|
|
|
|
|
constructor(scene: BattleScene, slotIndex: integer, pokemon: PlayerPokemon, iconAnimHandler: PokemonIconAnimHandler, partyUiMode: PartyUiMode, tmMoveId: Moves) {
|
2023-05-18 16:11:06 +01:00
|
|
|
super(scene, slotIndex >= scene.currentBattle.getBattlerCount() ? 230.5 : 64,
|
2024-02-15 04:33:55 +00:00
|
|
|
slotIndex >= scene.currentBattle.getBattlerCount() ? -184 + (scene.currentBattle.double ? -40 : 0)
|
|
|
|
+ (28 + (scene.currentBattle.double ? 8 : 0)) * slotIndex : -124 + (scene.currentBattle.double ? -8 : 0) + slotIndex * 64);
|
2023-03-28 19:54:52 +01:00
|
|
|
|
|
|
|
this.slotIndex = slotIndex;
|
|
|
|
this.pokemon = pokemon;
|
2023-12-07 05:52:20 +00:00
|
|
|
this.iconAnimHandler = iconAnimHandler;
|
2023-03-28 19:54:52 +01:00
|
|
|
|
2023-07-05 04:11:31 +01:00
|
|
|
this.setup(partyUiMode, tmMoveId);
|
2023-03-28 19:54:52 +01:00
|
|
|
}
|
|
|
|
|
2023-07-05 04:11:31 +01:00
|
|
|
setup(partyUiMode: PartyUiMode, tmMoveId: Moves) {
|
2023-05-18 16:11:06 +01:00
|
|
|
const battlerCount = (this.scene as BattleScene).currentBattle.getBattlerCount();
|
|
|
|
|
|
|
|
const slotKey = `party_slot${this.slotIndex >= battlerCount ? '' : '_main'}`;
|
2023-03-28 19:54:52 +01:00
|
|
|
|
|
|
|
const slotBg = this.scene.add.sprite(0, 0, slotKey, `${slotKey}${this.pokemon.hp ? '' : '_fnt'}`);
|
|
|
|
this.slotBg = slotBg;
|
|
|
|
|
|
|
|
this.add(slotBg);
|
|
|
|
|
2023-05-18 16:11:06 +01:00
|
|
|
const slotPb = this.scene.add.sprite(this.slotIndex >= battlerCount ? -85.5 : -51, this.slotIndex >= battlerCount ? 0 : -20.5, 'party_pb');
|
2023-03-28 19:54:52 +01:00
|
|
|
this.slotPb = slotPb;
|
|
|
|
|
|
|
|
this.add(slotPb);
|
|
|
|
|
2023-12-07 05:52:20 +00:00
|
|
|
this.pokemonIcon = this.scene.add.sprite(slotPb.x, slotPb.y, this.pokemon.getIconAtlasKey(true));
|
2023-12-24 20:09:52 +00:00
|
|
|
this.pokemonIcon.setFrame(this.pokemon.getIconId(true));
|
2023-12-07 05:52:20 +00:00
|
|
|
|
|
|
|
this.add(this.pokemonIcon);
|
2023-03-28 19:54:52 +01:00
|
|
|
|
2023-12-07 05:52:20 +00:00
|
|
|
this.iconAnimHandler.addOrUpdate(this.pokemonIcon, PokemonIconAnimMode.PASSIVE);
|
2023-03-28 19:54:52 +01:00
|
|
|
|
|
|
|
const slotInfoContainer = this.scene.add.container(0, 0);
|
|
|
|
this.add(slotInfoContainer);
|
|
|
|
|
2023-12-10 04:41:36 +00:00
|
|
|
let displayName = this.pokemon.name;
|
|
|
|
let nameTextWidth: number;
|
|
|
|
|
|
|
|
let nameSizeTest = addTextObject(this.scene, 0, 0, displayName, TextStyle.PARTY);
|
|
|
|
nameTextWidth = nameSizeTest.displayWidth;
|
|
|
|
|
|
|
|
while (nameTextWidth > (this.slotIndex ? 52 : 80)) {
|
|
|
|
displayName = `${displayName.slice(0, displayName.endsWith('.') ? -2 : -1).trimEnd()}.`;
|
|
|
|
nameSizeTest.setText(displayName);
|
|
|
|
nameTextWidth = nameSizeTest.displayWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
nameSizeTest.destroy();
|
|
|
|
|
|
|
|
const slotName = addTextObject(this.scene, 0, 0, displayName, TextStyle.PARTY);
|
2023-07-05 05:29:22 +01:00
|
|
|
slotName.setPositionRelative(slotBg, this.slotIndex >= battlerCount ? 21 : 24, this.slotIndex >= battlerCount ? 2 : 10);
|
2023-03-28 19:54:52 +01:00
|
|
|
slotName.setOrigin(0, 0);
|
|
|
|
|
|
|
|
const slotLevelLabel = this.scene.add.image(0, 0, 'party_slot_overlay_lv');
|
|
|
|
slotLevelLabel.setPositionRelative(slotName, 8, 12);
|
|
|
|
slotLevelLabel.setOrigin(0, 0);
|
|
|
|
|
2023-10-03 17:50:31 +01:00
|
|
|
const slotLevelText = addTextObject(this.scene, 0, 0, this.pokemon.level.toString(), this.pokemon.level < (this.scene as BattleScene).getMaxExpLevel() ? TextStyle.PARTY : TextStyle.PARTY_RED);
|
2023-03-28 19:54:52 +01:00
|
|
|
slotLevelText.setPositionRelative(slotLevelLabel, 9, 0);
|
|
|
|
slotLevelText.setOrigin(0, 0.25);
|
|
|
|
|
2023-07-05 04:11:31 +01:00
|
|
|
slotInfoContainer.add([ slotName, slotLevelLabel, slotLevelText ]);
|
|
|
|
|
2023-10-29 05:28:56 +00:00
|
|
|
const genderSymbol = getGenderSymbol(this.pokemon.getGender(true));
|
2023-07-05 05:29:22 +01:00
|
|
|
|
|
|
|
if (genderSymbol) {
|
|
|
|
const slotGenderText = addTextObject(this.scene, 0, 0, genderSymbol, TextStyle.PARTY);
|
2023-10-29 05:28:56 +00:00
|
|
|
slotGenderText.setColor(getGenderColor(this.pokemon.getGender(true)));
|
|
|
|
slotGenderText.setShadowColor(getGenderColor(this.pokemon.getGender(true), true));
|
2023-07-10 16:21:05 +01:00
|
|
|
if (this.slotIndex >= battlerCount)
|
|
|
|
slotGenderText.setPositionRelative(slotLevelLabel, 36, 0);
|
|
|
|
else
|
|
|
|
slotGenderText.setPositionRelative(slotName, 76, 3);
|
2023-07-05 05:29:22 +01:00
|
|
|
slotGenderText.setOrigin(0, 0.25);
|
|
|
|
|
|
|
|
slotInfoContainer.add(slotGenderText);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.pokemon.status) {
|
|
|
|
const statusIndicator = this.scene.add.sprite(0, 0, 'statuses');
|
2023-07-10 16:21:05 +01:00
|
|
|
statusIndicator.setFrame(StatusEffect[this.pokemon.status?.effect].toLowerCase());
|
2023-07-05 05:29:22 +01:00
|
|
|
statusIndicator.setOrigin(0, 0);
|
|
|
|
statusIndicator.setPositionRelative(slotLevelLabel, this.slotIndex >= battlerCount ? 43 : 55, 0);
|
|
|
|
|
|
|
|
slotInfoContainer.add(statusIndicator);
|
|
|
|
}
|
|
|
|
|
2023-11-06 04:48:04 +00:00
|
|
|
if (this.pokemon.isShiny()) {
|
2023-07-05 16:54:36 +01:00
|
|
|
const shinyStar = this.scene.add.image(0, 0, 'shiny_star');
|
2023-07-05 05:29:22 +01:00
|
|
|
shinyStar.setOrigin(0, 0);
|
2023-07-10 16:21:05 +01:00
|
|
|
shinyStar.setPositionRelative(slotName, -8, 2);
|
2023-07-05 05:29:22 +01:00
|
|
|
|
|
|
|
slotInfoContainer.add(shinyStar);
|
|
|
|
}
|
|
|
|
|
2023-07-05 04:11:31 +01:00
|
|
|
if (partyUiMode !== PartyUiMode.TM_MODIFIER) {
|
|
|
|
const slotHpBar = this.scene.add.image(0, 0, 'party_slot_hp_bar');
|
2023-07-05 05:29:22 +01:00
|
|
|
slotHpBar.setPositionRelative(slotBg, this.slotIndex >= battlerCount ? 72 : 8, this.slotIndex >= battlerCount ? 6 : 31);
|
2023-07-05 04:11:31 +01:00
|
|
|
slotHpBar.setOrigin(0, 0);
|
2023-03-28 19:54:52 +01:00
|
|
|
|
2023-07-05 04:11:31 +01:00
|
|
|
const hpRatio = this.pokemon.getHpRatio();
|
2023-03-28 19:54:52 +01:00
|
|
|
|
2023-07-05 04:11:31 +01:00
|
|
|
const slotHpOverlay = this.scene.add.sprite(0, 0, 'party_slot_hp_overlay', hpRatio > 0.5 ? 'high' : hpRatio > 0.25 ? 'medium' : 'low');
|
|
|
|
slotHpOverlay.setPositionRelative(slotHpBar, 16, 2);
|
|
|
|
slotHpOverlay.setOrigin(0, 0);
|
|
|
|
slotHpOverlay.setScale(hpRatio, 1);
|
2023-03-28 19:54:52 +01:00
|
|
|
|
2023-07-05 04:11:31 +01:00
|
|
|
const slotHpText = addTextObject(this.scene, 0, 0, `${this.pokemon.hp}/${this.pokemon.getMaxHp()}`, TextStyle.PARTY);
|
|
|
|
slotHpText.setPositionRelative(slotHpBar, slotHpBar.width - 3, slotHpBar.height - 2);
|
|
|
|
slotHpText.setOrigin(1, 0);
|
2023-03-28 19:54:52 +01:00
|
|
|
|
2023-07-05 04:11:31 +01:00
|
|
|
slotInfoContainer.add([ slotHpBar, slotHpOverlay, slotHpText ]);
|
|
|
|
} else {
|
|
|
|
let slotTmText: string;
|
|
|
|
switch (true) {
|
|
|
|
case (this.pokemon.compatibleTms.indexOf(tmMoveId) === -1):
|
2023-10-18 23:01:15 +01:00
|
|
|
slotTmText = 'Not Able';
|
2023-07-05 04:11:31 +01:00
|
|
|
break;
|
|
|
|
case (this.pokemon.getMoveset().filter(m => m?.moveId === tmMoveId).length > 0):
|
2023-10-18 23:01:15 +01:00
|
|
|
slotTmText = 'Learned';
|
2023-07-05 04:11:31 +01:00
|
|
|
break;
|
|
|
|
default:
|
2023-10-18 23:01:15 +01:00
|
|
|
slotTmText = 'Able';
|
2023-07-05 04:11:31 +01:00
|
|
|
break;
|
|
|
|
}
|
2023-03-28 19:54:52 +01:00
|
|
|
|
2023-07-05 05:29:22 +01:00
|
|
|
const slotTmLabel = addTextObject(this.scene, 0, 0, slotTmText, TextStyle.MESSAGE);
|
|
|
|
slotTmLabel.setPositionRelative(slotBg, this.slotIndex >= battlerCount ? 94 : 32, this.slotIndex >= battlerCount ? 16 : 46);
|
|
|
|
slotTmLabel.setOrigin(0, 1);
|
|
|
|
|
|
|
|
slotInfoContainer.add(slotTmLabel);
|
2023-07-05 04:11:31 +01:00
|
|
|
}
|
2023-03-28 19:54:52 +01:00
|
|
|
}
|
|
|
|
|
2023-04-21 19:05:16 +01:00
|
|
|
select(): void {
|
2023-03-28 19:54:52 +01:00
|
|
|
if (this.selected)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this.selected = true;
|
2023-12-07 05:52:20 +00:00
|
|
|
this.iconAnimHandler.addOrUpdate(this.pokemonIcon, PokemonIconAnimMode.ACTIVE);
|
2023-03-28 19:54:52 +01:00
|
|
|
|
2023-04-21 19:05:16 +01:00
|
|
|
this.updateSlotTexture();
|
2023-03-28 19:54:52 +01:00
|
|
|
this.slotPb.setFrame('party_pb_sel');
|
|
|
|
}
|
|
|
|
|
2023-04-21 19:05:16 +01:00
|
|
|
deselect(): void {
|
2023-03-28 19:54:52 +01:00
|
|
|
if (!this.selected)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this.selected = false;
|
2023-12-07 05:52:20 +00:00
|
|
|
this.iconAnimHandler.addOrUpdate(this.pokemonIcon, PokemonIconAnimMode.PASSIVE);
|
2023-03-28 19:54:52 +01:00
|
|
|
|
2023-04-21 19:05:16 +01:00
|
|
|
this.updateSlotTexture();
|
2023-03-28 19:54:52 +01:00
|
|
|
this.slotPb.setFrame('party_pb');
|
|
|
|
}
|
2023-04-21 19:05:16 +01:00
|
|
|
|
|
|
|
setTransfer(transfer: boolean): void {
|
|
|
|
if (this.transfer === transfer)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this.transfer = transfer;
|
|
|
|
this.updateSlotTexture();
|
|
|
|
}
|
|
|
|
|
|
|
|
private updateSlotTexture(): void {
|
2023-05-18 16:11:06 +01:00
|
|
|
const battlerCount = (this.scene as BattleScene).currentBattle.getBattlerCount();
|
|
|
|
this.slotBg.setTexture(`party_slot${this.slotIndex >= battlerCount ? '' : '_main'}`,
|
|
|
|
`party_slot${this.slotIndex >= battlerCount ? '' : '_main'}${this.transfer ? '_swap' : this.pokemon.hp ? '' : '_fnt'}${this.selected ? '_sel' : ''}`);
|
2023-04-21 19:05:16 +01:00
|
|
|
}
|
2023-03-28 19:54:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
class PartyCancelButton extends Phaser.GameObjects.Container {
|
|
|
|
private selected: boolean;
|
|
|
|
|
|
|
|
private partyCancelBg: Phaser.GameObjects.Sprite;
|
|
|
|
private partyCancelPb: Phaser.GameObjects.Sprite;
|
|
|
|
|
|
|
|
constructor(scene: BattleScene, x: number, y: number) {
|
|
|
|
super(scene, x, y);
|
|
|
|
|
|
|
|
this.setup();
|
|
|
|
}
|
|
|
|
|
|
|
|
setup() {
|
|
|
|
const partyCancelBg = this.scene.add.sprite(0, 0, 'party_cancel');
|
|
|
|
this.add(partyCancelBg);
|
|
|
|
|
|
|
|
this.partyCancelBg = partyCancelBg;
|
|
|
|
|
|
|
|
const partyCancelPb = this.scene.add.sprite(-17, 0, 'party_pb');
|
|
|
|
this.add(partyCancelPb);
|
|
|
|
|
|
|
|
this.partyCancelPb = partyCancelPb;
|
|
|
|
|
2023-10-18 23:01:15 +01:00
|
|
|
const partyCancelText = addTextObject(this.scene, -7, -6, 'Cancel', TextStyle.PARTY);
|
2023-03-28 19:54:52 +01:00
|
|
|
this.add(partyCancelText);
|
|
|
|
}
|
|
|
|
|
|
|
|
select() {
|
|
|
|
if (this.selected)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this.selected = true;
|
|
|
|
|
|
|
|
this.partyCancelBg.setFrame(`party_cancel_sel`);
|
|
|
|
this.partyCancelPb.setFrame('party_pb_sel');
|
|
|
|
}
|
|
|
|
|
|
|
|
deselect() {
|
|
|
|
if (!this.selected)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this.selected = false;
|
|
|
|
|
|
|
|
this.partyCancelBg.setFrame('party_cancel');
|
|
|
|
this.partyCancelPb.setFrame('party_pb');
|
|
|
|
}
|
|
|
|
}
|