Files
noname-shuying/mengsan/cards/hand-upgrade.js
T
Diuse 94a2a6724b fixed # 补全部分卡牌
fixed # 修复部分已知BUG
2026-10-04 19:32:38 +08:00

88 lines
4.3 KiB
JavaScript

import { canUpgradeCard, cardUpgradeLevel } from "./upgrades.js";
// 武装只强化当前战斗的真实手牌;不写征程永久牌组。
export function createHandUpgrader(game, getActiveBattle, get) {
const states = new WeakMap();
const valid = (player, battle) => Boolean(battle && getActiveBattle() === battle &&
battle.session?.active && battle.players?.has(player) && player?.isAlive?.());
const getPile = (player, battle) => player === game.me
? battle.personalPiles : battle.monsterPiles?.get(player);
function dataOf(card) {
return card.storage?.mengsanCard_shuying || {
name: card.name, suit: card.suit, number: card.number, nature: card.nature || null,
upgrade: cardUpgradeLevel(card), affixes: Array.isArray(card.affixes) ? card.affixes : [],
};
}
function eligible(card) {
const data = dataOf(card);
return !card.storage?.mengsanExhausted_shuying && data.name === card.name &&
canUpgradeCard(data);
}
const handCards = (player, event) => {
const playing = new Set(event?.cards || []);
return player.getCards("h").filter(card => !playing.has(card) && eligible(card));
};
function remember(battle, card, after) {
let cards = states.get(battle);
if (!cards) {
cards = new Map();
states.set(battle, cards);
battle.session.ownResource(cards, () => {
// Do not overwrite a later replacement by another mechanic.
for (const [node, state] of cards) {
if (node.storage?.mengsanCard_shuying !== state.after) continue;
if (state.before === undefined) delete node.storage.mengsanCard_shuying;
else node.storage.mengsanCard_shuying = state.before;
}
cards.clear();
states.delete(battle);
});
}
const previous = cards.get(card);
cards.set(card, { before: previous ? previous.before : card.storage?.mengsanCard_shuying, after });
}
return async function blockUpgrade(player, event, block, all) {
if (!Number.isSafeInteger(block) || block < 0 || typeof all !== "boolean") {
throw new TypeError("武装格挡与手牌强化参数无效");
}
const battle = getActiveBattle();
if (!valid(player, battle)) return [];
const pile = getPile(player, battle);
if (typeof pile?.take !== "function") throw new Error("武装缺少个人牌堆接口");
await player.changeHujia(block);
if (!valid(player, battle) || getPile(player, battle) !== pile) return [];
const candidates = handCards(player, event);
if (!candidates.length) return [];
let chosen = candidates;
if (!all && candidates.length > 1) {
const result = await player.chooseButton({
createDialog: ["武装:选择强化一张你的手牌", candidates],
forced: true, selectButton: 1,
ai(button) { return get.value(button.link, player); },
}).forResult();
if (!result.bool || result.links?.length !== 1 || !candidates.includes(result.links[0])) return [];
chosen = result.links;
} else if (!all) chosen = [candidates[0]];
// No asynchronous work during commit: one current-hand snapshot avoids quadratic filtering.
const currentHand = new Set(player.getCards("h"));
const playing = new Set(event?.cards || []);
const changed = [];
for (const card of chosen) {
if (!valid(player, battle) || getPile(player, battle) !== pile) break;
if (!currentHand.has(card) || playing.has(card) || !eligible(card)) continue;
const data = dataOf(card);
const next = { ...data, affixes: data.affixes?.slice() || [], upgrade: (data.upgrade || 0) + 1 };
remember(battle, card, next);
card.storage ||= {};
card.storage.mengsanCard_shuying = next;
changed.push(card);
}
if (changed.length) {
battle.handUI?.refresh();
battle.pilesUI?.refresh();
game.log(player, "强化了", changed, "(仅本场战斗)");
}
return changed;
};
}