mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-10-20 12:05:50 +02:00
* add .github/workflows/mystery-event.yml * update mystery-event.yml * mystery encounters: resolve review comments: Lost at Sea: -fix typo in handlePokemonGuidingYouPhase function Mysterious Chest: - remove obsolete commented code mystery-encounter.ts - remove unused `onDone` field from MysteryEncounterBuilder * fix typo in CanLearnMoveRequirementOptions * remove redundance from Pokemon.isAllowedInBattle() * chore: jsdoc formatting * fix lost-at-sea tests * add fallback for biomeMysteryEncounters if empty * lost-at-sea-encounter: fix and extend tests * move "battle:fainted" into `koPlayerPokemon` * add retries to quick-draw tests * fix lost-at-sea-encounter tests * clean up battle animation logic * Update and rename mystery-event.yml to mystery-events.yml * Update mystery-events.yml * Fix typo * Update mystery-events.yml Fix debug runs * clean up unit tests and utils * attach github issues to all encounter jsdocs * start dialogue refactor * update sleeping snorlax encounter * migrate encounters dialogue to new format * cleanup and add jsdocs * finish fiery fallout encounter * fix unit test breaks * add skeleton tests to fiery fallout * commit latest test changes * finish unit tests for fiery fallout * bug fix for empty modifier shop * stash working changes * stash changes * Update src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Update src/test/utils/overridesHelper.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Update src/test/utils/overridesHelper.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Update src/test/utils/overridesHelper.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Update src/test/utils/overridesHelper.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Update src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Update src/data/battle-anims.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * nit updates and cleanup * Update src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * add jsdocs and more cleanup * add more jsdoc * add the strong stuff encounter * add the strong stuff encounter and more unit tests * cleanup container length checks in ME ui * add retries to tests * add retries to tests * fix trainer wave disable override * add shuckle juice modifier * add dialogue bug fixes * add dialogue bug fixes * add pokemon salesman encounter and affects pokedex UI display * add unit tests for pokemon salesman * temp stash * add offer you can't refuse * add unit tests for offer you can't refuse encounter * remove unnecessary prompt handlers * add tests for disabled encounter options * add delibird-y encounter * add delibird-y encounter * add absolute avarice encounter * finish absolute avarice encounter * add unit tests and enhancements for item overrides in tests * fix unit test * cleanup absolute avarice PR * small bug fixes with latest sync from main * update visuals loading for safari and stat trainer visuals * update visuals loading for safari and stat trainer visuals * update a trainer's test encounter and add unit tests * add Trash to Treasure encounter * clean up trash to treasure encounter * clean up trash to treasure encounter * add berries abound encounter * start clowning around encounter * first implementation pass at clowning around * add unit tests for clowning around * add unit tests for clowning around * clean up ME unit tests * clean up unit tests * update unit tests * add part timer and dancing lessons encounters * add unit tests for Dancing Lessons and Part-Timer * reordered biome list and adjusted redirection for project and labels * Add Weird Dream encounter and slight reworks to Berries Abound/Fight or Flight * adjusting yml to match new labels * fix yml whoopsie * Expanded 'Weird Dream' banlist and fixed a bug with the BST bump range * adds Winstrate Challenge mystery encounter * small cleanup for winstrates * add unit tests for Winstrate Challenge * fix pokemon not returning after winstrate battle * commit latest beta merge updates * fix ME null checks and unit tests with beta update * fix ME null checks and unit tests with beta update * MEs to pokerogue beta branch * test dialogue changes * test patch fix * test patch fix * test patch fix * adds teleporting hijinks encounter * add unit tests for Teleporting Hijinks * small change to teleporting hijinks dialogue * migrate ME translations to json * add retries to berries-abound.Option1: should reward the player with X berries based on wave * add missing ME dialogue back in * revert template changes * add ME unique trainer dialogue to both dialogue jsons * fix hanging comma in json * fix broken imports * resolve lint issues * fix flaky test * balance tweaks to a few MEs, updates to bug superfan * add unit tests for Bug-Type Superfan and clean up dialogue * Adds Fun and Games mystery encounter * add unit tests for Fun and Games encounter * update jsdoc * small ME balance changes * small ME balance changes * Adds Uncommon Breed ME and misc. ME bug fixes * Update getFinalSessionData() to collect Mystery Encounter data * adds GTS encounter * various ME bug fixes and balance changes * latest ME bug fixes * clean up GTS Encounter and add unit tests * small cleanup to MEs branch * add BGM music names for ME music * bug fixes and balance changes for MEs * ME data schema updates * balance changes and bug fixes to MEs * balance changes and bug fixes to MEs * update tests for MEs * add jsdoc to party exp function * dialogue updates and test fixes for MEs * dialogue updates and test fixes for MEs * PR suggestions and fixees * stash PR feedback and bugfixes * fix all tests for MEs and cleanup * PR feedback * update flaky ME test * update tests, bug fix MEs, and sprite assets * remove unintentional console log * re-enable stubbed function for Phaser text styling * handle undefined introVisuals properly * PR feedback from NightKev * disable Uncommon Breed tests * locales updates and bug fixes for safari zone * more PR feedback and update field trip with Rarer Candy * fix unit test * Change how reroll button gets disabled in Modifier Shop Phase * update continue button text logic * Update src/ui/modifier-select-ui-handler.ts Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> * fix money formatting and some nits * more nits * more nits * update ME tsdocs with links * update ME tsdocs with links --------- Co-authored-by: Felix Staud <felix.staud@headwire.com> Co-authored-by: flx-sta <50131232+flx-sta@users.noreply.github.com> Co-authored-by: ImperialSympathizer <imperialsympathizer@gmail.com> Co-authored-by: InnocentGameDev <asdargmng@gmail.com> Co-authored-by: Mumble <171087428+frutescens@users.noreply.github.com>
218 lines
7.3 KiB
TypeScript
218 lines
7.3 KiB
TypeScript
import BattleScene from "../battle-scene";
|
|
import AwaitableUiHandler from "./awaitable-ui-handler";
|
|
import { Mode } from "./ui";
|
|
import * as Utils from "../utils";
|
|
|
|
export default abstract class MessageUiHandler extends AwaitableUiHandler {
|
|
protected textTimer: Phaser.Time.TimerEvent | null;
|
|
protected textCallbackTimer: Phaser.Time.TimerEvent | null;
|
|
public pendingPrompt: boolean;
|
|
|
|
public message: Phaser.GameObjects.Text;
|
|
public prompt: Phaser.GameObjects.Sprite;
|
|
|
|
constructor(scene: BattleScene, mode: Mode | null = null) {
|
|
super(scene, mode);
|
|
|
|
this.pendingPrompt = false;
|
|
}
|
|
|
|
showText(text: string, delay?: integer | null, callback?: Function | null, callbackDelay?: integer | null, prompt?: boolean | null, promptDelay?: integer | null) {
|
|
this.showTextInternal(text, delay, callback, callbackDelay, prompt, promptDelay);
|
|
}
|
|
|
|
showDialogue(text: string, name?: string, delay?: integer | null, callback?: Function | null, callbackDelay?: integer | null, prompt?: boolean | null, promptDelay?: integer | null) {
|
|
this.showTextInternal(text, delay, callback, callbackDelay, prompt, promptDelay);
|
|
}
|
|
|
|
private showTextInternal(text: string, delay?: integer | null, callback?: Function | null, callbackDelay?: integer | null, prompt?: boolean | null, promptDelay?: integer | null) {
|
|
if (delay === null || delay === undefined) {
|
|
delay = 20;
|
|
}
|
|
|
|
// Pattern matching regex that checks for @c{}, @f{}, @s{}, and @f{} patterns within message text and parses them to their respective behaviors.
|
|
const charVarMap = new Map<integer, string>();
|
|
const delayMap = new Map<integer, integer>();
|
|
const soundMap = new Map<integer, string>();
|
|
const fadeMap = new Map<integer, integer>();
|
|
const actionPattern = /@(c|d|s|f)\{(.*?)\}/;
|
|
let actionMatch: RegExpExecArray | null;
|
|
while ((actionMatch = actionPattern.exec(text))) {
|
|
switch (actionMatch[1]) {
|
|
case "c":
|
|
charVarMap.set(actionMatch.index, actionMatch[2]);
|
|
break;
|
|
case "d":
|
|
delayMap.set(actionMatch.index, parseInt(actionMatch[2]));
|
|
break;
|
|
case "s":
|
|
soundMap.set(actionMatch.index, actionMatch[2]);
|
|
break;
|
|
case "f":
|
|
fadeMap.set(actionMatch.index, parseInt(actionMatch[2]));
|
|
break;
|
|
}
|
|
text = text.slice(0, actionMatch.index) + text.slice(actionMatch.index + actionMatch[2].length + 4);
|
|
}
|
|
|
|
if (text) {
|
|
// Predetermine overflow line breaks to avoid words breaking while displaying
|
|
const textWords = text.split(" ");
|
|
let lastLineCount = 1;
|
|
let newText = "";
|
|
for (let w = 0; w < textWords.length; w++) {
|
|
const nextWordText = newText ? `${newText} ${textWords[w]}` : textWords[w];
|
|
|
|
if (textWords[w].includes("\n")) {
|
|
newText = nextWordText;
|
|
lastLineCount++;
|
|
} else {
|
|
const lineCount = this.message.runWordWrap(nextWordText).split(/\n/g).length;
|
|
if (lineCount > lastLineCount) {
|
|
lastLineCount = lineCount;
|
|
newText = `${newText}\n${textWords[w]}`;
|
|
} else {
|
|
newText = nextWordText;
|
|
}
|
|
}
|
|
}
|
|
|
|
text = newText;
|
|
}
|
|
|
|
if (this.textTimer) {
|
|
this.textTimer.remove();
|
|
if (this.textCallbackTimer) {
|
|
this.textCallbackTimer.callback();
|
|
}
|
|
}
|
|
if (prompt) {
|
|
const originalCallback = callback;
|
|
callback = () => {
|
|
const showPrompt = () => this.showPrompt(originalCallback, callbackDelay);
|
|
if (promptDelay) {
|
|
this.scene.time.delayedCall(promptDelay, showPrompt);
|
|
} else {
|
|
showPrompt();
|
|
}
|
|
};
|
|
}
|
|
if (delay) {
|
|
this.clearText();
|
|
if (prompt) {
|
|
this.pendingPrompt = true;
|
|
}
|
|
this.textTimer = this.scene.time.addEvent({
|
|
delay: delay,
|
|
callback: () => {
|
|
const charIndex = text.length - (this.textTimer?.repeatCount!); // TODO: is this bang correct?
|
|
const charVar = charVarMap.get(charIndex);
|
|
const charSound = soundMap.get(charIndex);
|
|
const charDelay = delayMap.get(charIndex);
|
|
const charFade = fadeMap.get(charIndex);
|
|
this.message.setText(text.slice(0, charIndex));
|
|
const advance = () => {
|
|
if (charVar) {
|
|
this.scene.charSprite.setVariant(charVar);
|
|
}
|
|
if (charSound) {
|
|
this.scene.playSound(charSound);
|
|
}
|
|
if (callback && !this.textTimer?.repeatCount) {
|
|
if (callbackDelay && !prompt) {
|
|
this.textCallbackTimer = this.scene.time.delayedCall(callbackDelay, () => {
|
|
if (this.textCallbackTimer) {
|
|
this.textCallbackTimer.destroy();
|
|
this.textCallbackTimer = null;
|
|
}
|
|
callback();
|
|
});
|
|
} else {
|
|
callback();
|
|
}
|
|
}
|
|
};
|
|
if (charDelay) {
|
|
this.textTimer!.paused = true; // TODO: is the bang correct?
|
|
this.scene.tweens.addCounter({
|
|
duration: Utils.getFrameMs(charDelay),
|
|
onComplete: () => {
|
|
this.textTimer!.paused = false; // TODO: is the bang correct?
|
|
advance();
|
|
}
|
|
});
|
|
} else if (charFade) {
|
|
this.textTimer!.paused = true;
|
|
this.scene.time.delayedCall(150, () => {
|
|
this.scene.ui.fadeOut(750).then(() => {
|
|
const delay = Utils.getFrameMs(charFade);
|
|
this.scene.time.delayedCall(delay, () => {
|
|
this.scene.ui.fadeIn(500).then(() => {
|
|
this.textTimer!.paused = false;
|
|
advance();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
} else {
|
|
advance();
|
|
}
|
|
},
|
|
repeat: text.length
|
|
});
|
|
} else {
|
|
this.message.setText(text);
|
|
if (prompt) {
|
|
this.pendingPrompt = true;
|
|
}
|
|
if (callback) {
|
|
callback();
|
|
}
|
|
}
|
|
}
|
|
|
|
showPrompt(callback?: Function | null, callbackDelay?: integer | null) {
|
|
const wrappedTextLines = this.message.runWordWrap(this.message.text).split(/\n/g);
|
|
const textLinesCount = wrappedTextLines.length;
|
|
const lastTextLine = wrappedTextLines[wrappedTextLines.length - 1];
|
|
const lastLineTest = this.scene.add.text(0, 0, lastTextLine, { font: "96px emerald" });
|
|
lastLineTest.setScale(this.message.scale);
|
|
const lastLineWidth = lastLineTest.displayWidth;
|
|
lastLineTest.destroy();
|
|
if (this.prompt) {
|
|
this.prompt.setPosition(lastLineWidth + 2, (textLinesCount - 1) * 18 + 2);
|
|
this.prompt.play("prompt");
|
|
}
|
|
this.pendingPrompt = false;
|
|
this.awaitingActionInput = true;
|
|
this.onActionInput = () => {
|
|
if (this.prompt) {
|
|
this.prompt.anims.stop();
|
|
this.prompt.setVisible(false);
|
|
}
|
|
if (callback) {
|
|
if (callbackDelay) {
|
|
this.textCallbackTimer = this.scene.time.delayedCall(callbackDelay, () => {
|
|
if (this.textCallbackTimer) {
|
|
this.textCallbackTimer.destroy();
|
|
this.textCallbackTimer = null;
|
|
}
|
|
callback();
|
|
});
|
|
} else {
|
|
callback();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
clearText() {
|
|
this.message.setText("");
|
|
this.pendingPrompt = false;
|
|
}
|
|
|
|
clear() {
|
|
super.clear();
|
|
}
|
|
}
|