Files
noname-shuying/mengsan/cards/mode-cards.js
T
Diuse c448da39c2 fixed # 补全梦三怪物、卡牌
fixed # 修复天书乱斗中,过关技能不会重置次数的问题
2026-10-03 04:42:19 +08:00

803 lines
48 KiB
JavaScript

// 梦三的模式牌定义:复制标准/军争的实体牌定义,不改动原牌包。
// 保留原牌名,以兼容原有牌的响应、装备技能及转化牌引用。
import standard from "../../../../card/standard.js";
import extra from "../../../../card/extra.js";
import { _status, game, get } from "../../../../noname.js";
import { cardCost, canPayCard, isActiveCardUse, SHA_DAMAGE,
TRICK_DAMAGE } from "../battle/combat-rules.js";
import { cardUpgradeLevel, cardUpgradeRule } from "./upgrades.js";
import { applyMengsanDebuff } from "../monsters/artifact-status.js";
import { isAttackCard } from "../monsters/vine-tangled.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";
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({ copyToDiscard, reclaimFromDiscard, temporaryStrength, countStrikeCards, randomHandExhaust, battleEnergy, handExhaust, playDrawTop, blockDraw, 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.mengsan_zhongsha = {
type: "basic",
fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_zhongsha.png",
mengsanCost_shuying: cardCost({ name: "mengsan_zhongsha" }),
enable(used, player, event) {
return !isActiveCardUse(event || _status.event, player) ||
canPayCard(player, used);
},
usable: Infinity,
selectTarget: 1,
range: nativeSha.range,
filterTarget: nativeSha.filterTarget,
async content(event, trigger, player) {
const target = event.target;
const effect = cardUpgradeLevel(event.card)
? cardUpgradeRule("mengsan_zhongsha")
: { damage: 8, vulnerable: 2 };
const damage = target.damage(effect.damage, player);
damage.mengsanAttack_shuying = true;
await damage;
if (!target.isAlive()) return;
if (applyMengsanDebuff(target, "vulnerable", effect.vulnerable))
game.log(target, `获得${effect.vulnerable}层易伤`);
},
ai: { order: 4, result: { target: -1.5 },
tag: { damage: 1 } },
cardPrompt(used) {
const effect = cardUpgradeLevel(used)
? cardUpgradeRule("mengsan_zhongsha")
: { damage: 8, vulnerable: 2 };
return "梦三:主动使用消耗2费用。对攻击范围内的" +
`一名其他角色造成${effect.damage}点伤害,然后给予其` +
`${effect.vulnerable}层易伤。受到攻击伤害增加50%` +
"(向上取整),每个自身回合结束减少1层。" +
"每回合使用次数不限。";
},
};
translate.mengsan_zhongsha = "重杀";
translate.mengsan_zhongsha_info =
"梦三:主动使用消耗2费用。出牌阶段,对攻击范围内的" +
"一名其他角色造成8点伤害,然后给予其2层易伤。" +
"易伤使受到的攻击伤害增加50%(向上取整)," +
"每个自身回合结束减少1层。每回合使用次数不限。";
// STS2 Setup Strike: the new temporary strength does not enhance its own hit.
// STS2 Cinder: damage first, then exhaust one random remaining hand card.
card.mengsan_yujin = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_yujin.png",
mengsanCost_shuying: cardCost({ name: "mengsan_yujin" }),
usable: Infinity, selectTarget: 1,
enable(used, player, event) {
if (!isBattleActive() || !player.isAlive()) return false;
return !isActiveCardUse(event || _status.event, player) || canPayCard(player, used);
},
filterTarget(used, player, target) {
return target !== player && target.isAlive() && player.isEnemyOf(target);
},
async content(event, trigger, player) {
const target = event.target;
if (!isBattleActive() || !player.isAlive() || !target?.isAlive() ||
target === player || !player.isEnemyOf(target)) return;
if (!randomHandExhaust?.capture || !randomHandExhaust?.exhaust) throw new Error("余烬缺少随机消耗接口");
const battle = randomHandExhaust.capture();
if (!battle) return;
const rule = cardUpgradeRule("mengsan_yujin");
const damage = target.damage(cardUpgradeLevel(event.card) ? rule.damage : rule.baseDamage, player);
damage.mengsanAttack_shuying = true;
await damage;
if (isBattleActive() && player.isAlive()) await randomHandExhaust.exhaust(player, event, battle);
},
ai: { order: 6, result: { target: -2 }, tag: { damage: 1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_yujin");
const amount = cardUpgradeLevel(used) ? rule.damage : rule.baseDamage;
return `梦三:主动使用消耗2费用。对一名敌方角色造成${amount}点伤害,然后随机消耗一张你的手牌(退出本场战斗,不进入弃牌堆或洗牌)。没有手牌时不消耗牌。每回合使用次数不限。`;
},
};
translate.mengsan_yujin = "余烬";
translate.mengsan_yujin_info = card.mengsan_yujin.cardPrompt({ name: "mengsan_yujin" });
// STS2 Perfected Strike counts current physical combat cards, including itself/exhaust.
card.mengsan_wanmeidaji = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_wanmeidaji.png",
mengsanCost_shuying: cardCost({ name: "mengsan_wanmeidaji" }),
usable: Infinity, selectTarget: 1,
enable(used, player, event) {
if (!isBattleActive() || !player.isAlive()) return false;
return !isActiveCardUse(event || _status.event, player) || canPayCard(player, used);
},
filterTarget(used, player, target) {
return target !== player && target.isAlive() && player.isEnemyOf(target);
},
async content(event, trigger, player) {
const target = event.target;
if (!isBattleActive() || !player.isAlive() || !target?.isAlive() ||
target === player || !player.isEnemyOf(target)) return;
if (typeof countStrikeCards !== "function") throw new Error("完美打击缺少打击牌计数接口");
const count = countStrikeCards(player, event);
if (!Number.isSafeInteger(count) || count < 0) throw new RangeError("打击牌数量无效");
const rule = cardUpgradeRule("mengsan_wanmeidaji");
const amount = rule.baseDamage + count * (cardUpgradeLevel(event.card) ? rule.perStrike : rule.basePerStrike);
if (!Number.isSafeInteger(amount) || amount < 0) throw new RangeError("完美打击伤害无效");
const damage = target.damage(amount, player);
damage.mengsanAttack_shuying = true;
damage.mengsanStrikeCount_shuying = count;
await damage;
},
ai: { order: 7, result: { target: -2 }, tag: { damage: 1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_wanmeidaji");
const bonus = cardUpgradeLevel(used) ? rule.perStrike : rule.basePerStrike;
return `梦三:主动使用消耗2费用。对一名敌方角色造成6点伤害,本场战斗的牌中每有一张名称含“打击”的牌,伤害增加${bonus}点(包括手牌、个人抽牌堆、个人弃牌堆、消耗牌及打出区)。每回合使用次数不限。`;
},
};
translate.mengsan_wanmeidaji = "完美打击";
translate.mengsan_wanmeidaji_info = card.mengsan_wanmeidaji.cardPrompt({ name: "mengsan_wanmeidaji" });
card.mengsan_yubeidaji = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_yubeidaji.png",
mengsanCost_shuying: cardCost({ name: "mengsan_yubeidaji" }),
usable: Infinity, selectTarget: 1,
enable(used, player, event) {
if (!isBattleActive() || !player.isAlive()) return false;
return !isActiveCardUse(event || _status.event, player) || canPayCard(player, used);
},
filterTarget(used, player, target) {
return target !== player && target.isAlive() && player.isEnemyOf(target);
},
async content(event, trigger, player) {
const target = event.target;
if (!isBattleActive() || !player.isAlive() || !target?.isAlive() ||
target === player || !player.isEnemyOf(target)) return;
if (!temporaryStrength?.capture || !temporaryStrength?.grant) throw new Error("预备打击缺少临时力量接口");
const battle = temporaryStrength.capture();
if (!battle) return;
const rule = cardUpgradeRule("mengsan_yubeidaji");
const upgraded = cardUpgradeLevel(event.card);
const damage = target.damage(upgraded ? rule.damage : rule.baseDamage, player);
damage.mengsanAttack_shuying = true;
await damage;
if (isBattleActive() && player.isAlive()) {
temporaryStrength.grant(player, upgraded ? rule.strength : rule.baseStrength, event, battle);
}
},
ai: { order: 8, result: { player: 0.8, target: -1.5 }, tag: { damage: 1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_yubeidaji");
const upgraded = cardUpgradeLevel(used);
return `梦三:主动使用消耗1费用。对一名敌方角色造成${upgraded ? rule.damage : rule.baseDamage}点伤害,然后在本回合内获得${upgraded ? rule.strength : rule.baseStrength}点力量。每回合使用次数不限。`;
},
};
translate.mengsan_yubeidaji = "预备打击";
translate.mengsan_yubeidaji_info = "梦三:主动使用消耗1费用。对一名敌方角色造成7点伤害,然后在本回合内获得2点力量。每回合使用次数不限。";
// STS2 Breakthrough: native life loss is paid once before the all-enemy attack.
card.mengsan_tupo = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_tupo.png",
mengsanCost_shuying: cardCost({ name: "mengsan_tupo" }),
notarget: true, usable: Infinity,
enable(used, player, event) {
if (!isBattleActive() || !player.isAlive()) return false;
if (!game.filterPlayer(target => target !== player &&
target.isAlive() && player.isEnemyOf(target)).length) return false;
return !isActiveCardUse(event || _status.event, player) || canPayCard(player, used);
},
async content(event, trigger, player) {
if (!isBattleActive() || !player.isAlive()) return;
if (!game.filterPlayer(target => target !== player &&
target.isAlive() && player.isEnemyOf(target)).length) return;
// loseHp bypasses block and awaits the normal dying/rescue process.
await player.loseHp(1);
if (!isBattleActive() || !player.isAlive()) return;
const rule = cardUpgradeRule("mengsan_tupo");
const amount = cardUpgradeLevel(event.card) ? rule.damage : rule.baseDamage;
const targets = game.filterPlayer(target => target !== player &&
target.isAlive() && player.isEnemyOf(target));
for (const target of targets) {
if (!isBattleActive() || !player.isAlive()) break;
if (!target.isAlive() || !player.isEnemyOf(target)) continue;
player.line(target, "green");
const damage = target.damage(amount, player);
damage.mengsanAttack_shuying = true;
await damage;
}
},
ai: { order: 7, result: { player(player) { return player.hp <= 1 ? -10 : 1; } }, tag: { damage: 1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_tupo");
const amount = cardUpgradeLevel(used) ? rule.damage : rule.baseDamage;
return `梦三:主动使用消耗1费用。失去1点生命,然后对所有敌方角色造成${amount}点伤害。每回合使用次数不限。`;
},
};
translate.mengsan_tupo = "突破";
translate.mengsan_tupo_info = "梦三:主动使用消耗1费用。失去1点生命,然后对所有敌方角色造成9点伤害。每回合使用次数不限。";
// STS2 Headbutt: damage first, then choose from the actor's own real discard pile.
card.mengsan_touchui = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_touchui.png",
mengsanCost_shuying: cardCost({ name: "mengsan_touchui" }),
usable: Infinity, selectTarget: 1,
enable(used, player, event) {
if (!isBattleActive() || !player.isAlive()) return false;
return !isActiveCardUse(event || _status.event, player) || canPayCard(player, used);
},
filterTarget(used, player, target) {
return target !== player && target.isAlive() && player.isEnemyOf(target);
},
async content(event, trigger, player) {
const target = event.target;
if (!isBattleActive() || !player.isAlive() || !target?.isAlive() ||
target === player || !player.isEnemyOf(target)) return;
if (typeof reclaimFromDiscard !== "function") throw new Error("头槌缺少个人弃牌回收接口");
const rule = cardUpgradeRule("mengsan_touchui");
const amount = cardUpgradeLevel(event.card) ? rule.damage : rule.baseDamage;
const damage = target.damage(amount, player);
damage.mengsanAttack_shuying = true;
await damage;
// Defeating one enemy does not prevent recovery unless combat actually ends.
if (isBattleActive() && player.isAlive()) await reclaimFromDiscard(player);
},
ai: { order: 6, result: { player: 0.4, target: -1.5 }, tag: { damage: 1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_touchui");
const amount = cardUpgradeLevel(used) ? rule.damage : rule.baseDamage;
return '梦三:主动使用消耗1费用。对一名敌方角色造成' + amount +
'点伤害,然后选择个人弃牌堆中的一张牌放到个人抽牌堆顶部。每回合使用次数不限。';
},
};
translate.mengsan_touchui = "头槌";
translate.mengsan_touchui_info = "梦三:主动使用消耗1费用。对一名敌方角色造成9点伤害," +
"然后选择个人弃牌堆中的一张牌放到个人抽牌堆顶部。每回合使用次数不限。";
// STS2 Iron Wave: obtain block before resolving the attack.
card.mengsan_tiezhanbo = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_tiezhanbo.png",
mengsanCost_shuying: cardCost({ name: "mengsan_tiezhanbo" }),
usable: Infinity, selectTarget: 1,
enable(used, player, event) {
if (!isBattleActive() || !player.isAlive()) return false;
return !isActiveCardUse(event || _status.event, player) || canPayCard(player, used);
},
filterTarget(used, player, target) {
return target !== player && target.isAlive() && player.isEnemyOf(target);
},
async content(event, trigger, player) {
const target = event.target;
const canResolve = () => isBattleActive() && player.isAlive() &&
target?.isAlive() && target !== player && player.isEnemyOf(target);
if (!canResolve()) return;
const rule = cardUpgradeRule("mengsan_tiezhanbo");
const upgraded = cardUpgradeLevel(event.card) > 0;
await player.changeHujia(upgraded ? rule.block : rule.baseBlock);
// Block triggers may end combat or remove the acting player/target.
if (!canResolve()) return;
const damage = target.damage(upgraded ? rule.damage : rule.baseDamage, player);
damage.mengsanAttack_shuying = true;
await damage;
},
ai: { order: 7, result: { player: 0.6, target: -1.2 }, tag: { damage: 1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_tiezhanbo");
const upgraded = cardUpgradeLevel(used) > 0;
const block = upgraded ? rule.block : rule.baseBlock;
const damage = upgraded ? rule.damage : rule.baseDamage;
return '梦三:主动使用消耗1费用。获得' + block +
'点格挡(护甲),然后对一名敌方角色造成' + damage +
'点伤害。每回合使用次数不限。';
},
};
translate.mengsan_tiezhanbo = "铁斩波";
translate.mengsan_tiezhanbo_info = "梦三:主动使用消耗1费用。获得5点格挡(护甲)," +
"然后对一名敌方角色造成5点伤害。每回合使用次数不限。";
// STS2 Twin Strike: each hit resolves on the same target separately.
card.mengsan_shuangchongdaji = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_shuangchongdaji.png",
mengsanCost_shuying: cardCost({ name: "mengsan_shuangchongdaji" }),
usable: Infinity, selectTarget: 1,
enable(used, player, event) {
if (!isBattleActive() || !player.isAlive()) return false;
return !isActiveCardUse(event || _status.event, player) || canPayCard(player, used);
},
filterTarget(used, player, target) {
return target !== player && target.isAlive() && player.isEnemyOf(target);
},
async content(event, trigger, player) {
const target = event.target;
const rule = cardUpgradeRule("mengsan_shuangchongdaji");
const amount = cardUpgradeLevel(event.card) ? rule.damage : rule.baseDamage;
for (let hitIndex = 0; hitIndex < rule.hits; hitIndex++) {
if (!isBattleActive() || !player.isAlive() || !target?.isAlive() ||
target === player || !player.isEnemyOf(target)) break;
const damage = target.damage(amount, player);
damage.mengsanAttack_shuying = true;
await damage;
}
},
ai: { order: 6, result: { target: -1.5 }, tag: { damage: 1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_shuangchongdaji");
const amount = cardUpgradeLevel(used) ? rule.damage : rule.baseDamage;
return '梦三:主动使用消耗1费用。对一名敌方角色造成' +
amount + '点伤害两次,两次伤害分别结算。每回合使用次数不限。';
},
};
translate.mengsan_shuangchongdaji = "双重打击";
translate.mengsan_shuangchongdaji_info = "梦三:主动使用消耗1费用。对一名敌方角色造成5点伤害两次," +
"两次伤害分别结算。每回合使用次数不限。";
// STS2 Thunderclap: hit each living enemy before adding new vulnerable.
card.mengsan_shandianpili = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_shandianpili.png",
mengsanCost_shuying: cardCost({ name: "mengsan_shandianpili" }),
notarget: true, usable: Infinity,
enable(used, player, event) {
if (!isBattleActive() || !player.isAlive()) return false;
if (!game.filterPlayer(target => target !== player &&
target.isAlive() && player.isEnemyOf(target)).length) return false;
return !isActiveCardUse(event || _status.event, player) || canPayCard(player, used);
},
async content(event, trigger, player) {
if (!isBattleActive() || !player.isAlive()) return;
const rule = cardUpgradeRule("mengsan_shandianpili");
const amount = cardUpgradeLevel(event.card) ? rule.damage : rule.baseDamage;
const targets = game.filterPlayer(target => target !== player &&
target.isAlive() && player.isEnemyOf(target));
for (const target of targets) {
if (!isBattleActive() || !player.isAlive()) break;
if (!target.isAlive() || !player.isEnemyOf(target)) continue;
player.line(target, "green");
const damage = target.damage(amount, player);
damage.mengsanAttack_shuying = true;
await damage;
}
// 伤害结束后重新取得存活敌人,包含异蛙亡语刚生成的扭动虫。
for (const target of game.filterPlayer(target => target !== player && target.isAlive() && player.isEnemyOf(target))) {
if (!isBattleActive() || !player.isAlive()) break;
if (applyMengsanDebuff(target, "vulnerable", rule.vulnerable))
game.log(target, `获得${rule.vulnerable}层易伤`);
}
},
ai: { order: 7, result: { player: 1 }, tag: { damage: 1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_shandianpili");
const amount = cardUpgradeLevel(used) ? rule.damage : rule.baseDamage;
return `梦三:主动使用消耗1费用。对所有敌方角色造成${amount}点伤害,然后给予其1层易伤。` +
"易伤使受到的攻击伤害增加50%(向上取整),每个自身回合结束减少1层。每回合使用次数不限。";
},
};
translate.mengsan_shandianpili = "闪电霹雳";
translate.mengsan_shandianpili_info = "梦三:主动使用消耗1费用。对所有敌方角色造成4点伤害,然后给予其1层易伤。" +
"易伤使受到的攻击伤害增加50%(向上取整),每个自身回合结束减少1层。每回合使用次数不限。";
// Each throw resolves separately and samples the still-living enemies again.
card.mengsan_feijianhuixuanbiao = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_feijianhuixuanbiao.png",
mengsanCost_shuying: cardCost({ name: "mengsan_feijianhuixuanbiao" }),
notarget: true, usable: Infinity,
enable(used, player, event) {
if (!isBattleActive() || !player.isAlive()) return false;
if (!game.filterPlayer(target => target !== player &&
target.isAlive() && player.isEnemyOf(target)).length) return false;
return !isActiveCardUse(event || _status.event, player) || canPayCard(player, used);
},
async content(event, trigger, player) {
const rule = cardUpgradeRule("mengsan_feijianhuixuanbiao");
const count = cardUpgradeLevel(event.card) ? rule.hits : rule.baseHits;
for (let hitIndex = 0; hitIndex < count; hitIndex++) {
if (!isBattleActive() || !player.isAlive()) break;
const enemies = game.filterPlayer(target => target !== player &&
target.isAlive() && player.isEnemyOf(target));
if (!enemies.length) break;
// Use the engine helper with an inclusive index range.
const target = enemies[get.rand(0, enemies.length - 1)];
player.line(target, "green");
const damage = target.damage(rule.damage, player);
damage.mengsanAttack_shuying = true;
await damage;
}
},
ai: { order: 6, result: { player: 1 }, tag: { damage: 1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_feijianhuixuanbiao");
const count = cardUpgradeLevel(used) ? rule.hits : rule.baseHits;
return `梦三:主动使用消耗1费用。每次对随机一名敌方角色造成${rule.damage}点伤害,共${count}次。` +
"每次攻击重新随机选择存活的敌人,可以重复命中同一敌人。" +
"每回合使用次数不限。";
},
};
translate.mengsan_feijianhuixuanbiao = "飞剑回旋镖";
translate.mengsan_feijianhuixuanbiao_info = "梦三:主动使用消耗1费用。随机对敌人造成3点伤害3次。" +
"每次攻击重新随机选择存活的敌人,可以重复命中同一敌人。每回合使用次数不限。";
// Resolve damage before drawing from the acting player's mode-owned pile.
card.mengsan_jianbingdaji = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_jianbingdaji.png",
mengsanCost_shuying: cardCost({ name: "mengsan_jianbingdaji" }),
usable: Infinity, selectTarget: 1,
enable(used, player, event) {
if (!isBattleActive() || !player.isAlive()) return false;
return !isActiveCardUse(event || _status.event, player) || canPayCard(player, used);
},
filterTarget(used, player, target) {
return target !== player && target.isAlive() && player.isEnemyOf(target);
},
async content(event, trigger, player) {
if (!isBattleActive() || !player.isAlive()) return;
const rule = cardUpgradeRule("mengsan_jianbingdaji");
const upgraded = cardUpgradeLevel(event.card) > 0;
const damage = event.target.damage(upgraded ? rule.damage : rule.baseDamage, player);
damage.mengsanAttack_shuying = true;
await damage;
// Defeating the last enemy may dispose the personal pile during damage.
if (isBattleActive() && player.isAlive()) {
await player.draw(upgraded ? rule.draw : rule.baseDraw);
}
},
ai: { order: 6, result: { player: 0.6, target: -1.5 }, tag: { damage: 1, draw: 1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_jianbingdaji");
const upgraded = cardUpgradeLevel(used) > 0;
const damage = upgraded ? rule.damage : rule.baseDamage;
const draw = upgraded ? rule.draw : rule.baseDraw;
return `梦三:主动使用消耗1费用。对一名敌方角色造成${damage}点伤害,然后抽${draw}张牌。` +
"每回合使用次数不限。";
},
};
translate.mengsan_jianbingdaji = "剑柄打击";
translate.mengsan_jianbingdaji_info = "梦三:主动使用消耗1费用。对一名敌方角色造成9点伤害,然后抽1张牌。" +
"每回合使用次数不限。";
// Block determines base damage without spending the acting player's block.
card.mengsan_quanshenzhuangji = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_quanshenzhuangji.png",
mengsanCost_shuying: cardCost({ name: "mengsan_quanshenzhuangji" }),
usable: Infinity, selectTarget: 1,
enable(used, player, event) {
if (!isBattleActive() || !player.isAlive()) return false;
return !isActiveCardUse(event || _status.event, player) || canPayCard(player, used);
},
filterTarget(used, player, target) {
return target !== player && target.isAlive() && player.isEnemyOf(target);
},
async content(event, trigger, player) {
if (!isBattleActive() || !player.isAlive()) return;
const block = Number.isFinite(player.hujia) ? Math.max(0, player.hujia) : 0;
const storedStrength = player.storage?.mengsanStrength_shuying;
const strength = Number.isInteger(storedStrength) ? storedStrength : 0;
// Native damage(0) stops before damageBegin1, so strength must be included here.
const temporary = temporaryStrength?.amount(player) || 0;
const damage = event.target.damage(Math.max(0, block + strength + temporary), player);
damage.mengsanAttack_shuying = true;
damage.mengsanCardStrengthApplied_shuying = true;
damage.mengsanSetupStrengthApplied_shuying = true;
await damage;
},
ai: {
order: 5,
result: { target(used, player) { return player.hujia > 0 ? -1.5 : 0; } },
tag: { damage: 1 },
},
cardPrompt(used) {
const cost = cardCost(used || { name: "mengsan_quanshenzhuangji" });
return `梦三:主动使用消耗${cost}费用。对一名敌方角色造成等同于你当前格挡(护甲)值的伤害。` +
"不消耗格挡,可以受到力量加成。" +
"每回合使用次数不限。";
},
};
translate.mengsan_quanshenzhuangji = "全身撞击";
translate.mengsan_quanshenzhuangji_info = "梦三:主动使用消耗1费用。对一名敌方角色造成等同于你当前格挡(护甲)值的伤害。" +
"不消耗格挡,可以受到力量加成。每回合使用次数不限。";
// Double only the surviving target's existing vulnerable after damage resolves.
card.mengsan_rongrongzhiquan = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_rongrongzhiquan.png",
mengsanCost_shuying: cardCost({ name: "mengsan_rongrongzhiquan" }),
mengsanExhaust_shuying: true,
usable: Infinity, selectTarget: 1,
enable(used, player, event) {
if (!isBattleActive() || !player.isAlive()) return false;
return !isActiveCardUse(event || _status.event, player) || canPayCard(player, used);
},
filterTarget(used, player, target) {
return target !== player && target.isAlive() && player.isEnemyOf(target);
},
async content(event, trigger, player) {
if (!isBattleActive() || !player.isAlive()) return;
const rule = cardUpgradeRule("mengsan_rongrongzhiquan");
const target = event.target;
const damage = target.damage(cardUpgradeLevel(event.card) ? rule.damage : rule.baseDamage, player);
damage.mengsanAttack_shuying = true;
await damage;
if (!target.isAlive() || !isBattleActive()) return;
const stacks = target.storage?.mengsanVulnerable_shuying;
if (!Number.isSafeInteger(stacks) || stacks <= 0) return;
const doubled = stacks * 2;
if (!Number.isSafeInteger(doubled)) throw new RangeError("易伤层数越界");
if (applyMengsanDebuff(target, "vulnerable", stacks))
game.log(target, `易伤层数从${stacks}翻倍为${doubled}`);
},
ai: { order: 6, result: { target: -1.5 }, tag: { damage: 1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_rongrongzhiquan");
const damage = cardUpgradeLevel(used) ? rule.damage : rule.baseDamage;
return `梦三:主动使用消耗1费用。对一名敌方角色造成${damage}点伤害,然后将该目标已有的易伤层数翻倍。` +
"没有易伤时不会新增易伤。消耗:使用后退出本场战斗,不进入弃牌堆或洗牌。";
},
};
translate.mengsan_rongrongzhiquan = "熔融之拳";
translate.mengsan_rongrongzhiquan_info = "梦三:主动使用消耗1费用。对一名敌方角色造成10点伤害,然后将该目标已有的易伤层数翻倍。" +
"消耗:使用后退出本场战斗。";
// STS2【愤怒】:攻击后生成独立的战斗复制品,不扩充永久牌组。
card.mengsan_fennu = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_fennu.png",
mengsanCost_shuying: cardCost({ name: "mengsan_fennu" }),
enable(used, player, event) {
return !isActiveCardUse(event || _status.event, player) ||
canPayCard(player, used);
},
usable: Infinity, selectTarget: 1,
filterTarget(used, player, target) {
return target !== player && player.isEnemyOf(target);
},
async content(event, trigger, player) {
if (typeof copyToDiscard !== "function") throw new Error("愤怒缺少战斗复制接口");
const amount = cardUpgradeLevel(event.card)
? cardUpgradeRule("mengsan_fennu").damage : 6;
const damage = event.target.damage(amount, player);
damage.mengsanAttack_shuying = true;
await damage;
if (copyToDiscard(player, event.card, event.cards)) {
game.log(player, "将一张【愤怒】的复制品加入个人弃牌堆");
}
},
ai: { order: 6, result: { target: -1 }, tag: { damage: 1 } },
cardPrompt(used) {
const amount = cardUpgradeLevel(used)
? cardUpgradeRule("mengsan_fennu").damage : 6;
return `梦三:主动使用消耗0费用。对一名敌方角色造成${amount}点伤害,` +
"然后将一张此牌的复制品加入你的个人弃牌堆。" +
"复制品保留原牌状态和词缀,仅存在于本场战斗。";
},
};
translate.mengsan_fennu = "愤怒";
translate.mengsan_fennu_info = "梦三:主动使用消耗0费用。对一名敌方角色造成6点伤害," +
"然后将一张此牌的复制品加入你的个人弃牌堆。复制品保留原牌状态和词缀,仅存在于本场战斗。" +
"每回合使用次数不限。";
// STS2【放血】:先等待原生生命流失及濒死救援,再增加当前战斗费用。
card.mengsan_fangxue = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_fangxue.png",
mengsanCost_shuying: cardCost({ name: "mengsan_fangxue" }),
enable(used, player, event) {
return isBattleActive() && Boolean(battleEnergy?.canUse(player)) &&
(!isActiveCardUse(event || _status.event, player) || canPayCard(player, used));
},
usable: Infinity, toself: true, selectTarget: -1,
filterTarget(used, player, target) { return target === player; },
async content(event, trigger, player) {
if (typeof battleEnergy?.capture !== "function" || typeof battleEnergy?.grant !== "function") {
throw new Error("放血缺少战斗费用接口");
}
const rule = cardUpgradeRule("mengsan_fangxue");
const amount = cardUpgradeLevel(event.card) ? rule.energy : rule.baseEnergy;
const battle = battleEnergy.capture(player, amount);
if (!battle) return;
await player.loseHp(rule.loseHp);
battleEnergy.grant(player, amount, battle);
},
ai: { order: 9, result: { player: player => player.hp > 3 ? 1 : -1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_fangxue");
const amount = cardUpgradeLevel(used) ? rule.energy : rule.baseEnergy;
return "梦三:主动使用消耗0费用。失去" + rule.loseHp + "点生命,然后获得" + amount + "点费用。";
},
};
translate.mengsan_fangxue = "放血";
translate.mengsan_fangxue_info = "梦三:主动使用消耗0费用。失去3点生命,然后获得2点费用。";
// STS2【坚毅】:先获得格挡,再消耗一张自身当时的手牌。
card.mengsan_jianyi = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_jianyi.png",
mengsanCost_shuying: cardCost({ name: "mengsan_jianyi" }),
enable(used, player, event) {
return isBattleActive() && Boolean(player?.isAlive?.()) &&
(!isActiveCardUse(event || _status.event, player) || canPayCard(player, used));
},
usable: Infinity, toself: true, selectTarget: -1,
filterTarget(used, player, target) { return target === player; },
async content(event, trigger, player) {
if (typeof handExhaust?.capture !== "function" || typeof handExhaust?.exhaust !== "function") {
throw new Error("坚毅缺少手牌消耗接口");
}
const battle = handExhaust.capture(player);
if (!battle) return;
const rule = cardUpgradeRule("mengsan_jianyi");
const current = cardUpgradeLevel(event.card);
await player.changeHujia(current ? rule.block : rule.baseBlock);
await handExhaust.exhaust(player, event, battle, Boolean(current && rule.chooseExhaust));
},
ai: { order: 7, result: { player: 1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_jianyi");
const current = cardUpgradeLevel(used);
const block = current ? rule.block : rule.baseBlock;
return "梦三:主动使用消耗1费用。获得" + block + "点格挡(护甲),然后" +
(current && rule.chooseExhaust ? "选择消耗" : "随机消耗") +
"一张你的手牌(退出本场战斗,不进入弃牌堆或洗牌)。没有手牌时不消耗牌。";
},
};
translate.mengsan_jianyi = "坚毅";
translate.mengsan_jianyi_info = "梦三:主动使用消耗1费用。获得7点格挡(护甲),然后随机消耗一张你的手牌(退出本场战斗,不进入弃牌堆或洗牌)。没有手牌时不消耗牌。";
// STS2【破灭】:免费使用自己的堆顶原牌,再将这一原牌消耗。
card.mengsan_pomie = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_pomie.png",
mengsanCost_shuying: cardCost({ name: "mengsan_pomie" }),
enable(used, player, event) {
return isBattleActive() && Boolean(player?.isAlive?.()) &&
(!isActiveCardUse(event || _status.event, player) || canPayCard(player, used));
},
usable: Infinity, toself: true, selectTarget: -1,
filterTarget(used, player, target) { return target === player; },
async content(event, trigger, player) {
if (typeof playDrawTop !== "function") throw new Error("破灭缺少堆顶使用接口");
await playDrawTop(player);
},
ai: { order: 6, result: { player: 1 } },
cardPrompt(used) {
return "梦三:主动使用消耗" + cardCost(used) +
"费用。免费使用你抽牌堆顶部的牌,然后将该原牌消耗(退出本场战斗,不进入弃牌堆或洗牌)。抽牌堆为空时不生效。";
},
};
translate.mengsan_pomie = "破灭";
translate.mengsan_pomie_info = "梦三:主动使用消耗1费用。免费使用你抽牌堆顶部的牌,然后将该原牌消耗(退出本场战斗,不进入弃牌堆或洗牌)。抽牌堆为空时不生效。";
// STS2【耸肩无视】:先获得格挡,再抽一张牌。
card.mengsan_songjianwushi = {
type: "basic", fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_songjianwushi.png",
mengsanCost_shuying: cardCost({ name: "mengsan_songjianwushi" }),
enable(used, player, event) {
return isBattleActive() && Boolean(player?.isAlive?.()) &&
(!isActiveCardUse(event || _status.event, player) || canPayCard(player, used));
},
usable: Infinity, toself: true, selectTarget: -1,
filterTarget(used, player, target) { return target === player; },
async content(event, trigger, player) {
if (typeof blockDraw !== "function") throw new Error("耸肩无视缺少格挡抽牌接口");
const rule = cardUpgradeRule("mengsan_songjianwushi");
await blockDraw(player, cardUpgradeLevel(event.card) ? rule.block : rule.baseBlock, rule.draw);
},
ai: { order: 7, result: { player: 1 }, tag: { draw: 1 } },
cardPrompt(used) {
const rule = cardUpgradeRule("mengsan_songjianwushi");
const block = cardUpgradeLevel(used) ? rule.block : rule.baseBlock;
return "梦三:主动使用消耗1费用。获得" + block + "点格挡(护甲),然后抽" + rule.draw + "张牌。";
},
};
translate.mengsan_songjianwushi = "耸肩无视";
translate.mengsan_songjianwushi_info = "梦三:主动使用消耗1费用。获得8点格挡(护甲),然后抽1张牌。";
// 【防御】沿用梦三护甲事件,保留脆弱与伤害抵扣等既有规则。
card.mengsan_fangyu = {
type: "basic",
fullimage: true,
image: "ext:术樱包/mengsan/assets/cards/mengsan_fangyu.png",
mengsanCost_shuying: cardCost({ name: "mengsan_fangyu" }),
enable(used, player, event) {
return !isActiveCardUse(event || _status.event, player) ||
canPayCard(player, used);
},
usable: Infinity,
toself: true,
selectTarget: -1,
filterTarget(used, player, target) { return target === player; },
async content(event, trigger, player) {
await player.changeHujia(5);
},
ai: { order: 7, result: { target: 1 } },
cardPrompt() { return translate.mengsan_fangyu_info; },
};
translate.mengsan_fangyu = "防御";
translate.mengsan_fangyu_info =
"梦三:主动使用消耗1费用。出牌阶段,对自己使用,获得5点格挡(护甲)。" +
"每回合使用次数不限。";
// 【桃】的回复量也由梦三牌本体提供;救援仍不消耗费用。
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[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();
for (const [name, definition] of Object.entries(card)) {
if (!isAttackCard({ name }) || typeof definition.cardPrompt !== "function") continue;
const prompt = definition.cardPrompt;
definition.cardPrompt = function (used) {
const text = prompt.call(this, used);
const owner = used && typeof get.owner === "function" ? get.owner(used) : null;
if (!isBattleActive() || !owner?.storage?.mengsanTangled_shuying || typeof text !== "string") return text;
return text.replace(/主动使用消耗\d+费用/, `主动使用消耗${cardCost(used || { name }, owner)}费用`);
};
}
return { card, translate, names: [...names, "mengsan_zhongsha", "mengsan_fangyu", "mengsan_fennu", "mengsan_feijianhuixuanbiao", "mengsan_jianbingdaji", "mengsan_quanshenzhuangji", "mengsan_rongrongzhiquan", "mengsan_shandianpili", "mengsan_shuangchongdaji", "mengsan_tiezhanbo", "mengsan_touchui", "mengsan_tupo", "mengsan_yubeidaji", "mengsan_wanmeidaji", "mengsan_yujin", "mengsan_fangxue", "mengsan_jianyi", "mengsan_pomie", "mengsan_songjianwushi"] };
}