mirror of
https://github.com/Shu-Ying/noname-shuying.git
synced 2026-10-21 14:49:59 +08:00
fixed # 重构梦三项目结构
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
import { AFFIX_INFO } from "../cards/affixes.js";
|
||||
import { describeLibraryCard } from "./card-library.js";
|
||||
|
||||
const node = (tag, className, label, parent) => {
|
||||
const element = document.createElement(tag);
|
||||
element.className = className;
|
||||
if (label != null) element.textContent = label;
|
||||
parent?.appendChild(element);
|
||||
return element;
|
||||
};
|
||||
|
||||
const button = (label, parent, action) => {
|
||||
const element = node("button", "ms-deck-button", label, parent);
|
||||
element.type = "button";
|
||||
element.addEventListener("click", action);
|
||||
return element;
|
||||
};
|
||||
|
||||
// Keep the command battle-scoped; further GM actions can be added as panels here.
|
||||
export function mountGMManager(session, owner, piles, battle, resources, game) {
|
||||
let dialog = null, selected = null, previousFocus = null, disposed = false;
|
||||
const available = () => !disposed && session.active && !battle.resolving;
|
||||
const close = () => {
|
||||
if (!dialog) return;
|
||||
const current = dialog;
|
||||
dialog = null;
|
||||
if (current.open) current.close();
|
||||
current.remove();
|
||||
if (previousFocus?.isConnected) previousFocus.focus();
|
||||
previousFocus = null;
|
||||
};
|
||||
const render = () => {
|
||||
if (!dialog) return;
|
||||
const list = dialog.querySelector(".ms-gm-hand");
|
||||
const editor = dialog.querySelector(".ms-gm-editor");
|
||||
list.replaceChildren(); editor.replaceChildren();
|
||||
const hand = owner.getCards("h").filter(card => card.storage?.mengsanCard_shuying);
|
||||
if (!hand.includes(selected)) selected = null;
|
||||
if (!hand.length) node("p", "ms-deck-empty", "当前没有可编辑的梦三手牌。", list);
|
||||
for (const [index, card] of hand.entries()) {
|
||||
const data = card.storage.mengsanCard_shuying;
|
||||
const details = describeLibraryCard({ ...data, name: card.name, suit: card.suit, number: card.number });
|
||||
const label = `${index + 1}. ${details.name} ${details.suit}${details.number}${details.affixes.length ? ` · ${details.affixes.map(value => value.split(":")[0]).join("、")}` : ""}`;
|
||||
const item = button(label, list, () => { selected = card; render(); });
|
||||
item.classList.add("ms-gm-card");
|
||||
item.setAttribute("aria-pressed", String(selected === card));
|
||||
}
|
||||
if (!selected) { node("p", "ms-deck-empty", "选择一张手牌,然后添加词缀。", editor); return; }
|
||||
node("h3", "", `编辑:${describeLibraryCard(selected.storage.mengsanCard_shuying).name}`, editor);
|
||||
const choices = node("div", "ms-gm-affixes", null, editor);
|
||||
for (const [key, info] of Object.entries(AFFIX_INFO)) {
|
||||
const applied = selected.storage.mengsanCard_shuying.affixes.includes(key);
|
||||
const item = button(`${info.name}${applied ? " · 已有" : ""}`, choices, () => {
|
||||
if (!available() || !owner.getCards("h").includes(selected)) { render(); return; }
|
||||
piles.addAffix(selected, key);
|
||||
render();
|
||||
});
|
||||
item.disabled = applied;
|
||||
item.title = info.description;
|
||||
}
|
||||
};
|
||||
const open = () => {
|
||||
if (!available()) return false;
|
||||
if (dialog?.open) { render(); dialog.focus(); return true; }
|
||||
previousFocus = document.activeElement;
|
||||
dialog = node("dialog", "mengsan-deck-dialog-shuying mengsan-gm-dialog-shuying", null);
|
||||
dialog.setAttribute("aria-label", "梦三 GM 管理器");
|
||||
dialog.tabIndex = -1;
|
||||
const header = node("header", "ms-deck-header", null, dialog);
|
||||
node("h2", "ms-deck-title", "GM 管理器", header);
|
||||
button("关闭", header, close);
|
||||
node("p", "ms-deck-summary", "手牌词缀 · 仅本场战斗生效,不改永久牌组或存档。", dialog);
|
||||
button("刷新手牌", dialog, render);
|
||||
node("div", "ms-gm-hand", null, dialog);
|
||||
node("section", "ms-gm-editor", null, dialog);
|
||||
const created = dialog;
|
||||
dialog.addEventListener("close", () => { if (dialog === created) close(); });
|
||||
dialog.addEventListener("keydown", event => event.stopPropagation());
|
||||
document.body.appendChild(dialog);
|
||||
try { dialog.showModal(); } catch (error) { close(); throw error; }
|
||||
render();
|
||||
dialog.querySelector(".ms-deck-header button").focus();
|
||||
return true;
|
||||
};
|
||||
resources.field(globalThis, "mengsanGM_shuying", open);
|
||||
resources.field(game, "mengsanGM_shuying", open);
|
||||
const handle = { dispose: close };
|
||||
session.ownResource(handle, () => { disposed = true; close(); });
|
||||
return handle;
|
||||
}
|
||||
Reference in New Issue
Block a user