import { DrawPile } from "./drawpile.ts"; import { CheckData, CheckDataOption, ChoiceOption } from "./newmap.ts"; import { getPartLocation, withCamera } from "./layout.ts"; import { AlignX, AlignY, Point, Rect, Size } from "./engine/datatypes.ts"; import { D } from "./engine/public.ts"; import { addButton } from "./button.ts"; import { getSkills } from "./skills.ts"; import { getPlayerProgress } from "./playerprogress.ts"; import { C } from "./colors.ts"; export class CheckModal { #drawpile: DrawPile; #activeCheck: CheckData | null; #callback: (() => void) | null; #success: string | null; constructor() { this.#drawpile = new DrawPile(); this.#activeCheck = null; this.#callback = null; this.#success = null; } get isShown() { return this.#activeCheck != null; } get #size(): Size { return getPartLocation("BottomModal").size; } update() { withCamera("BottomModal", () => this.#update()); this.#drawpile.executeOnClick(); } draw() { withCamera("BottomModal", () => this.#draw()); } show(checkData: CheckData | null, callback: (() => void) | null) { this.#activeCheck = checkData; this.#callback = callback; this.#success = null; } #update() { this.#drawpile.clear(); let check = this.#activeCheck; if (!check) { return; } let size = this.#size; this.#drawpile.add(0, () => { D.fillRect(new Point(-4, -4), size.add(new Size(8, 8)), C.BG_UI); }); let success = this.#success; if (success) { this.#drawpile.add(0, () => { D.drawText( success, new Point(size.w / 2, (size.h - 64) / 2), C.FG_BOLD, { forceWidth: size.w, alignX: AlignX.Center, alignY: AlignY.Middle, }, ); }); addButton( this.#drawpile, "OK!", new Rect(new Point(0, size.h - 64), new Size(size.w, 64)), true, () => { this.show(null, null); }, ); return; } let labelText = check.label; this.#drawpile.add(0, () => { D.drawText( labelText, new Point(size.w / 2, (size.h - 64) / 2), C.FG_BOLD, { forceWidth: size.w, alignX: AlignX.Center, alignY: AlignY.Middle, }, ); }); let options = check.options; let addOptionButton = ( option: CheckDataOption | ChoiceOption, rect: Rect, ) => { let accomplished: boolean; let optionLabel: string; let resultMessage: string | null; let endorse = false; if ((option as ChoiceOption).isChoice) { // TODO: Use OOP here option = option as ChoiceOption; accomplished = option.countsAsSuccess; optionLabel = option.unlockable; resultMessage = option.success; } else { option = option as CheckDataOption; let skill = option.skill(); let skillName = getSkills().get(skill).profile.name; let hasSkill = getPlayerProgress().hasLearned(skill); // hasSkill ||= true; if (hasSkill) { optionLabel = `[${skillName}] ${option.unlockable}`; endorse = true; } else { optionLabel = `[Needs ${skillName}] ${option.locked}`; } resultMessage = hasSkill ? option.success : option.failure; accomplished = hasSkill; } addButton( this.#drawpile, optionLabel, rect, true, () => { this.#success = resultMessage; if (accomplished) { let cb = this.#callback; if (cb) { cb(); } } if (resultMessage == null) { this.show(null, null); } }, { endorse }, ); }; if (options.length == 0) { addButton( this.#drawpile, "OK!", new Rect(new Point(0, size.h - 64), new Size(size.w, 64)), true, () => { this.show(null, null); }, ); } else if (options.length == 1) { addOptionButton( options[0], new Rect(new Point(0, size.h - 64), new Size(size.w, 64)), ); } else if (options.length == 2) { addOptionButton( options[0], new Rect(new Point(0, size.h - 64), new Size(size.w, 32)), ); addOptionButton( options[1], new Rect(new Point(0, size.h - 32), new Size(size.w, 32)), ); } else { throw new Error(`unexpected number of options ${options.length}`); } } #draw() { this.#drawpile.draw(); } } let active: CheckModal = new CheckModal(); export function getCheckModal() { return active; }