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

130 lines
7.6 KiB
JavaScript

// 梦三的模式牌定义:复制标准/军争的实体牌定义,不改动原牌包。
// 保留原牌名,以兼容原有牌的响应、装备技能及转化牌引用。
import standard from "../../../../card/standard.js";
import extra from "../../../../card/extra.js";
import { _status, game } from "../../../../noname.js";
import { cardCost, canPayCard, isActiveCardUse, SHA_DAMAGE,
TRICK_DAMAGE } from "../battle/combat-rules.js";
import { cardUpgradeLevel, cardUpgradeRule } from "./upgrades.js";
import { cardDefinitions } from "./card-definitions.js";
import { cleanCardDescription } from "./description.js";
import { DAZED_NAME, dazedDefinition } from "./status-cards.js";
import { SLIMED_NAME, slimedDefinition } from "./slimed-card.js";
import { INFECTION_NAME, infectionDefinition } from "./infection-card.js";
import { WOUND_NAME, woundDefinition } from "./wound-card.js";
const packs = [standard, extra];
const names = [...new Set(packs.flatMap(pack => pack.list.map(entry => entry[2])))];
const sourceCard = name => standard.card[name] || extra.card[name];
const sourceText = name => extra.translate[`${name}_info`] || standard.translate[`${name}_info`];
export function createMengsanCards({ cardPacks, isBattleActive = () => true } = {}) {
const card = {};
const translate = {};
for (const name of names) {
const source = sourceCard(name);
if (!source) throw new Error(`梦三牌定义缺失:${name}`);
const copy = { ...source, mengsanCost_shuying: cardCost({ name }) };
// 卡牌本身校验费用;响应和濒死救援不属于主动出牌。
if (source.enable || source.type === "equip" || source.type === "delay") {
copy.enable = function (used, player, event) {
if (isActiveCardUse(event || _status.event, player) && !canPayCard(player, used)) return false;
return typeof source.enable === "function" ? source.enable.call(this, used, player, event) : source.enable ?? true;
};
}
const prompt = source.cardPrompt;
const costLabel = name === "shan" || name === "wuxie"
? "响应不消耗费用" : `主动使用消耗${copy.mengsanCost_shuying}费用`;
copy.cardPrompt = function (used) {
const detail = typeof prompt === "function" ? prompt.call(this, used) : prompt;
return `梦三:${costLabel}。${detail || sourceText(name) || ""}`;
};
const nativeText = sourceText(name);
if (nativeText) translate[`${name}_info`] = `梦三:${costLabel}。${nativeText}`;
card[name] = copy;
}
// 【杀】的基础伤害由牌内容决定,而不是事后追加伤害的角色技能。
const nativeSha = sourceCard("sha");
card.sha.baseDamage = SHA_DAMAGE;
card.sha.content = async function (event, trigger, player) {
if (typeof event.baseDamage !== "number") event.baseDamage = SHA_DAMAGE;
if (cardUpgradeLevel(event.card)) {
event.baseDamage += cardUpgradeRule("sha").damage - SHA_DAMAGE;
}
return nativeSha.content.call(this, event, trigger, player);
};
card.sha.usable = Infinity;
card.sha.cardPrompt = used => {
const damage = cardUpgradeLevel(used)
? cardUpgradeRule("sha").damage : SHA_DAMAGE;
return `梦三:主动使用消耗1费用;目标须使用【闪】,` +
`否则受到${damage}点伤害。每回合使用次数不限。`;
};
translate.sha_info = `梦三:主动使用消耗1费用。出牌阶段,对攻击范围内的一名角色使用;其须使用【闪】,否则受到${SHA_DAMAGE}点伤害。每回合使用次数不限。`;
card.tao.content = async function (event) { await event.target.recover(8); };
translate.tao_info = "梦三:主动使用消耗1费用,回复8点生命;濒死救援不消耗费用,同样回复8点生命。";
card.taoyuan.content = async function (event) { await event.target.recover(8); };
translate.taoyuan_info = "梦三:主动使用消耗2费用。所有角色各回复8点生命。";
card.taoyuan.cardPrompt = () => translate.taoyuan_info;
for (const name of ["nanman", "wanjian", "juedou"]) {
const nativeContent = sourceCard(name).content;
card[name].baseDamage = TRICK_DAMAGE;
card[name].content = async function (event, trigger, player) {
if (typeof event.baseDamage !== "number") event.baseDamage = TRICK_DAMAGE;
return nativeContent.call(this, event, trigger, player);
};
const detail = {
nanman: "所有其他角色须打出【杀】,否则受到4点伤害。",
wanjian: "所有其他角色须打出【闪】,否则受到4点伤害。",
juedou: "目标与你轮流打出【杀】;未能打出的一方受到4点伤害。",
}[name];
translate[`${name}_info`] = `梦三:主动使用消耗${cardCost({ name })}费用。${detail}`;
card[name].cardPrompt = () => translate[`${name}_info`];
}
// 火攻通过当前牌事件的 baseDamage 传入 damage("fire")。
card.huogong.baseDamage = TRICK_DAMAGE;
translate.huogong_info = "梦三:主动使用消耗1费用。令一名有手牌的角色展示一张手牌;若你弃置同花色牌,对其造成4点火焰伤害。";
card.huogong.cardPrompt = () => translate.huogong_info;
// 闪电属于延时锦囊,其命中伤害在 effect 中显式写死为3,需要独立覆写。
card.shandian.effect = async function (event, trigger, player, result) {
if (result.bool === false) await player.damage(12, "thunder", "nosource");
else player.addJudgeNext(event.card);
};
translate.shandian_info = "梦三:主动使用消耗1费用。若判定为黑桃2~9,目标受到12点雷电伤害;否则移至下家的判定区。";
card.shandian.cardPrompt = () => translate.shandian_info;
card[WOUND_NAME] = { ...woundDefinition };
translate[WOUND_NAME] = "伤口";
translate[`${WOUND_NAME}_info`] = woundDefinition.cardPrompt();
card[INFECTION_NAME] = { ...infectionDefinition };
translate[INFECTION_NAME] = "感染";
translate[`${INFECTION_NAME}_info`] = infectionDefinition.cardPrompt();
card[SLIMED_NAME] = { ...slimedDefinition };
translate[SLIMED_NAME] = "黏液";
translate[`${SLIMED_NAME}_info`] = slimedDefinition.cardPrompt();
card[DAZED_NAME] = { ...dazedDefinition };
translate[DAZED_NAME] = "晕眩";
translate[`${DAZED_NAME}_info`] = dazedDefinition.cardPrompt();
if (cardPacks) {
Object.assign(card, cardPacks.cards);
Object.assign(translate, cardPacks.translate);
}
for (const [name, definition] of Object.entries(card)) {
const classification = cardDefinitions[name];
definition.cardType = classification?.cardType ?? (definition.type === "status" ? "status" : null);
definition.rarity = classification?.rarity ?? definition.rarity ?? (definition.type === "status" ? "status" : "common");
definition.mengsanPower_shuying = definition.cardType === "power" ||
!definition.cardType && Boolean(definition.mengsanPower_shuying);
const infoKey = `${name}_info`;
if (typeof translate[infoKey] === "string") {
translate[infoKey] = cleanCardDescription(translate[infoKey]);
}
if (typeof definition.cardPrompt !== "function") continue;
const prompt = definition.cardPrompt;
definition.cardPrompt = function (used) {
return cleanCardDescription(prompt.call(this, used));
};
}
return { card, translate, names:[...new Set([...names, ...(cardPacks?.names || [])])] };
}