mirror of
https://github.com/Shu-Ying/noname-shuying.git
synced 2026-10-25 09:10:02 +08:00
fixed # 补全梦三怪物、卡牌
fixed # 修复天书乱斗中,过关技能不会重置次数的问题
This commit is contained in:
@@ -10,9 +10,10 @@ export function installPersonalPiles(session, owner, battle, run, resources, env
|
||||
if (!descriptor || !descriptor.configurable || (!Object.hasOwn(descriptor, "value") && typeof descriptor.get !== "function")) throw new Error("Unsupported pile property: " + key);
|
||||
}
|
||||
const draw = document.createElement("div"), discard = document.createElement("div");
|
||||
const exhausted = document.createElement("div"); exhausted.id = "special";
|
||||
// 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(), topPlaying = new Set(), restores = [];
|
||||
const strict = env.strict !== false;
|
||||
let released = false, forcedOwner = false;
|
||||
const personal = () => {
|
||||
@@ -41,7 +42,17 @@ export function installPersonalPiles(session, owner, battle, run, resources, env
|
||||
card.destroyLog = false;
|
||||
card.destroyed = (current, position) => {
|
||||
if (released || !["discardPile", "equip", "judge"].includes(position)) return false;
|
||||
if (current.storage.mengsanCard_shuying.affixes.includes("exhaust") && current.storage.mengsanConsumed_shuying) {
|
||||
if (position === "discardPile" && topPlaying.has(current)) {
|
||||
if (!current.storage.mengsanExhausted_shuying) {
|
||||
current.storage.mengsanExhausted_shuying = true;
|
||||
battle.exhaustPile.push(snapshot(current));
|
||||
refresh();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const exhaust = env.lib?.card?.[current.name]?.mengsanExhaust_shuying === true ||
|
||||
current.storage.mengsanCard_shuying.affixes.includes("exhaust");
|
||||
if (exhaust && current.storage.mengsanConsumed_shuying) {
|
||||
if (current.storage.mengsanExhausted_shuying) return true;
|
||||
current.storage.mengsanExhausted_shuying = true;
|
||||
battle.exhaustPile.push(snapshot(current));
|
||||
@@ -51,7 +62,7 @@ export function installPersonalPiles(session, owner, battle, run, resources, env
|
||||
return false; // Actual discarded cards remain available to native skills.
|
||||
};
|
||||
for (const key of card.storage.mengsanCard_shuying.affixes) card.addGaintag(AFFIX_INFO[key]?.name || key);
|
||||
if (data.upgrade) card.addGaintag(`强化+${data.upgrade}`);
|
||||
// 强化仅用手牌 +X 角标显示;数值仍保存在 mengsanCard_shuying.upgrade。
|
||||
}
|
||||
function snapshot(card) {
|
||||
const data = card.storage?.mengsanCard_shuying || {};
|
||||
@@ -124,10 +135,95 @@ export function installPersonalPiles(session, owner, battle, run, resources, env
|
||||
observer.disconnect(); released = true;
|
||||
for (const restore of restores.reverse()) restore();
|
||||
for (const card of owned) card.remove();
|
||||
owned.clear(); draw.remove(); discard.remove();
|
||||
owned.clear(); topPlaying.clear(); draw.remove(); discard.remove(); exhausted.remove();
|
||||
});
|
||||
return {
|
||||
take,
|
||||
// 取出当前堆顶,不算抽牌、不洗牌,也不触发不足牌堆失败。
|
||||
beginTopPlay() {
|
||||
if (released || !session.active || !owner.isAlive() || !draw.firstChild) return null;
|
||||
const card = draw.firstChild;
|
||||
adopt(card); card.original = "c"; card.fix?.();
|
||||
exhausted.appendChild(card); topPlaying.add(card); refresh();
|
||||
return card;
|
||||
},
|
||||
async finishTopPlay(card) {
|
||||
if (!topPlaying.has(card)) return null;
|
||||
try {
|
||||
if (released || !session.active) return null;
|
||||
if (card.storage?.mengsanExhausted_shuying) { card.remove(); return card; }
|
||||
if (owner.getCards("hej").includes(card)) {
|
||||
const loss = owner.lose(card, exhausted); loss.type = "mengsanExhaust";
|
||||
await loss;
|
||||
if (released || !session.active || card.parentNode !== exhausted) return null;
|
||||
}
|
||||
// 被使用后在排序区/弃牌堆,或无法使用而仍在暂存区,均消耗原牌一次。
|
||||
if (!owned.has(card)) return null;
|
||||
card.storage.mengsanExhausted_shuying = true;
|
||||
battle.exhaustPile.push(snapshot(card)); card.remove(); refresh();
|
||||
return card;
|
||||
} finally { topPlaying.delete(card); }
|
||||
},
|
||||
// Explicit exhaustion is not a discard and must not touch the public piles.
|
||||
async exhaustFromHand(card) {
|
||||
if (released || !session.active || !owner.isAlive() ||
|
||||
!owner.getCards("h").includes(card) || card.storage?.mengsanExhausted_shuying) return null;
|
||||
adopt(card);
|
||||
const loss = owner.lose(card, exhausted);
|
||||
loss.type = "mengsanExhaust";
|
||||
await loss;
|
||||
// A cancelled/redirection event must not falsely consume its original.
|
||||
if (released || !session.active || card.parentNode !== exhausted) return null;
|
||||
if (!card.storage.mengsanExhausted_shuying) {
|
||||
card.storage.mengsanExhausted_shuying = true;
|
||||
battle.exhaustPile.push(snapshot(card));
|
||||
}
|
||||
card.remove();
|
||||
refresh();
|
||||
return card;
|
||||
},
|
||||
// Current physical combat cards only. Exhausted originals remain in owned;
|
||||
// never add the serialized exhaust snapshots a second time.
|
||||
battleCards(playing = []) {
|
||||
if (released || !session.active) return [];
|
||||
const cards = new Set([...owner.getCards("h"), ...draw.childNodes, ...discard.childNodes, ...exhausted.childNodes]);
|
||||
for (const card of owned) {
|
||||
if (card.storage?.mengsanOwnerId_shuying === owner.playerid &&
|
||||
card.storage?.mengsanExhausted_shuying) cards.add(card);
|
||||
}
|
||||
// The caller supplies this actor's native use-card originals, not virtual cards.
|
||||
for (const card of playing) if (ui.ordering && card?.parentNode === ui.ordering) cards.add(card);
|
||||
return [...cards];
|
||||
},
|
||||
addToDiscard(data) {
|
||||
if (released || !session.active) return null;
|
||||
if (!data || typeof data.id !== "string" || !data.id ||
|
||||
typeof data.name !== "string" || !/^[a-z][a-z0-9_]*$/.test(data.name) ||
|
||||
!["spade", "heart", "club", "diamond"].includes(data.suit) ||
|
||||
!Number.isInteger(data.number) || data.number < 1 || data.number > 13 ||
|
||||
!Array.isArray(data.affixes) || data.affixes.some(key => !Object.hasOwn(AFFIX_INFO, key))) {
|
||||
throw new TypeError("战斗生成牌数据无效");
|
||||
}
|
||||
const card = game.createCard(data.name, data.suit, data.number, data.nature);
|
||||
adopt(card, data);
|
||||
discard.appendChild(card);
|
||||
refresh();
|
||||
return card;
|
||||
},
|
||||
// Return references only to cards currently in this actor's discard node.
|
||||
discardCards() {
|
||||
if (released || !session.active) return [];
|
||||
return Array.from(discard.childNodes).filter(card => owned.has(card) &&
|
||||
!card.storage?.mengsanExhausted_shuying);
|
||||
},
|
||||
moveDiscardToTop(card) {
|
||||
if (released || !session.active || !owned.has(card) ||
|
||||
card.parentNode !== discard || card.storage?.mengsanExhausted_shuying) return false;
|
||||
card.fix?.();
|
||||
draw.insertBefore(card, draw.firstChild);
|
||||
refresh();
|
||||
return true;
|
||||
},
|
||||
addAffix(card, key) {
|
||||
if (released || !Object.hasOwn(AFFIX_INFO, key) || !owned.has(card) || !owner.getCards("h").includes(card)) return false;
|
||||
const affixes = card.storage?.mengsanCard_shuying?.affixes;
|
||||
|
||||
Reference in New Issue
Block a user