Implement trainer battles and various changes
Implement trainer battles; add dialogue functionality; add random session seed for predictable random results; remove capitalization from text; add full party heal after every 10 waves
This commit is contained in:
1 parent
75bd40863e
commit
83c70889fc
50 files changed
+1500
-399
No files matched your search
@@ -32,7 +32,7 @@ export default class BallUiHandler extends UiHandler {
|
||||
|
||||
for (let pb = 0; pb < Object.keys(this.scene.pokeballCounts).length; pb++)
|
||||
optionsTextContent += `${getPokeballName(pb)}\n`;
|
||||
optionsTextContent += 'CANCEL';
|
||||
optionsTextContent += 'Cancel';
|
||||
const optionsText = addTextObject(this.scene, 0, 0, optionsTextContent, TextStyle.WINDOW, { align: 'right', maxLines: 6 });
|
||||
optionsText.setOrigin(0, 0);
|
||||
optionsText.setPositionRelative(this.pokeballSelectBg, 42, 9);
|
||||
|
||||
@@ -9,14 +9,16 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
|
||||
private levelUpStatsContainer: Phaser.GameObjects.Container;
|
||||
private levelUpStatsIncrContent: Phaser.GameObjects.Text;
|
||||
private levelUpStatsValuesContent: Phaser.GameObjects.Text;
|
||||
private nameText: Phaser.GameObjects.Text;
|
||||
|
||||
public bg: Phaser.GameObjects.Image;
|
||||
public nameBoxContainer: Phaser.GameObjects.Container;
|
||||
|
||||
constructor(scene: BattleScene) {
|
||||
super(scene, Mode.MESSAGE);
|
||||
}
|
||||
|
||||
setup() {
|
||||
setup(): void {
|
||||
const ui = this.getUi();
|
||||
|
||||
this.textTimer = null;
|
||||
@@ -41,6 +43,18 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
|
||||
|
||||
this.message = message;
|
||||
|
||||
this.nameBoxContainer = this.scene.add.container(0, -16);
|
||||
this.nameBoxContainer.setVisible(false);
|
||||
|
||||
const nameBox = this.scene.add.nineslice(0, 0, 'namebox', null, 72, 16, 8, 8, 5, 5);
|
||||
nameBox.setOrigin(0, 0);
|
||||
|
||||
this.nameText = addTextObject(this.scene, 8, 0, 'Rival', TextStyle.MESSAGE, { maxLines: 1 });
|
||||
|
||||
this.nameBoxContainer.add(nameBox);
|
||||
this.nameBoxContainer.add(this.nameText);
|
||||
messageContainer.add(this.nameBoxContainer);
|
||||
|
||||
const prompt = this.scene.add.sprite(0, 0, 'prompt');
|
||||
prompt.setVisible(false);
|
||||
prompt.setOrigin(0, 0);
|
||||
@@ -81,14 +95,14 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
|
||||
this.levelUpStatsValuesContent = levelUpStatsValuesContent;
|
||||
}
|
||||
|
||||
show(args: any[]) {
|
||||
show(args: any[]): void {
|
||||
super.show(args);
|
||||
|
||||
this.bg.setTexture('bg');
|
||||
this.message.setWordWrapWidth(1780);
|
||||
}
|
||||
|
||||
processInput(button: Button) {
|
||||
processInput(button: Button): void {
|
||||
const ui = this.getUi();
|
||||
if (this.awaitingActionInput) {
|
||||
if (button === Button.CANCEL || button === Button.ACTION) {
|
||||
@@ -102,11 +116,21 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
clear(): void {
|
||||
super.clear();
|
||||
}
|
||||
|
||||
promptLevelUpStats(partyMemberIndex: integer, prevStats: integer[], showTotals: boolean, callback?: Function) {
|
||||
showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer) {
|
||||
this.hideNameText();
|
||||
super.showText(text, delay, callback, callbackDelay, prompt, promptDelay);
|
||||
}
|
||||
|
||||
showDialogue(text: string, name: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer) {
|
||||
this.showNameText(name);
|
||||
super.showDialogue(text, name, delay, callback, callbackDelay, prompt, promptDelay);
|
||||
}
|
||||
|
||||
promptLevelUpStats(partyMemberIndex: integer, prevStats: integer[], showTotals: boolean, callback?: Function): void {
|
||||
const newStats = (this.scene as BattleScene).getParty()[partyMemberIndex].stats;
|
||||
let levelUpStatsValuesText = '';
|
||||
const stats = Utils.getEnumValues(Stat);
|
||||
@@ -126,4 +150,13 @@ export default class BattleMessageUiHandler extends MessageUiHandler {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
showNameText(name: string): void {
|
||||
this.nameBoxContainer.setVisible(true);
|
||||
this.nameText.setText(name);
|
||||
}
|
||||
|
||||
hideNameText(): void {
|
||||
this.nameBoxContainer.setVisible(false);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import { CommandPhase } from "../battle-phases";
|
||||
import BattleScene, { Button } from "../battle-scene";
|
||||
import { addTextObject, TextStyle } from "./text";
|
||||
import { toPokemonUpperCase } from "../utils";
|
||||
import PartyUiHandler, { PartyUiMode } from "./party-ui-handler";
|
||||
import UI, { Mode } from "./ui";
|
||||
import UiHandler from "./uiHandler";
|
||||
@@ -23,7 +22,7 @@ export default class CommandUiHandler extends UiHandler {
|
||||
|
||||
setup() {
|
||||
const ui = this.getUi();
|
||||
const commands = [ 'Fight', 'Ball', 'Pokémon', 'Run' ].map(s => toPokemonUpperCase(s));
|
||||
const commands = [ 'Fight', 'Ball', 'Pokémon', 'Run' ];
|
||||
|
||||
this.commandsContainer = this.scene.add.container(216, -38.7);
|
||||
this.commandsContainer.setVisible(false);
|
||||
|
||||
@@ -18,6 +18,14 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler {
|
||||
}
|
||||
|
||||
showText(text: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer) {
|
||||
this.showTextInternal(text, delay, callback, callbackDelay, prompt, promptDelay);
|
||||
}
|
||||
|
||||
showDialogue(text: string, name: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer) {
|
||||
this.showTextInternal(text, delay, callback, callbackDelay, prompt, promptDelay);
|
||||
}
|
||||
|
||||
private showTextInternal(text: string, delay: integer, callback: Function, callbackDelay: integer, prompt: boolean, promptDelay: integer) {
|
||||
if (delay === null || delay === undefined)
|
||||
delay = 20;
|
||||
let delayMap = new Map<integer, integer>();
|
||||
|
||||
@@ -188,7 +188,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
|
||||
ui.showText(this.options[this.cursor].modifierTypeOption.type.description);
|
||||
} else {
|
||||
this.cursorObj.setPosition((this.scene.game.canvas.width / 6) - 50, -60);
|
||||
ui.showText('Transfer a held item from one POKéMON to another instead of selecting an item');
|
||||
ui.showText('Transfer a held item from one Pokémon to another instead of selecting an item');
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -249,7 +249,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
});
|
||||
});
|
||||
} else
|
||||
this.showText('You can\'t release a POKéMON that\'s in battle!', null, () => this.showText(null, 0), null, true);
|
||||
this.showText('You can\'t release a Pokémon that\'s in battle!', null, () => this.showText(null, 0), null, true);
|
||||
} else if (option === PartyOption.CANCEL)
|
||||
this.processInput(Button.CANCEL);
|
||||
} else if (button === Button.CANCEL) {
|
||||
@@ -473,7 +473,7 @@ export default class PartyUiHandler extends MessageUiHandler {
|
||||
optionName = pokemon.moveset[option - PartyOption.MOVE_1].getName();
|
||||
break;
|
||||
default:
|
||||
optionName = PartyOption[option].replace(/\_/g, ' ');
|
||||
optionName = Utils.toReadableString(PartyOption[option]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -694,13 +694,13 @@ class PartySlot extends Phaser.GameObjects.Container {
|
||||
let slotTmText: string;
|
||||
switch (true) {
|
||||
case (this.pokemon.compatibleTms.indexOf(tmMoveId) === -1):
|
||||
slotTmText = 'NOT ABLE';
|
||||
slotTmText = 'Not Able';
|
||||
break;
|
||||
case (this.pokemon.getMoveset().filter(m => m?.moveId === tmMoveId).length > 0):
|
||||
slotTmText = 'LEARNED';
|
||||
slotTmText = 'Learned';
|
||||
break;
|
||||
default:
|
||||
slotTmText = 'ABLE';
|
||||
slotTmText = 'Able';
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -770,7 +770,7 @@ class PartyCancelButton extends Phaser.GameObjects.Container {
|
||||
|
||||
this.partyCancelPb = partyCancelPb;
|
||||
|
||||
const partyCancelText = addTextObject(this.scene, -7, -6, 'CANCEL', TextStyle.PARTY);
|
||||
const partyCancelText = addTextObject(this.scene, -7, -6, 'Cancel', TextStyle.PARTY);
|
||||
this.add(partyCancelText);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
import BattleScene from "../battle-scene";
|
||||
import Pokemon from "../pokemon";
|
||||
|
||||
export default class PokeballTray extends Phaser.GameObjects.Container {
|
||||
private player: boolean;
|
||||
|
||||
private bg: Phaser.GameObjects.NineSlice;
|
||||
private balls: Phaser.GameObjects.Sprite[];
|
||||
|
||||
public shown: boolean;
|
||||
|
||||
constructor(scene: BattleScene, player: boolean) {
|
||||
super(scene, player ? (scene.game.canvas.width / 6) : 0, player ? -72 : -144);
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
setup(): void {
|
||||
this.bg = this.scene.add.nineslice(0, 0, `pb_tray_overlay_${this.player ? 'player' : 'enemy'}`, null, 104, 4, 48, 8, 0, 0);
|
||||
this.bg.setOrigin(this.player ? 1 : 0, 0);
|
||||
|
||||
this.add(this.bg);
|
||||
|
||||
this.balls = new Array(6).fill(null).map((_, i) => this.scene.add.sprite((this.player ? -83 : 76) + (this.scene.game.canvas.width / 6) * (this.player ? -1 : 1) + 10 * i * (this.player ? 1 : -1), -8, 'pb_tray_ball', 'empty'));
|
||||
|
||||
for (let ball of this.balls) {
|
||||
ball.setOrigin(0, 0);
|
||||
this.add(ball);
|
||||
}
|
||||
|
||||
this.setVisible(false);
|
||||
this.shown = false;
|
||||
}
|
||||
|
||||
showPbTray(party: Pokemon[]): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
if (this.shown)
|
||||
return resolve();
|
||||
|
||||
(this.scene as BattleScene).fieldUI.bringToTop(this);
|
||||
|
||||
this.x += 104 * (this.player ? 1 : -1);
|
||||
|
||||
this.bg.width = 104;
|
||||
this.bg.alpha = 1;
|
||||
|
||||
this.balls.forEach((ball, b) => {
|
||||
ball.x += (this.scene.game.canvas.width / 6 + 104) * (this.player ? 1 : -1);
|
||||
let ballFrame = 'ball';
|
||||
if (b >= party.length)
|
||||
ballFrame = 'empty';
|
||||
else if (!party[b].hp)
|
||||
ballFrame = 'fainted';
|
||||
else if (party[b].status)
|
||||
ballFrame = 'status';
|
||||
ball.setFrame(ballFrame);
|
||||
});
|
||||
|
||||
this.scene.sound.play('pb_tray_enter');
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: this,
|
||||
x: `${this.player ? '-' : '+'}=104`,
|
||||
duration: 500,
|
||||
ease: 'Sine.easeIn',
|
||||
onComplete: () => {
|
||||
this.balls.forEach((ball, b) => {
|
||||
this.scene.tweens.add({
|
||||
targets: ball,
|
||||
x: `${this.player ? '-' : '+'}=104`,
|
||||
duration: b * 100,
|
||||
ease: 'Sine.easeIn',
|
||||
onComplete: () => this.scene.sound.play(b < party.length ? 'pb_tray_ball' : 'pb_tray_empty')
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.setVisible(true);
|
||||
this.shown = true;
|
||||
|
||||
this.scene.time.delayedCall(1100, () => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
hide(): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
if (!this.shown)
|
||||
return resolve();
|
||||
|
||||
this.balls.forEach((ball, b) => {
|
||||
this.scene.tweens.add({
|
||||
targets: ball,
|
||||
x: `${this.player ? '-' : '+'}=${this.scene.game.canvas.width / 6}`,
|
||||
duration: 250,
|
||||
delay: b * 100,
|
||||
ease: 'Sine.easeIn'
|
||||
});
|
||||
});
|
||||
|
||||
this.scene.tweens.add({
|
||||
targets: this.bg,
|
||||
width: 144,
|
||||
alpha: 0,
|
||||
duration: 500,
|
||||
ease: 'Sine.easeIn'
|
||||
});
|
||||
|
||||
this.scene.time.delayedCall(850, () => {
|
||||
this.setVisible(false);
|
||||
resolve();
|
||||
});
|
||||
|
||||
this.shown = false;
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -94,7 +94,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
this.pokemonGenderText.setOrigin(0, 0);
|
||||
this.starterSelectContainer.add(this.pokemonGenderText);
|
||||
|
||||
this.pokemonAbilityLabelText = addTextObject(this.scene, 6, 126, 'ABILITY:', TextStyle.SUMMARY, { fontSize: '64px' });
|
||||
this.pokemonAbilityLabelText = addTextObject(this.scene, 6, 126, 'Ability:', TextStyle.SUMMARY, { fontSize: '64px' });
|
||||
this.pokemonAbilityLabelText.setOrigin(0, 0);
|
||||
this.pokemonAbilityLabelText.setVisible(false);
|
||||
this.starterSelectContainer.add(this.pokemonAbilityLabelText);
|
||||
@@ -276,7 +276,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
this.popStarter();
|
||||
this.clearText();
|
||||
};
|
||||
ui.showText('Begin with these POKéMON?', null, () => {
|
||||
ui.showText('Begin with these Pokémon?', null, () => {
|
||||
ui.setModeWithoutClear(Mode.CONFIRM, () => {
|
||||
const startRun = (gameMode: GameMode) => {
|
||||
this.scene.gameMode = gameMode;
|
||||
@@ -467,7 +467,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
|
||||
|
||||
if (species && this.speciesStarterDexEntry) {
|
||||
this.pokemonNumberText.setText(Utils.padInt(species.speciesId, 3));
|
||||
this.pokemonNameText.setText(species.name.toUpperCase());
|
||||
this.pokemonNameText.setText(species.name);
|
||||
this.pokemonAbilityLabelText.setVisible(true);
|
||||
|
||||
this.setSpeciesDetails(species, !!this.speciesStarterDexEntry?.shiny, this.speciesStarterDexEntry?.formIndex, !!this.speciesStarterDexEntry?.female, this.speciesStarterDexEntry?.abilityIndex);
|
||||
|
||||
@@ -109,12 +109,19 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
this.summaryContainer.add(this.genderText);
|
||||
|
||||
this.moveEffectContainer = this.scene.add.container(106, -62);
|
||||
|
||||
this.summaryContainer.add(this.moveEffectContainer);
|
||||
|
||||
const moveEffectBg = this.scene.add.image(0, 0, 'summary_moves_effect');
|
||||
moveEffectBg.setOrigin(0, 0);
|
||||
this.moveEffectContainer.add(moveEffectBg);
|
||||
|
||||
const moveEffectLabels = addTextObject(this.scene, 8, 12, 'Power\nAccuracy\nCategory', TextStyle.SUMMARY);
|
||||
moveEffectLabels.setLineSpacing(9);
|
||||
moveEffectLabels.setOrigin(0, 0);
|
||||
|
||||
this.moveEffectContainer.add(moveEffectLabels);
|
||||
|
||||
this.movePowerText = addTextObject(this.scene, 99, 27, '0', TextStyle.WINDOW);
|
||||
this.movePowerText.setOrigin(1, 1);
|
||||
this.moveEffectContainer.add(this.movePowerText);
|
||||
@@ -420,7 +427,7 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
const profileContainer = this.scene.add.container(0, -pageBg.height);
|
||||
pageContainer.add(profileContainer);
|
||||
|
||||
const typeLabel = addTextObject(this.scene, 7, 28, 'TYPE/', TextStyle.WINDOW);
|
||||
const typeLabel = addTextObject(this.scene, 7, 28, 'Type/', TextStyle.WINDOW);
|
||||
typeLabel.setOrigin(0, 0);
|
||||
profileContainer.add(typeLabel);
|
||||
|
||||
@@ -483,11 +490,11 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
const totalLvExp = getLevelTotalExp(this.pokemon.level, this.pokemon.species.growthRate);
|
||||
const expRatio = this.pokemon.level < this.scene.getMaxExpLevel() ? this.pokemon.levelExp / totalLvExp : 0;
|
||||
|
||||
const expLabel = addTextObject(this.scene, 6, 112, 'EXP. POINTS', TextStyle.SUMMARY);
|
||||
const expLabel = addTextObject(this.scene, 6, 112, 'EXP. Points', TextStyle.SUMMARY);
|
||||
expLabel.setOrigin(0, 0);
|
||||
statsContainer.add(expLabel);
|
||||
|
||||
const nextLvExpLabel = addTextObject(this.scene, 6, 128, 'NEXT LV.', TextStyle.SUMMARY);
|
||||
const nextLvExpLabel = addTextObject(this.scene, 6, 128, 'Next Lv.', TextStyle.SUMMARY);
|
||||
nextLvExpLabel.setOrigin(0, 0);
|
||||
statsContainer.add(nextLvExpLabel);
|
||||
|
||||
@@ -528,7 +535,7 @@ export default class SummaryUiHandler extends UiHandler {
|
||||
extraRowOverlay.setOrigin(0, 1);
|
||||
this.extraMoveRowContainer.add(extraRowOverlay);
|
||||
|
||||
const extraRowText = addTextObject(this.scene, 35, 0, this.summaryUiMode === SummaryUiMode.LEARN_MOVE ? this.newMove.name : 'CANCEL',
|
||||
const extraRowText = addTextObject(this.scene, 35, 0, this.summaryUiMode === SummaryUiMode.LEARN_MOVE ? this.newMove.name : 'Cancel',
|
||||
this.summaryUiMode === SummaryUiMode.LEARN_MOVE ? TextStyle.SUMMARY_RED : TextStyle.SUMMARY);
|
||||
extraRowText.setOrigin(0, 1);
|
||||
this.extraMoveRowContainer.add(extraRowText);
|
||||
|
||||
@@ -26,7 +26,6 @@ export function addTextObject(scene: Phaser.Scene, x: number, y: number, content
|
||||
case TextStyle.SUMMARY:
|
||||
case TextStyle.SUMMARY_RED:
|
||||
case TextStyle.SUMMARY_GOLD:
|
||||
styleOptions.padding = undefined;
|
||||
case TextStyle.WINDOW:
|
||||
case TextStyle.MESSAGE:
|
||||
styleOptions.fontSize = '96px';
|
||||
|
||||
@@ -104,6 +104,14 @@ export default class UI extends Phaser.GameObjects.Container {
|
||||
this.getMessageHandler().showText(text, delay, callback, callbackDelay, prompt, promptDelay);
|
||||
}
|
||||
|
||||
showDialogue(text: string, name: string, delay?: integer, callback?: Function, callbackDelay?: integer, prompt?: boolean, promptDelay?: integer): void {
|
||||
const handler = this.getHandler();
|
||||
if (handler instanceof MessageUiHandler)
|
||||
(handler as MessageUiHandler).showDialogue(text, name, delay, callback, callbackDelay, prompt, promptDelay);
|
||||
else
|
||||
this.getMessageHandler().showDialogue(text, name, delay, callback, callbackDelay, prompt, promptDelay);
|
||||
}
|
||||
|
||||
clearText(): void {
|
||||
const handler = this.getHandler();
|
||||
if (handler instanceof MessageUiHandler)
|
||||
|
||||
Reference in new issue
Block a user