42 lines
2.6 KiB
TypeScript
42 lines
2.6 KiB
TypeScript
import type { NaniRuntime } from "./nani-runtime";
|
|
|
|
export interface BoardCell { index: number; code: number; area: string; icon: string; title: string; detail: string }
|
|
export class TomieGameplay {
|
|
constructor(private runtime: NaniRuntime, private routes: Record<string, { script: string; label: string }>) {}
|
|
|
|
cells(): BoardCell[] {
|
|
return String(this.runtime.variables.savedBlock ?? "").split("&").filter(Boolean).flatMap((value) => {
|
|
const parts = value.split("@");
|
|
return parts.length < 6 ? [] : [{ index: Number(parts[0]), code: Number(parts[1]), area: parts[2], icon: parts[3], title: parts[4], detail: parts[5] }];
|
|
});
|
|
}
|
|
|
|
roll(type = 0): { ok: boolean; message?: string; roll?: number; destination?: number } {
|
|
const vm = this.runtime, values = vm.variables;
|
|
if (vm.waiting !== "board") return { ok: false, message: "Сначала завершите текущее действие." };
|
|
const cost = type === 2 ? 10 : [3, 4, 5].includes(type) ? 5 : 0;
|
|
if (Number(values.iWillpower ?? 0) < cost) return { ok: false, message: "Недостаточно воли для этого кубика." };
|
|
if (type > 10 && (type > 16 || Number(values.iJoker ?? 0) < 1)) return { ok: false, message: "Нужна одна карта Joker." };
|
|
const rng = vm.evaluator;
|
|
let number: number;
|
|
if (type === 0 || type === 1) {
|
|
number = rng.integer(1, 6);
|
|
if (type === 1 && rng.random() >= 0.6) number = Math.min(6, Math.max(1, Math.trunc(Number(values._godot_dice_slider ?? 0) * 3) + 1));
|
|
} else if (type === 2) number = rng.integer(1, 3);
|
|
else if (type === 3) number = rng.integer(4, 6);
|
|
else if (type === 4) number = rng.integer(1, 3) * 2 - 1;
|
|
else if (type === 5) number = rng.integer(1, 3) * 2;
|
|
else if (type > 10) number = type - 10;
|
|
else return { ok: false, message: "Этот тип кубика не подключён." };
|
|
const cells = this.cells(), destination = Math.min(Number(values.currentPosition ?? 0) + number, cells.length - 1);
|
|
const cell = cells[destination], target = cell && this.routes[String(cell.code)];
|
|
if (!cell || !target || !vm.content.scripts[target.script]) return { ok: false, message: "Неизвестный тип клетки. Позиция и ресурсы сохранены." };
|
|
values.mDiceResult = number; values.currentPosition = destination; values.thisBlockNumber = cell.code;
|
|
values.iWillpower = Number(values.iWillpower ?? 0) - cost;
|
|
if (type > 10) values.iJoker = Number(values.iJoker ?? 0) - 1;
|
|
values.isAppScreen = false;
|
|
vm.runExternal(target.script, target.label);
|
|
return { ok: true, roll: number, destination };
|
|
}
|
|
}
|