mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-03-09 11:31:49 +00:00
* Changing only achvs-ui-handler for now * Add ACTION sprite --------- Co-authored-by: frutescens <info@laptop> Co-authored-by: chaosgrimmon <31082757+chaosgrimmon@users.noreply.github.com>
424 lines
15 KiB
TypeScript
424 lines
15 KiB
TypeScript
import BattleScene from "../battle-scene";
|
|
import { Button } from "#enums/buttons";
|
|
import i18next from "i18next";
|
|
import { Achv, achvs, getAchievementDescription } from "../system/achv";
|
|
import { Voucher, getVoucherTypeIcon, getVoucherTypeName, vouchers } from "../system/voucher";
|
|
import MessageUiHandler from "./message-ui-handler";
|
|
import { addTextObject, TextStyle } from "./text";
|
|
import { Mode } from "./ui";
|
|
import { addWindow } from "./ui-theme";
|
|
import { PlayerGender } from "#enums/player-gender";
|
|
|
|
enum Page {
|
|
ACHIEVEMENTS,
|
|
VOUCHERS
|
|
}
|
|
|
|
interface LanguageSetting {
|
|
TextSize: string,
|
|
}
|
|
|
|
const languageSettings: { [key: string]: LanguageSetting } = {
|
|
"de":{
|
|
TextSize: "80px"
|
|
}
|
|
};
|
|
|
|
export default class AchvsUiHandler extends MessageUiHandler {
|
|
private readonly ROWS = 4;
|
|
private readonly COLS = 17;
|
|
|
|
private mainContainer: Phaser.GameObjects.Container;
|
|
private iconsContainer: Phaser.GameObjects.Container;
|
|
|
|
private headerBg: Phaser.GameObjects.NineSlice;
|
|
private headerText: Phaser.GameObjects.Text;
|
|
private headerActionText: Phaser.GameObjects.Text;
|
|
private headerActionButton: Phaser.GameObjects.Sprite;
|
|
private headerBgX: number;
|
|
private iconsBg: Phaser.GameObjects.NineSlice;
|
|
private icons: Phaser.GameObjects.Sprite[];
|
|
|
|
private titleText: Phaser.GameObjects.Text;
|
|
private scoreText: Phaser.GameObjects.Text;
|
|
private unlockText: Phaser.GameObjects.Text;
|
|
|
|
private achvsName: string;
|
|
private achvsTotal: number;
|
|
private vouchersName: string;
|
|
private vouchersTotal: number;
|
|
private currentTotal: number;
|
|
|
|
private scrollCursor: number;
|
|
private cursorObj: Phaser.GameObjects.NineSlice | null;
|
|
private currentPage: Page;
|
|
|
|
constructor(scene: BattleScene, mode: Mode | null = null) {
|
|
super(scene, mode);
|
|
|
|
this.achvsTotal = Object.keys(achvs).length;
|
|
this.vouchersTotal = Object.keys(vouchers).length;
|
|
this.scrollCursor = 0;
|
|
}
|
|
|
|
setup() {
|
|
const ui = this.getUi();
|
|
|
|
this.mainContainer = this.scene.add.container(1, -(this.scene.game.canvas.height / 6) + 1);
|
|
|
|
this.mainContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6), Phaser.Geom.Rectangle.Contains);
|
|
|
|
this.headerBg = addWindow(this.scene, 0, 0, (this.scene.game.canvas.width / 6) - 2, 24);
|
|
this.headerBg.setOrigin(0, 0);
|
|
|
|
this.headerText = addTextObject(this.scene, 0, 0, "", TextStyle.SETTINGS_LABEL);
|
|
this.headerText.setOrigin(0, 0);
|
|
this.headerText.setPositionRelative(this.headerBg, 8, 4);
|
|
this.headerActionButton = new Phaser.GameObjects.Sprite(this.scene, 0, 0, "keyboard", "ACTION.png");
|
|
this.headerActionButton.setOrigin(0, 0);
|
|
this.headerActionButton.setPositionRelative(this.headerBg, 236, 6);
|
|
this.headerActionText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW, {fontSize:"60px"});
|
|
this.headerActionText.setOrigin(0, 0);
|
|
this.headerActionText.setPositionRelative(this.headerBg, 264, 8);
|
|
|
|
// We need to get the player gender from the game data to add the correct prefix to the achievement name
|
|
const genderIndex = this.scene.gameData.gender ?? PlayerGender.MALE;
|
|
const genderStr = PlayerGender[genderIndex].toLowerCase();
|
|
|
|
this.achvsName = i18next.t("achv:Achievements.name", { context: genderStr });
|
|
this.vouchersName = i18next.t("voucher:vouchers");
|
|
|
|
this.iconsBg = addWindow(this.scene, 0, this.headerBg.height, (this.scene.game.canvas.width / 6) - 2, (this.scene.game.canvas.height / 6) - this.headerBg.height - 68);
|
|
this.iconsBg.setOrigin(0, 0);
|
|
|
|
this.iconsContainer = this.scene.add.container(6, this.headerBg.height + 6);
|
|
|
|
this.icons = [];
|
|
|
|
for (let a = 0; a < this.ROWS * this.COLS; a++) {
|
|
const x = (a % this.COLS) * 18;
|
|
const y = Math.floor(a / this.COLS) * 18;
|
|
|
|
const icon = this.scene.add.sprite(x, y, "items", "unknown");
|
|
icon.setOrigin(0, 0);
|
|
icon.setScale(0.5);
|
|
|
|
this.icons.push(icon);
|
|
this.iconsContainer.add(icon);
|
|
}
|
|
|
|
const titleBg = addWindow(this.scene, 0, this.headerBg.height + this.iconsBg.height, 174, 24);
|
|
titleBg.setOrigin(0, 0);
|
|
|
|
this.titleText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW);
|
|
const textSize = languageSettings[i18next.language]?.TextSize ?? this.titleText.style.fontSize;
|
|
this.titleText.setFontSize(textSize);
|
|
this.titleText.setOrigin(0, 0);
|
|
const titleBgCenterX = titleBg.x + titleBg.width / 2;
|
|
const titleBgCenterY = titleBg.y + titleBg.height / 2;
|
|
this.titleText.setOrigin(0.5, 0.5);
|
|
this.titleText.setPosition(titleBgCenterX, titleBgCenterY);
|
|
|
|
const scoreBg = addWindow(this.scene, titleBg.x + titleBg.width, titleBg.y, 46, 24);
|
|
scoreBg.setOrigin(0, 0);
|
|
|
|
this.scoreText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW);
|
|
this.scoreText.setOrigin(0, 0);
|
|
this.scoreText.setPositionRelative(scoreBg, 8, 4);
|
|
|
|
const unlockBg = addWindow(this.scene, scoreBg.x + scoreBg.width, scoreBg.y, 98, 24);
|
|
unlockBg.setOrigin(0, 0);
|
|
|
|
this.unlockText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW);
|
|
this.unlockText.setOrigin(0, 0);
|
|
this.unlockText.setPositionRelative(unlockBg, 8, 4);
|
|
|
|
const descriptionBg = addWindow(this.scene, 0, titleBg.y + titleBg.height, (this.scene.game.canvas.width / 6) - 2, 42);
|
|
descriptionBg.setOrigin(0, 0);
|
|
|
|
const descriptionText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW, { maxLines: 2 });
|
|
descriptionText.setWordWrapWidth(1870);
|
|
descriptionText.setOrigin(0, 0);
|
|
descriptionText.setPositionRelative(descriptionBg, 8, 4);
|
|
|
|
this.message = descriptionText;
|
|
|
|
this.mainContainer.add(this.headerBg);
|
|
this.mainContainer.add(this.headerActionButton);
|
|
this.mainContainer.add(this.headerText);
|
|
this.mainContainer.add(this.headerActionText);
|
|
this.mainContainer.add(this.iconsBg);
|
|
this.mainContainer.add(this.iconsContainer);
|
|
this.mainContainer.add(titleBg);
|
|
this.mainContainer.add(this.titleText);
|
|
this.mainContainer.add(scoreBg);
|
|
this.mainContainer.add(this.scoreText);
|
|
this.mainContainer.add(unlockBg);
|
|
this.mainContainer.add(this.unlockText);
|
|
this.mainContainer.add(descriptionBg);
|
|
this.mainContainer.add(descriptionText);
|
|
|
|
ui.add(this.mainContainer);
|
|
|
|
this.currentPage = Page.ACHIEVEMENTS;
|
|
this.setCursor(0);
|
|
|
|
this.mainContainer.setVisible(false);
|
|
}
|
|
|
|
show(args: any[]): boolean {
|
|
super.show(args);
|
|
|
|
this.headerBgX = this.headerBg.getTopRight().x;
|
|
this.updateAchvIcons();
|
|
|
|
this.mainContainer.setVisible(true);
|
|
this.setCursor(0);
|
|
this.setScrollCursor(0);
|
|
|
|
this.getUi().moveTo(this.mainContainer, this.getUi().length - 1);
|
|
|
|
this.getUi().hideTooltip();
|
|
|
|
return true;
|
|
}
|
|
|
|
protected showAchv(achv: Achv) {
|
|
// We need to get the player gender from the game data to add the correct prefix to the achievement name
|
|
const genderIndex = this.scene.gameData.gender ?? PlayerGender.MALE;
|
|
const genderStr = PlayerGender[genderIndex].toLowerCase();
|
|
|
|
achv.name = i18next.t(`achv:${achv.localizationKey}.name`, { context: genderStr });
|
|
achv.description = getAchievementDescription(achv.localizationKey);
|
|
const achvUnlocks = this.scene.gameData.achvUnlocks;
|
|
const unlocked = achvUnlocks.hasOwnProperty(achv.id);
|
|
const hidden = !unlocked && achv.secret && (!achv.parentId || !achvUnlocks.hasOwnProperty(achv.parentId));
|
|
this.titleText.setText(unlocked ? achv.name : "???");
|
|
this.showText(!hidden ? achv.description : "");
|
|
this.scoreText.setText(`${achv.score}pt`);
|
|
this.unlockText.setText(unlocked ? new Date(achvUnlocks[achv.id]).toLocaleDateString() : i18next.t("achv:Locked.name"));
|
|
}
|
|
|
|
protected showVoucher(voucher: Voucher) {
|
|
const voucherUnlocks = this.scene.gameData.voucherUnlocks;
|
|
const unlocked = voucherUnlocks.hasOwnProperty(voucher.id);
|
|
|
|
this.titleText.setText(getVoucherTypeName(voucher.voucherType));
|
|
this.showText(voucher.description);
|
|
this.unlockText.setText(unlocked ? new Date(voucherUnlocks[voucher.id]).toLocaleDateString() : i18next.t("voucher:locked"));
|
|
}
|
|
|
|
processInput(button: Button): boolean {
|
|
const ui = this.getUi();
|
|
|
|
let success = false;
|
|
|
|
if (button === Button.ACTION) {
|
|
success = true;
|
|
this.setScrollCursor(0);
|
|
if (this.currentPage === Page.ACHIEVEMENTS) {
|
|
this.currentPage = Page.VOUCHERS;
|
|
this.updateVoucherIcons();
|
|
} else if (this.currentPage === Page.VOUCHERS) {
|
|
this.currentPage = Page.ACHIEVEMENTS;
|
|
this.updateAchvIcons();
|
|
}
|
|
this.setCursor(0, true);
|
|
this.mainContainer.update();
|
|
}
|
|
if (button === Button.CANCEL) {
|
|
success = true;
|
|
this.scene.ui.revertMode();
|
|
} else {
|
|
const rowIndex = Math.floor(this.cursor / this.COLS);
|
|
const itemOffset = (this.scrollCursor * this.COLS);
|
|
switch (button) {
|
|
case Button.UP:
|
|
if (this.cursor < this.COLS) {
|
|
if (this.scrollCursor) {
|
|
success = this.setScrollCursor(this.scrollCursor - 1);
|
|
}
|
|
} else {
|
|
success = this.setCursor(this.cursor - this.COLS);
|
|
}
|
|
break;
|
|
case Button.DOWN:
|
|
const canMoveDown = (this.cursor + itemOffset) + this.COLS < this.currentTotal;
|
|
if (rowIndex >= this.ROWS - 1) {
|
|
if (this.scrollCursor < Math.ceil(this.currentTotal / this.COLS) - this.ROWS && canMoveDown) {
|
|
success = this.setScrollCursor(this.scrollCursor + 1);
|
|
}
|
|
} else if (canMoveDown) {
|
|
success = this.setCursor(this.cursor + this.COLS);
|
|
}
|
|
break;
|
|
case Button.LEFT:
|
|
if (!this.cursor && this.scrollCursor) {
|
|
success = this.setScrollCursor(this.scrollCursor - 1) && this.setCursor(this.cursor + (this.COLS - 1));
|
|
} else if (this.cursor) {
|
|
success = this.setCursor(this.cursor - 1);
|
|
}
|
|
break;
|
|
case Button.RIGHT:
|
|
if (this.cursor + 1 === this.ROWS * this.COLS && this.scrollCursor < Math.ceil(this.currentTotal / this.COLS) - this.ROWS) {
|
|
success = this.setScrollCursor(this.scrollCursor + 1) && this.setCursor(this.cursor - (this.COLS - 1));
|
|
} else if (this.cursor + itemOffset < this.currentTotal - 1) {
|
|
success = this.setCursor(this.cursor + 1);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (success) {
|
|
ui.playSelect();
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
setCursor(cursor: integer, pageChange?: boolean): boolean {
|
|
const ret = super.setCursor(cursor);
|
|
|
|
let update = ret;
|
|
|
|
if (!this.cursorObj) {
|
|
this.cursorObj = this.scene.add.nineslice(0, 0, "select_cursor_highlight", undefined, 16, 16, 1, 1, 1, 1);
|
|
this.cursorObj.setOrigin(0, 0);
|
|
this.iconsContainer.add(this.cursorObj);
|
|
update = true;
|
|
}
|
|
|
|
this.cursorObj.setPositionRelative(this.icons[this.cursor], 0, 0);
|
|
|
|
if (update || pageChange) {
|
|
switch (this.currentPage) {
|
|
case Page.ACHIEVEMENTS:
|
|
this.showAchv(achvs[Object.keys(achvs)[cursor + this.scrollCursor * this.COLS]]);
|
|
break;
|
|
case Page.VOUCHERS:
|
|
this.showVoucher(vouchers[Object.keys(vouchers)[cursor + this.scrollCursor * this.COLS]]);
|
|
break;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* setScrollCursor(scrollCursor: integer) : boolean
|
|
* scrollCursor refers to the page's position within the entire sum of the data, unlike cursor, which refers to a user's position within displayed data
|
|
* @param takes a scrollCursor that has been updated based on user behavior
|
|
* @returns returns a boolean that indicates whether the updated scrollCursor led to an update in the data displayed.
|
|
*/
|
|
setScrollCursor(scrollCursor: integer): boolean {
|
|
if (scrollCursor === this.scrollCursor) {
|
|
return false;
|
|
}
|
|
|
|
this.scrollCursor = scrollCursor;
|
|
|
|
switch (this.currentPage) {
|
|
case Page.ACHIEVEMENTS:
|
|
this.updateAchvIcons();
|
|
this.showAchv(achvs[Object.keys(achvs)[Math.min(this.cursor + this.scrollCursor * this.COLS, Object.values(achvs).length - 1)]]);
|
|
break;
|
|
case Page.VOUCHERS:
|
|
this.updateVoucherIcons();
|
|
this.showVoucher(vouchers[Object.keys(vouchers)[Math.min(this.cursor + this.scrollCursor * this.COLS, Object.values(vouchers).length - 1)]]);
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* updateAchvIcons(): void
|
|
* Determines what data is to be displayed on the UI and updates it accordingly based on the current value of this.scrollCursor
|
|
*/
|
|
updateAchvIcons(): void {
|
|
this.headerText.text = this.achvsName;
|
|
this.headerActionText.text = this.vouchersName;
|
|
const textPosition = this.headerBgX - this.headerActionText.displayWidth - 8;
|
|
this.headerActionText.setX(textPosition);
|
|
this.headerActionButton.setX(textPosition - this.headerActionButton.displayWidth - 4);
|
|
|
|
const achvUnlocks = this.scene.gameData.achvUnlocks;
|
|
|
|
const itemOffset = this.scrollCursor * this.COLS;
|
|
const itemLimit = this.ROWS * this.COLS;
|
|
|
|
const achvRange = Object.values(achvs).slice(itemOffset, itemLimit + itemOffset);
|
|
|
|
achvRange.forEach((achv: Achv, i: integer) => {
|
|
const icon = this.icons[i];
|
|
const unlocked = achvUnlocks.hasOwnProperty(achv.id);
|
|
const hidden = !unlocked && achv.secret && (!achv.parentId || !achvUnlocks.hasOwnProperty(achv.parentId));
|
|
const tinted = !hidden && !unlocked;
|
|
|
|
icon.setFrame(!hidden ? achv.iconImage : "unknown");
|
|
icon.setVisible(true);
|
|
if (tinted) {
|
|
icon.setTintFill(0);
|
|
} else {
|
|
icon.clearTint();
|
|
}
|
|
});
|
|
|
|
if (achvRange.length < this.icons.length) {
|
|
this.icons.slice(achvRange.length).map(i => i.setVisible(false));
|
|
}
|
|
|
|
this.currentTotal = this.achvsTotal;
|
|
}
|
|
|
|
/**
|
|
* updateVoucherIcons(): void
|
|
* Determines what data is to be displayed on the UI and updates it accordingly based on the current value of this.scrollCursor
|
|
*/
|
|
updateVoucherIcons(): void {
|
|
this.headerText.text = this.vouchersName;
|
|
this.headerActionText.text = this.achvsName;
|
|
const textPosition = this.headerBgX - this.headerActionText.displayWidth - 8;
|
|
this.headerActionText.setX(textPosition);
|
|
this.headerActionButton.setX(textPosition - this.headerActionButton.displayWidth - 4);
|
|
|
|
const voucherUnlocks = this.scene.gameData.voucherUnlocks;
|
|
|
|
const itemOffset = this.scrollCursor * this.COLS;
|
|
const itemLimit = this.ROWS * this.COLS;
|
|
|
|
const voucherRange = Object.values(vouchers).slice(itemOffset, itemLimit + itemOffset);
|
|
|
|
voucherRange.forEach((voucher: Voucher, i: integer) => {
|
|
const icon = this.icons[i];
|
|
const unlocked = voucherUnlocks.hasOwnProperty(voucher.id);
|
|
|
|
icon.setFrame(getVoucherTypeIcon(voucher.voucherType));
|
|
icon.setVisible(true);
|
|
if (!unlocked) {
|
|
icon.setTintFill(0);
|
|
} else {
|
|
icon.clearTint();
|
|
}
|
|
});
|
|
|
|
if (voucherRange.length < this.icons.length) {
|
|
this.icons.slice(voucherRange.length).map(i => i.setVisible(false));
|
|
}
|
|
this.currentTotal = this.vouchersTotal;
|
|
}
|
|
|
|
clear() {
|
|
super.clear();
|
|
this.currentPage = Page.ACHIEVEMENTS;
|
|
this.mainContainer.setVisible(false);
|
|
this.eraseCursor();
|
|
}
|
|
|
|
eraseCursor() {
|
|
if (this.cursorObj) {
|
|
this.cursorObj.destroy();
|
|
}
|
|
this.cursorObj = null;
|
|
}
|
|
}
|