改动整体底层系统

This commit is contained in:
2026-09-29 00:29:00 +08:00
parent ced1b28cc2
commit 2e552cf17d
24 changed files with 809 additions and 53 deletions
+43 -4
View File
@@ -13,7 +13,7 @@ export function installPersonalPiles(session, owner, battle, run, resources, env
const draw = document.createElement("div"), discard = document.createElement("div");
// Detached nodes: engine get.position recognises these IDs; no duplicate document IDs.
draw.id = "cardPile"; discard.id = "discardPile";
const owned = new Set(), restores = [];
const owned = new Set(), restores = [], costBadges = new Map();
const strict = env.strict !== false;
let released = false, forcedOwner = false;
const personal = () => {
@@ -27,6 +27,26 @@ export function installPersonalPiles(session, owner, battle, run, resources, env
return false; // Never infer ownership from whose turn it is.
};
const refresh = () => { if (!released) env.refresh(); };
function showCost(card) {
if (!env.showCosts || !card?.name) return;
const cost = String(cardCost(card));
card.dataset.mengsanCost = cost;
let badge = costBadges.get(card);
if (!badge) {
badge = Array.from(card.children || []).find(child => child.classList?.contains("mengsan-hand-cost-shuying"));
if (!badge) {
badge = document.createElement("span");
badge.className = "mengsan-hand-cost-shuying";
badge.setAttribute("aria-hidden", "true");
card.appendChild(badge);
}
costBadges.set(card, badge);
}
// 十周年 UI scans thrown-card children via innerText when adding “刘备使用”.
// Keep this child text-free so its numeric cost cannot match that scan.
badge.textContent = "";
badge.dataset.mengsanCost = cost;
}
function adopt(card, data) {
if (owned.has(card)) return;
owned.add(card); resources.card(card);
@@ -37,9 +57,7 @@ export function installPersonalPiles(session, owner, battle, run, resources, env
// Retired affixes from old saves must not acquire new battle behaviour.
card.storage.mengsanCard_shuying.affixes = (card.storage.mengsanCard_shuying.affixes || []).filter(key => key !== "annihilate");
}
if (data && env.showCosts) {
card.dataset.mengsanCost = String(cardCost(data));
}
if (data) showCost(card);
// Existing foreign/generated cards retain their original destruction semantics.
if (!data) return;
card.destroyLog = false;
@@ -66,6 +84,27 @@ export function installPersonalPiles(session, owner, battle, run, resources, env
const card = game.createCard(data.name, data.suit, data.number, data.nature);
adopt(card, data); draw.appendChild(card);
}
// Native and 十周年 UI both move real card nodes into these hand containers.
// Decorate newly gained cards without patching either UI's card factory or layout.
const handZones = [owner.node?.handcards1, owner.node?.handcards2].filter(Boolean);
const handObserver = new MutationObserver(mutations => {
if (released) return;
for (const mutation of mutations) for (const card of mutation.addedNodes) {
if (card.classList?.contains("card")) showCost(card);
}
});
for (const zone of handZones) {
for (const card of zone.childNodes) if (card.classList?.contains("card")) showCost(card);
handObserver.observe(zone, { childList: true });
}
session.ownResource(handObserver, () => {
handObserver.disconnect();
for (const [card, badge] of costBadges) {
if (badge.parentNode === card) badge.remove();
delete card.dataset.mengsanCost;
}
costBadges.clear();
});
const publicDiscard = ui.discardPile;
for (const [key, node] of [["cardPile", draw], ["discardPile", discard]]) {
const descriptor = Object.getOwnPropertyDescriptor(ui, key);