mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-10-20 12:05:50 +02:00
* TS: enable strict-null * fix battle-scene.ts * fix voucher.ts * adapt more files to strict-null * adapt more files to strict-null ( 2) * adapt ability.ts to strict-null * adapt `arena.ts` to strict-null * adapt TagAddedEvent constructor to strict-null * adapt phases.ts.to strict-null * adapt status-effect.ts to strict-null * adapt `account.ts` to strict-null * adapt `configHandler.ts` to strict-null * adapt `ability.ts` to strict-null * adapt `biomes.ts` to strict-null * adapt `challenge.ts` to strict-null * adapt `daily-run.ts` to strict-null * adapt `nature.ts` to strict-null * adapt `pokemon-forms.ts` to strict-null * adapt `tainer-names.ts` to strict-null * adapt `types.ts` to strict-null * adapt `weather.ts` to strict-null * adapt `egg-hatch-phase.ts` to strict-null * adapt `evolution-phase.ts` to strict-null * adapt `pokemon-sprite-sparkle-handler.ts` to strict-null * adapt `evolution-phase.ts` to strict-null * adapt `game-mode.ts` to strict-null * adapt `utils.ts` to strict-null * adapt `voucher-ui-handler.ts` to strict-null * adapt `src/ui/unavailable-modal-ui-handler.ts` to strict-null * adapt `src/ui/ui.ts` to strict-null * adapt `src/ui/ui-theme.ts` to strict-null * adapt `src/ui/title-ui-handler.ts` to strict-null * adapt `src/ui/time-of-day-widget.ts` to strict-null * adapt `src/ui/text.ts` to strict-null * adapt `src/ui/target-select-ui-handler.ts` to strict-null * adapt `src/ui/settings/settings-keyboard-ui-handler.ts` to strict-null * adapt more files to strict-null (3) * adapt more files to strict-null (4) * adapt more files (mostly tests) to strict-null (5) * adapt more files to strict-null (6) * adapt more files to strict-null (7) * Update `src/data/pokemon-evolutions.ts` for strict-null Partial update `src/data/pokemon-species.ts` for strict-null * adapt more files to strict-null (8) * adapt more files to strict-null (9) * Strict some more nulls (still a few errors remaining) * adapt rest of the files to strict-null (9) * fix tests (check for null instead of undefined) * repalce a lot of `??` with bangs And added TODO notice as usual * fix more tests * all tests pass now * fix broken game-loop after trainer battle add some console.warn for missing cases and falling back to default * remove guessed fallback from utils.rgbHexToRgba * add TODO for this.currentBattle = null * adjust getPokemonById() return to include `null` * fix compilation errors * add test for pokemon.trySetStatus * `chanceMultiplier` shouldn't be optional * allow `null` for currentPhase * adjust hasExpSprite logic for no keymatch found * reduce bang usage in account.updateUserInfo() * fix new strict-null issues after merge * fix `strict-null` issues in dropdown.ts and sand_spit.test.ts * fix egg-gacha * adapt gul_missile.test.ts to strict-null * fix move.ts strict-null * fix i18n.ts strict-null * fix strict-null issues * fix baton_pass test after accidentially breaking it * chore: fix compiler errors * revert accidential changes in baton_pass.test.ts --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
198 lines
6.5 KiB
TypeScript
198 lines
6.5 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) {
|
|
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;
|
|
}
|
|
const charVarMap = new Map<integer, string>();
|
|
const delayMap = new Map<integer, integer>();
|
|
const soundMap = new Map<integer, string>();
|
|
const actionPattern = /@(c|d|s)\{(.*?)\}/;
|
|
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;
|
|
}
|
|
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);
|
|
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 {
|
|
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();
|
|
}
|
|
}
|