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:
Flashfyre committed 2023-10-18 18:01:15 -04:00
1 parent 75bd40863e
commit 83c70889fc
50 files changed
+1500 -399

No files matched your search

+1 -1
View File
@@ -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);
+38 -5
View File
@@ -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 -2
View File
@@ -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);
+8
View File
@@ -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>();
+1 -1
View File
@@ -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;
+6 -6
View File
@@ -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);
}
+116
View File
@@ -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;
});
};
}
+3 -3
View File
@@ -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);
+11 -4
View File
@@ -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);
-1
View File
@@ -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';
+8
View File
@@ -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)