mirror of
https://github.com/Shu-Ying/noname-shuying.git
synced 2026-10-12 20:10:05 +08:00
88 lines
4.3 KiB
JavaScript
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;
|
|
};
|
|
}
|