import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { //江山如故·衰 //张举 jsrgqiluan: { usable: 2, enable: "chooseToUse", hiddenCard(player, name) { return (name === "sha" || name === "shan") && (player.getStat("skill").jsrgqiluan || 0) < 2 && player.countCards("he") > 0; }, filter(event, player) { return (event.filterCard({ name: "sha", isCard: true }, player, event) || event.filterCard({ name: "shan", isCard: true }, player, event)) && player.hasCard(card => lib.filter.cardDiscardable(card, player, "jsrgqiluan")); }, chooseButton: { dialog(event, player) { const vcards = []; if (event.filterCard({ name: "sha", isCard: true }, player, event)) vcards.push("sha"); if (event.filterCard({ name: "shan", isCard: true }, player, event)) vcards.push("shan"); return ui.create.dialog("起乱", [vcards, "vcard"], "hidden"); }, backup(links, player) { return { viewAs: { name: links[0][2], isCard: true }, filterCard: () => false, selectCard: -1, popname: true, async precontent(event, trigger, player) { delete event.result.skill; const stat = player.getStat("skill"); if (!stat.jsrgqiluan) stat.jsrgqiluan = 0; stat.jsrgqiluan++; const evt = event.getParent(); player.logSkill("jsrgqiluan"); const { cards, targets } = await player .chooseCardTarget({ prompt: "弃置任意张牌并选择等量角色", position: "he", filterCard: card => lib.filter.cardDiscardable(card, player, "jsrgqiluan"), filterTarget: lib.filter.notMe, selectCard: [1, Infinity], selectTarget: [1, Infinity], filterOk() { return ui.selected.cards.length === ui.selected.targets.length; }, forced: true, }) .forResult(); player.line(targets); targets.sortBySeat(); const cardsNum = cards.length; await player.discard(cards); let hasSomeoneUsed = false; for (const target of targets) { const cardName = event.result.card.name; const chooseToRespondEvent = target.chooseToRespond("是否替" + get.translation(player) + "打出一张" + get.translation(cardName) + "?", {name: cardName}); chooseToRespondEvent.set("ai", () => { const event = _status.event; return get.attitude(event.player, event.source) - 2; }); chooseToRespondEvent.set("source", player); chooseToRespondEvent.set("skillwarn", "替" + get.translation(player) + "打出一张" + get.translation(cardName)); chooseToRespondEvent.noOrdering = true; chooseToRespondEvent.autochoose = (cardName === "sha" ? lib.filter.autoRespondSha : lib.filter.autoRespondShan); const { bool, card, cards } = (await chooseToRespondEvent).result; if(bool){ hasSomeoneUsed = true; event.result.card = card; event.result.cards = cards; event.result._apply_args = { throw: false }; target.addExpose(0.2) await player.draw(cardsNum) break; } } if(!hasSomeoneUsed){ evt.goto(0); } }, }; }, prompt(links, player) { return `请选择【${get.translation(links[0][2])}】的目标`; }, }, //技能收益太低,不写AI了 }, jsrgxiangjia: { enable: "phaseUse", usable: 1, filter(event, player) { return player.getEquips(1).length > 0; }, viewAs: { name: "jiedao", isCard: true, }, filterCard: () => false, selectCard: -1, onuse(result, player) { player.addTempSkill("jsrgxiangjia_effect"); }, //技能收益太低,先不写AI了 subSkill: { effect: { charlotte: true, filter(event, player) { const card = get.autoViewAs({ name: "jiedao", isCard: true }); return ( event.skill === "jsrgxiangjia" && event.targets.some(current => { return current.isIn() && current.canUse(card, player); }) ); }, popup: false, async content(event, trigger, player) { const card = get.autoViewAs({ name: "jiedao", isCard: true }); for (const target of trigger.targets) { if (target.isIn() && target.canUse(card, player)) { const result = await target .chooseTarget(`是否对${get.translation(player)}使用【借刀杀人】?`, `操作提示:直接选择${get.translation(player)}使用【杀】的目标角色`, (card, player, target) => { const source = get.event("source"); return lib.card.jiedao.filterAddedTarget(card, player, target, source); }) .set("source", player) .set("ai", target => { const player = get.player(), card = get.autoViewAs({ name: "jiedao", isCard: true }); const source = get.event("source"); let eff = get.effect(source, card, player, player); _status.event.preTarget = source; eff += get.effect(target, card, player, player); delete _status.event.preTarget; return eff; }) .forResult(); if (result.bool) { await target.useCard(get.autoViewAs({ name: "jiedao", isCard: true }), [player, result.targets[0]]); } } } }, }, }, }, //陈蕃 jsrggangfen: { trigger: { global: "useCardToPlayer" }, filter(event, player) { if (event.card.name !== "sha") return false; if (event.player === player || event.player.countCards("h") <= player.countCards("h")) return false; return !event.targets.includes(player) && lib.filter.targetEnabled(event.card, event.player, player); }, logTarget: "player", prompt2(event, player) { return `你可以成为该角色使用的${get.translation(event.card)}的额外目标,并令所有其他角色也选择是否成为此牌的目标。然后该角色展示所有手牌,若其中的黑色牌数量小于此牌目标数,则此牌无效。`; }, check(event, player) { if ( event.targets.reduce((p, c) => { return p + get.effect_use(c, event.card, event.player, player) > 0; }, 0) >= 0 ) return false; //绝对保守策略:队友数大于来源牌数才发动技能 return game.countPlayer(current => event.targets.includes(current) || get.attitude(current, player) > 0) > event.player.countCards("h"); }, async content(event, trigger, player) { trigger.targets.add(player); const source = trigger.player; const targets = game .filterPlayer(current => { return current !== player && current !== source && !trigger.targets.includes(current) && lib.filter.targetEnabled(trigger.card, source, current); }) .sortBySeat(); for (const target of targets) { const bool = await target .chooseBool(`是否也成为${get.translation(trigger.card)}的目标?`, `若最终目标数大于${get.translation(source)}手牌中的黑色牌数,则此牌无效。`) .set("ai", () => get.event("choice")) .set( "choice", (() => { if (get.attitude(target, player) < 0) return false; return game.countPlayer(current => trigger.targets.includes(current) || get.attitude(current, player) > 0) > trigger.player.countCards("h"); })() ) .forResult("bool"); if (bool) { target.addExpose(0.15); target.chat("我也上!"); target.line(source); trigger.targets.add(target); game.log(target, "也成为了", trigger.card, "的目标"); await game.asyncDelayx(); } } await source.showHandcards(); const blackNum = source.countCards("h", card => get.color(card, source) === "black"); if (blackNum < trigger.targets.length) { trigger.getParent().all_excluded = true; trigger.targets.length = 0; trigger.untrigger(); } }, ai: { expose: 0.2, threaten: 4.5, }, }, jsrgdangren: { zhuanhuanji: true, enable: "chooseToUse", filter(event, player) { if (player.storage.jsrgdangren) return false; const card = get.autoViewAs({ name: "tao", isCard: true }); return event.filterCard(card, player, event) && event.filterTarget(card, player, player); }, viewAs: { name: "tao", isCard: true }, filterTarget(card, player, target) { return target === player; }, selectTarget: -1, filterCard() { return false; }, selectCard: -1, check() { const player = get.player(); if (player.isDying()) return true; return ( game.countPlayer(current => { return current.hp <= 2 && get.attitude(player, current) > 0; }) > game.countPlayer(current => { return current.hp <= 2 && get.attitude(player, current) <= 0; }) ); }, prompt: "视为对自己使用【桃】", async precontent(event, trigger, player) { player.logSkill("jsrgdangren"); player.changeZhuanhuanji("jsrgdangren"); delete event.result.skill; }, hiddenCard(player, name) { return name === "tao"; }, mark: true, marktext: "☯", intro: { content(storage) { if (storage) return "当你可以对其他角色使用【桃】时,你须视为使用之。"; return "当你需要对自己使用【桃】时,你可以视为使用之"; }, }, group: "jsrgdangren_save", subSkill: { save: { trigger: { player: "chooseToUseBegin" }, filter(event, player) { if (event.responded || !player.storage.jsrgdangren) return false; const card = get.autoViewAs({ name: "tao", isCard: true }); if (!event.filterCard(card, player, event)) return false; const backup = _status.event; _status.event = event; const hasTarget = game.hasPlayer(current => { return current !== player && event.filterTarget(card, player, current); }); _status.event = backup; return hasTarget; }, async cost(event, trigger, player) { const card = get.autoViewAs({ name: "tao", isCard: true }); const backup = _status.event; _status.event = trigger; const targets = game.filterPlayer(current => { return current !== player && trigger.filterTarget(card, player, current); }); _status.event = backup; if (targets.length === 1) { event.result = { bool: true, targets }; } else { event.result = await player .chooseTarget(true, "当仁:请选择【桃】的目标", (card, player, target) => { return get.event("targets").includes(target); }) .set("targets", targets) .forResult(); } }, async content(event, trigger, player) { trigger.result = { bool: true, card: { name: "tao", isCard: true }, targets: event.targets, }; trigger.untrigger(); trigger.set("responded", true); player.changeZhuanhuanji("jsrgdangren"); }, }, }, }, //卢植 jsrgruzong: { trigger: { player: "phaseEnd" }, filter(event, player) { const target = lib.skill.jsrgruzong.getTarget(player); if (!target) return false; const hs = player.countCards("h"); if (target !== player) return target.countCards("h") > hs; return game.hasPlayer(current => current !== player && current.countCards("h") < hs); }, getTarget(player) { const targets = []; player.checkHistory("useCard", evt => targets.addArray(evt.targets)); return targets.length === 1 ? targets[0] : null; }, frequent: true, async cost(event, trigger, player) { const target = lib.skill.jsrgruzong.getTarget(player); if (target !== player) { const bool = await player.chooseBool(get.prompt("jsrgruzong", target), "将手牌数摸至与该角色相同").set("frequentSkill", "jsrgruzong"); if (bool) { event.result = { bool, targets: [target], cost_data: "drawToOthers", }; } } else { event.result = await player .chooseTarget(get.prompt("jsrgruzong"), "令任意名角色将手牌数摸至与你相同", (card, player, target) => { return target.countCards("h") < player.countCards("h"); }) .set("ai", target => { const player = get.player(); return (get.attitude(player, target) * Math.sqrt(player.countCards("h") - target.countCards("h"))) / (target.hasSkillTag("nogain") ? 1 : 10); }); } }, async content(event, trigger, player) { if (event.cost_data === "drawToOthers") { const num = Math.min(5, event.targets[0].countCards("h") - player.countCards("h")); if (num > 0) await player.draw(num); } else { const num = player.countCards("h"); game.asyncDraw(event.targets.sortBySeat(), target => { return Math.min(5, num - target.countCards("h")); }); } }, }, jsrgdaoren: { enable: "phaseUse", usable: 1, filter(event, player) { return player.countCards("h") > 0; }, filterCard: true, position: "h", discard: false, lose: false, delay: false, filterTarget: lib.filter.notMe, check(card) { return 6 - get.value(card); }, async content(event, trigger, player) { const target = event.target; await player.give(event.cards, target); const targets = game .filterPlayer(current => { return player.inRange(current) && target.inRange(current); }) .sortBySeat(); for (const current of targets) { player.line(current); await current.damage("nocard"); await game.asyncDelayx(); } }, ai: { order: 2, result: { player(player, target) { const targets = game.filterPlayer(current => { return player.inRange(current) && target.inRange(current); }); if (targets.length === 0) return false; return targets.reduce((p, c) => { let eff = get.damageEffect(c, player, player); if (eff < 0 && c.hp <= 2) { const att = get.attitude(player, c); if (att > 0) eff *= Math.sqrt(att); } return p + eff; }, 0); }, }, }, }, //刘表 jsrgyansha: { trigger: { player: "phaseZhunbeiBegin" }, async cost(event, trigger, player) { //AI摆了,交给157了 event.result = await player .chooseTarget(get.prompt("jsrgyansha"), "你可以选择任意名角色,视为对这些角色使用【五谷丰登】,然后未被选择的角色依次可以将一张装备牌当作【杀】对目标角色使用。", [1, Infinity], (card, player, target) => { return player.canUse({ name: "wugu", isCard: true }, target); }) .forResult(); }, async content(event, trigger, player) { const targets = event.targets.slice(0).sortBySeat(); await player.useCard({ name: "wugu", isCard: true }, targets); const players = game.filterPlayer(current => !targets.includes(current)).sortBySeat(); for (const current of players) { const aliveTargets = targets.filter(current => current.isIn()); if (!aliveTargets.length) break; if ( current.isIn() && (current.countCards("e") > 0 || current.hasCard(card => { if (_status.connectMode) return true; return get.type(card) === "trick"; }, "hs")) ) { } const result = await current .chooseCardTarget({ prompt: `是否将一张装备牌当作【杀】对${get.translation(targets)}${targets.length > 1 ? "中的一名角色" : ""}使用?`, position: "hes", filterCard(card) { return get.type(card) === "equip"; }, filterTarget(card, player, target) { if (!get.event("targets").includes(target)) return false; card = get.autoViewAs({ name: "sha" }, ui.selected.cards); return player.canUse(card, target, false); }, ai1(card) { return 7 - get.value(card); }, ai2(target) { const player = get.player(), card = get.autoViewAs({ name: "sha" }, ui.selected.cards); return get.effect(target, card, player, player); }, targets: aliveTargets, }) .forResult(); if (result.bool) { await current.useCard(get.autoViewAs({ name: "sha" }, result.cards), result.cards, result.targets); } } }, }, jsrgqingping: { trigger: { player: "phaseJieshuBegin" }, frequent: true, filter(event, player) { const targets = game.filterPlayer(current => player.inRange(current)), hs = player.countCards("h"); return targets.length > 0 && targets.every(current => current.countCards("h") <= hs); }, async content(event, trigger, player) { await player.draw(game.countPlayer(current => player.inRange(current))); }, }, //张奂 jsrgzhushou: { trigger: { global: "phaseEnd" }, filter(event, player) { if (!player.getHistory("lose").length) return false; const card = lib.skill.jsrgzhushou.getMaxCard(); if (!card) return false; return game.hasPlayer(current => { return current.hasHistory("lose", evt => { return evt.cards2 && evt.cards2.includes(card); }); }); }, async cost(event, trigger, player) { const card = lib.skill.jsrgzhushou.getMaxCard(); const targets = game.filterPlayer(current => { return current.hasHistory("lose", evt => { return evt.cards2 && evt.cards2.includes(card); }); }); const result = await player .chooseTarget(get.prompt("jsrgzhushou"), `选择一名本回合内失去过${get.translation(card)}的角色,对其造成1点伤害。`, (card, player, target) => { return get.event("targets").includes(target); }) .set("targets", targets) .set("ai", target => { const player = get.player(); return get.damageEffect(target, player, player); }) .forResult(); if (result.bool) { event.result = { bool: true, targets: result.targets, cards: [card], }; } }, async content(event, trigger, player) { await player.showCards(event.cards, `${get.translation(player)}发动了【诛首】`); await event.targets[0].damage("nocard"); }, getMaxCard() { let cardsLost = []; game.getGlobalHistory("cardMove", evt => { if (evt.name === "cardsDiscard" || (evt.name === "lose" && evt.position === ui.discardPile)) { cardsLost.addArray(evt.cards); } }); cardsLost = cardsLost.filterInD("d"); let max = 0; return cardsLost.reduce( (maxCard, card) => { const num = get.number(card, false); if (num > max) { max = num; return card; } else if (num === max) { return void 0; } return maxCard; }, void 0 ); }, }, jsrgyangge: { global: "jsrgyangge_mizhao", subSkill: { mizhao: { //直接继承mizhao inherit: "mizhao", usable: void 0, filter(event, player) { return player.countCards("h") > 0 && player.isMinHp() && game.hasPlayer(current => lib.skill.jsrgyangge_mizhao.filterTarget(void 0, player, current)); }, filterTarget(card, player, target) { if (player === target) return false; return target.hasSkill("jsrgyangge") && !target.hasMark("jsrgyangge"); }, prompt() { const player = get.player(); const targets = game.filterPlayer(current => lib.skill.jsrgyangge_mizhao.filterTarget(void 0, player, current)); return `对${get.translation(targets)}${targets.length > 1 ? "中的一人" : ""}发动【密诏】`; }, }, }, }, //董卓 jsrgguanshi: { enable: "phaseUse", usable: 1, viewAs: { name: "huogong" }, viewAsFilter(player) { return player.hasCard(card => get.name(card) === "sha", "hs"); }, filterCard(card) { return get.name(card) === "sha"; }, selectTarget: [1, Infinity], onuse(result, player) { player.addTempSkill("jsrgguanshi_effect"); }, position: "hs", //这个AI难写,交给157了! check() { return -1; }, ai: {}, subSkill: { effect: { trigger: { player: ["useCardToBefore", "useCardToAfter", "useCardToExcluded", "useCardToOmitted", "useCardToCancelled"], }, forced: true, charlotte: true, popup: false, firstDo: true, priority: 100, filter(event, player, name) { if (event.type !== "card" || event.skill !== "jsrgguanshi") return false; const isUnhurted = event.card.storage && event.card.storage.jsrgguanshi; if (name === "useCardToBefore") return isUnhurted; return ( !isUnhurted && event.target && !player.hasHistory("sourceDamage", evt => { return evt.card === event.card && evt.getParent() === event; }) ); }, async content(event, trigger, player) { if (event.triggername === "useCardToBefore") { trigger.setContent(lib.card.juedou.content); } else { const card = trigger.card; if (!card.storage) card.storage = {}; card.storage.jsrgguanshi = true; } }, }, }, }, jsrgcangxiong: { trigger: { player: "loseAfter", global: ["gainAfter", "loseAsyncAfter"], }, getIndex(event, player, triggername) { if (event.type === "discard") { return event.getl(player).cards2 || []; } else if (event.name === "gain") { if (event.player === player) return; const cardsGained = event.getg(event.player), cardsLost = event.getl(player).cards2; return cardsLost.filter(card => cardsGained.includes(card)); } else if (event.name === "loseAsync" && event.type === "gain") { const cardsLost = event.getl(player).cards2; if (!cardsLost.length) return []; const cardsGained = []; game.countPlayer2( current => { if (current !== player) cardsGained.addArray(event.getg(current)); }, null, true ); return cardsLost.filter(card => cardsGained.includes(card)); } return []; }, filter(event, player, name, card) { if (player.isDisabledJudge()) return false; if (event.type === "discard") return get.position(card, true) === "d"; else { const owner = game.findPlayer2( current => { return current !== player && event.getg(current).includes(card); }, null, true ); return owner.getCards("h").includes(card); } }, prompt2(event, player, name, card) { return `将${get.translation(card)}作为蓄谋牌置入判定区${player.isPhaseUsing() ? ",然后摸一张牌。" : ""}`; }, async content(event, trigger, player) { const card = event.indexedData; if (get.position(card) === "d") { player.$gain2(card, false); game.log(player, "使用", card, "进行了明目张胆的蓄谋"); } else { get.owner(card).$giveAuto(card, player, false); } await game.asyncDelayx(); await player.addJudge({ name: "xumou_jsrg" }, [card]); if (player.isPhaseUsing()) await player.draw(); }, }, jsrgjiebing: { derivation: "jsrgbaowei", trigger: { player: "phaseZhunbeiBegin" }, forced: true, juexingji: true, skillAnimation: true, animationColor: "gray", filter(event, player) { const target = lib.skill.jsrgjiebing.getZhugong(player); return ( target && player.countCards("j", card => { return (card.viewAs || card.name) == "xumou_jsrg"; }) > target.getHp() ); }, async content(event, trigger, player) { await player.gainMaxHp(2); await player.recover(2); await player.addSkills("jsrgbaowei"); }, ai: { combo: "jsrgcangxiong", }, getZhugong(player) { const mode = get.mode(); if (mode === "identity") { if (_status.mode === "purple") { return game.findPlayer(current => { return current.isZhu2() && current.identity.slice(0, 1) === player.identity.slice(0, 1); }); } return game.findPlayer(current => current.isZhu2()); } else { return game.findPlayer(current => current.getSeatNum() === 1); } }, }, jsrgbaowei: { trigger: { player: "phaseJieshuBegin" }, forced: true, filter(event, player) { return game.hasPlayer(current => { return current !== player && (current.getHistory("useCard").length > 0 || current.getHistory("respond").length > 0); }); }, async content(event, trigger, player) { const targets = game.filterPlayer(current => { return current !== player && (current.getHistory("useCard").length > 0 || current.getHistory("respond").length > 0); }); if (targets.length > 2) { await player.loseHp(2); } else { let target; if (targets.length === 1) [target] = targets; else [target] = await player .chooseTarget(true, "暴威:对一名目标角色造成2点伤害", (card, player, target) => { return get.event("targets").includes(target); }) .set("targets", targets) .set("ai", target => { const player = get.player(); return get.damageEffect(target, player, player) * (1.1 - get.sgn(get.attitude(player, target))); }).forResult("targets"); player.line(target, "green"); target.damage(2); } }, ai: { //这里应该写一个强命AI,但是比较麻烦,可能还要写全局AI技能,先摆了 }, }, //阳球 jsrgsaojian: { enable: "phaseUse", usable: 1, filterTarget(card, player, target) { return target.countCards("h") > 0; }, async content(event, trigger, player) { const target = event.target; if (target.countCards("h") > 0) { const [card] = await player .choosePlayerCard(target, true, "h", "visible") .set("ai", button => { //开摆,直接随机选,不考虑有的没的 return get.event().getRand(button.link.cardid); }) .forResult("cards"); const videoId = lib.status.videoId++; game.addVideo("showCards", player, [`${get.translation(player)}对${get.translation(target)}发动了【扫奸】`, get.cardsInfo([card])]); game.broadcastAll( (card, id, player, target) => { if (target === game.me) return; const dialog = ui.create.dialog(`${get.translation(player)}对${get.translation(target)}发动了【扫奸】`, [card]); dialog.forcebutton = true; dialog.videoId = id; }, card, videoId, player, target ); await game.asyncDelay(3); game.broadcastAll("closeDialog", videoId); for (let i = 0; i < 5; i++) { const discarded = await target .chooseToDiscard("h", true) .set("ai", card => { //开摆,直接随机弃牌,不考虑有的没的 return get.event().getRand(card.cardid); }) .forResult("cards"); if (!discarded || !discarded.length || discarded[0] === card) break; } if (target.countCards("h") > player.countCards("h")) player.loseHp(); } }, ai: { order: 7, result: { target(player, target) { //对面牌比自己少,就放心大胆弃牌 if (target.countCards("h") <= player.countCards("h") - 1) return -3; //残血别浪 if (player.hp === 1 && get.effect(player, { name: "losehp" }, player, player) < 0) return 0; //血多无所谓 return -1; }, }, tag: { loseCard: 1, discard: 1, }, }, }, //张角 jsrgxiangru: { trigger: { global: "damageBegin2" }, filter(event, player) { if (event.player.hp + event.player.hujia > event.num) return false; const source = event.source; if (!source || !source.isIn()) return false; if (player !== event.player) { return event.player.isDamaged() && player !== source && player.countCards("he") > 1; } return game.hasPlayer(current => { return current !== source && current !== player && current.isDamaged() && current.countCards("he") >= 1; }); }, async cost(event, trigger, player) { const target = trigger.player, source = trigger.source; const targets = ( target === player ? game.filterPlayer(current => { return current !== source && current !== player && current.isDamaged() && current.countCards("he") >= 1; }) : [player] ).filter(current => current !== source && current !== target && current.countCards("he") >= 1); targets.sortBySeat(); let cards = null, giver = null; const eventId = get.id(), send = (target, source, current, eventId, eventNum) => { lib.skill.jsrgxiangru.chooseTarget(target, source, current, eventId, eventNum); game.resume(); }, humans = targets.filter(current => current === game.me || current.isOnline()), locals = targets.slice(0); locals.removeArray(humans); //让读条不消失并显示读条 event._global_waiting = true; let time = 10000; if (lib.configOL && lib.configOL.choose_timeout) time = parseInt(lib.configOL.choose_timeout) * 1000; targets.forEach(current => current.showTimer(time)); //先处理人类玩家 if (humans.length > 0) { const solve = function (resolve, reject) { return function (result, player) { if (result && result.bool && !cards) { resolve(); giver = player; cards = result.cards; } else reject(); }; }; await Promise.any( humans.map(current => { return new Promise(async (resolve, reject) => { if (current.isOnline()) { current.send(send, target, source, current, eventId, trigger.num); current.wait(solve(resolve, reject)); } else { const next = lib.skill.jsrgxiangru.chooseTarget(target, source, current, eventId, trigger.num); const solver = solve(resolve, reject); if (_status.connectMode) game.me.wait(solver); const result = await next.forResult(); if (_status.connectMode && !cards) game.me.unwait(result, current); else solver(result, current); } }); }) ).catch(() => {}); game.broadcastAll("cancel", eventId); } //再处理单机的他人控制玩家/AI玩家 if (!cards && locals.length > 0) { for (let current of locals) { if (cards) continue; const result = await lib.skill.jsrgxiangru.chooseTarget(target, source, current).forResult(); if (result.bool) { giver = current; cards = result.cards; } } } //清除读条 delete event._global_waiting; for (var i of targets) i.hideTimer(); //处理结果 if (cards) { event.result = { bool: true, targets: [player === target ? giver : target], cost_data: { cards, giver }, }; game.broadcastAll(result => console.log(result), event.result); } }, async content(event, trigger, player) { const { giver, cards } = event.cost_data; await giver.give(cards, trigger.source); await trigger.cancel(); }, chooseTarget(target, source, current, eventId, eventNum) { const goon = (() => { //资敌的代价太大,因此不到万不得已不给牌 if (get.attitude(current, target) < 4) return false; if (current.countCards("hs", card => current.canSaveCard(card, target)) >= 1 - (target.hp + target.hujia - eventNum)) return false; if (target == get.zhu(current) || get.attitude(current, source) > 0) return "长崎素世一般的恳求"; return "给点废牌算了"; })(); const next = current.chooseCard("he", 2); next.set("prompt", `是否对${get.translation(target)}发动【相濡】?`); next.set("prompt2", `选择交给${get.translation(source)}两张牌,然后防止${get.translation(target)}即将受到的致命伤害。`); next.set("id", eventId); next.set("_global_waiting", true); next.set("ai", card => { if (goon) { if (goon.includes("长崎素世")) return 20 - get.value(card); return 5 - get.value(card); } return 0; }); return next; }, }, jsrgwudao: { derivation: "jsrgjinglei", trigger: { global: "dying" }, forced: true, juexingji: true, skillAnimation: true, animationColor: "gray", filter(event, player) { return player.countCards("h") === 0; }, async content(event, trigger, player) { player.awakenSkill("jsrgwudao"); await player.gainMaxHp(); await player.recover(); await player.addSkills("jsrgjinglei"); }, }, jsrgjinglei: { trigger: { player: "phaseZhunbeiBegin" }, filter(event, player) { return game.hasPlayer(current => !current.isMinHandcard()); }, async cost(event, trigger, player) { event.result = await player .chooseTarget(get.prompt("jsrgjinglei"), "选择一名其他角色,令任意名手牌数之和小于其的角色各对其造成1点雷属性伤害", (card, player, target) => !target.isMinHandcard()) .set("ai", target => { //AI写的比较简单:不打队友,根据手牌数平方根酌情打牌多的 const player = get.player(); if (get.attitude(player, target) >= 0) return false; return get.damageEffect(target, player, player, "thunder") * Math.sqrt(target.countCards("h")); }) .forResult(); }, async content(event, trigger, player) { const [target] = event.targets; const maxmium = target.countCards("h"); const next = player.chooseTarget(true, `选择任意名手牌数之和小于${maxmium}的角色`, [1, Infinity]); next.set("promptbar", "none"); next.set("maxmium", maxmium); next.set("complexTarget", true); next.set("filterTarget", (card, player, target) => { const selected = ui.selected.targets, maxmium = get.event("maxmium"); return ( selected.reduce((p, c) => { return p + c.countCards("h"); }, target.countCards("h")) < maxmium ); }); next.set("ai", target => { //谁手牌少就选谁,没啥要考虑的 return 1 / (1 + target.countCards("h")); }); const sources = await next.forResult("targets"); sources.sortBySeat(); player.line(sources, "thunder"); for (let source of sources) { if (!source.isIn() || !target.isIn()) continue; target.damage(source, "thunder"); } }, }, //宋皇后 jsrgzhongzen: { trigger: { player: "phaseDiscardBegin" }, forced: true, filter(event, player) { const hs = player.countCards("h"); return game.hasPlayer(current => { if (current === player) return false; const hs2 = current.countCards("h"); return hs2 > 0 && hs2 < hs; }); }, logTarget(event, player) { const hs = player.countCards("h"); return game.filterPlayer(current => { if (current === player) return false; const hs2 = current.countCards("h"); return hs2 > 0 && hs2 < hs; }); }, async content(event, trigger, player) { const targets = event.targets.slice(0); targets.forEach(async target => { if (player.isIn() && target.countCards("h") > 0) { //暂时没有写给牌AI await target.chooseToGive(player, "h", true); } }); }, group: "jsrgzhongzen_discard", subSkill: { discard: { trigger: { player: "phaseDiscardEnd" }, forced: true, filter(event, player) { if (player.countCards("he") === 0) return false; const cards = []; player.getHistory("lose", evt => { if (evt.type === "discard" && evt.getParent("phaseDiscard") === event) cards.addArray(evt.cards); }); return ( cards.length > player.hp && cards.reduce((num, card) => { if (num <= player.hp && get.suit(card, false) === "spade") num++; return num; }, 0) > player.hp ); }, async content(event, trigger, player) { await player.chooseToDiscard(true, "he", player.countCards("he")); }, }, }, }, jsrgxuchong: { trigger: { target: "useCardToTargeted" }, async cost(event, trigger, player) { const current = _status.currentPhase; const choices = ["摸一张牌"]; if (current) choices.push(`令${get.translation(current)}本回合的手牌上限+2`); //暂时不写AI,默认摸牌,先爽再说 const control = await player.chooseControl("cancel2").set("choiceList", choices).forResult("control"); if (control !== "cancel2") { event.result = { bool: true, targets: control === "选项二" ? [current] : [], }; } }, async content(event, trigger, player) { if (event.targets && event.targets.length) { const [target] = event.targets; target.addTempSkill("jsrgxuchong_effect"); target.addMark("jsrgxuchong_effect", 2, false); } else { await player.draw(); } await player.gain(lib.card.ying.getYing(1), "gain2"); }, subSkill: { effect: { mod: { maxHandcard(player, num) { return num + player.countMark("jsrgxuchong_effect"); }, }, onremove: true, charlotte: true, intro: { content: "手牌上限+#", }, }, }, }, //曹节王甫 jsrgzonghai: { trigger: { global: "dying" }, logTarget: "player", round: 1, filter(event, player) { return event.player !== player && event.player.hp <= 0; }, check(event, player) { //理论上是小完杀+卖血 //先粗略地写一写,后面等157补 return get.attitude(player, event.player) < 0; }, async content(event, trigger, player) { const target = trigger.player; const targets = await target .chooseTarget([1, 2], true, "请选择至多两名角色", `${get.translation(player)}对你发动了【纵害】。你可以选择至多两名角色,只有这两名角色可以使用牌拯救你,且当此次濒死结算结束后,这两名角色均会受到来自${get.translation(player)}的1点伤害。`) .set("ai", target => { //自救还要挨一刀,最好的反制方法就是跟对面爆了 const evt = get.event(), player = evt.player, source = evt.getParent().player; return get.damageEffect(target, source, player); }) .set("forceDie", true) .forResult("targets"); target.line(targets); game.log(target, "选择了", targets); targets.sortBySeat(_status.currentPhase || player); const allPlayers = game.filterPlayer().sortBySeat(); if (!trigger._jsrgzonghai_id) trigger._jsrgzonghai_id = get.id(); const id = trigger._jsrgzonghai_id; allPlayers.forEach(target => { if (!targets.includes(target)) { target.addTempSkill("jsrgzonghai_blocker"); target.markAuto("jsrgzonghai_blocker", [id]); } }); target .when("dyingAfter") .vars({ id, allPlayers, targets, source: player }) .assign({ forceDie: true }) .then(() => { allPlayers.forEach(target => { target.unmarkAuto("jsrgzonghai_blocker", [id]); if (!target.getStorage("jsrgzonghai_blocker").length) target.removeSkill("jsrgzonghai_blocker"); }); if (source.isIn()) { targets.forEach(target => target.damage(source)); } }); }, subSkill: { blocker: { charlotte: true, onremove: true, mod: { cardSavable: () => false, cardEnabled: () => false, }, }, }, }, jsrgjueyin: { trigger: { player: "damageEnd" }, filter(event, player) { return player.getHistory("damage")[0] === event; }, async content(event, trigger, player) { await player.draw(3); const targets = game.filterPlayer().sortBySeat(); targets.forEach(current => { current.addTempSkill("jsrgjueyin_damage"); current.addMark("jsrgjueyin_damage", 1, false); }); }, subSkill: { damage: { onremove: true, charlotte: true, trigger: { player: "damageBegin1" }, forced: true, async content(event, trigger, player) { trigger.num++; }, intro: { content: "本回合受到的伤害+#", }, }, }, }, //梦袁绍 jsrgzhimeng: { trigger: { player: "phaseZhunbeiBegin" }, logTarget() { return game.filterPlayer(current => current.countCards("h") > 0).sortBySeat(); }, prompt: "是否发动【执盟】?", async content(event, trigger, player) { const { cards } = await game.cardsGotoOrdering(get.cards(game.countPlayer())); await player.showCards(cards, `${get.translation(player)}发动了【执盟】`); const targets = game.filterPlayer(current => current.countCards("h") > 0).sortBySeat(); //选牌 const showCardEvent = player.chooseCardOL(targets, `${get.translation(player)}发动了【执盟】,请展示一张手牌`, true); showCardEvent.set("ai", card => { if (get.event("_suits").includes(get.suit(card))) return 1 + Math.random(); return (1 - get.value(card)) * Math.random(); }); showCardEvent.set( "_suits", cards.map(card => get.suit(card, false)) ); showCardEvent.set("source", player); showCardEvent.set("aiCard", target => { const hs = target.getCards("h"); return { bool: true, cards: [hs.randomGet()] }; }); showCardEvent._args.remove("glow_result"); const result = await showCardEvent.forResult(); //选完了 展示牌 const videoId = lib.status.videoId++; const cardsToShown = []; for (let i = 0; i < targets.length; i++) { cardsToShown.push(result[i].cards[0]); game.log(targets[i], "展示了", result[i].cards[0]); } game.broadcastAll( (targets, cards, id, player) => { const dialog = ui.create.dialog(get.translation(player) + "发动了【执盟】", cards); dialog.videoId = id; const getName = function (target) { if (target._tempTranslate) return target._tempTranslate; var name = target.name; if (lib.translate[name + "_ab"]) return lib.translate[name + "_ab"]; return get.translation(name); }; for (let i = 0; i < targets.length; i++) { dialog.buttons[i].querySelector(".info").innerHTML = getName(targets[i]) + get.translation(get.suit(cards[i], targets[i])); } }, targets, cardsToShown, videoId, player ); await game.asyncDelay(4); game.broadcastAll("closeDialog", videoId); //展示完了 开始拿牌 const suitsMap = {}; for (let i = 0; i < targets.length; i++) { const target = targets[i], card = cardsToShown[i], suit = get.suit(card, target); if (!(suit in suitsMap)) suitsMap[suit] = target; else suitsMap[suit] = null; } const gain_list = []; for (const data of Object.entries(suitsMap)) { const [suit, target] = data; if (target) { const cardsToGain = cards.filter(card => get.suit(card, false) === suit); if (cardsToGain.length) gain_list.push([target, cardsToGain]); } } if (gain_list.length) { await game .loseAsync({ gain_list, animate: "gain2", }) .setContent("gaincardMultiple"); } }, }, jsrgtianyu: { trigger: { global: ["loseAsyncAfter", "cardsDiscardAfter"] }, frequent: true, getIndex(event) { return lib.skill.jsrgtianyu.getCards(event); }, filter(event, player, triggername, card) { return get.position(card, true) === "d"; }, frequent(event, player, triggername, card) { return get.value(card, player) > 0; }, getCards(event) { const cards = event.getd().filter(card => { return get.type(card, null, false) === "equip" || get.tag(card, "damage", null, false) > 0; }); if (!cards.length) return []; game.checkGlobalHistory("cardMove", evt => { if (evt.name === "lose") cards.removeArray(evt.cards); }); return cards; }, prompt2(event, player, triggername, card) { return `获得即将进入弃牌堆的${get.translation(card)}`; }, async content(event, trigger, player) { const cards = event.indexedData; await player.gain(cards, "gain2"); }, }, jsrgzhuni: { enable: "phaseUse", usable: 1, filterTarget: true, selectTarget: -1, multitarget: true, multiline: true, async content(event, trigger, player) { let targets = event.targets.slice(0), results = [], forceTargets = []; //XXX自选选择目标 if (player.hasSkill("jsrghezhi")) { forceTargets = targets.filter(current => current !== player && current.group === "qun"); targets.removeArray(forceTargets); } //让读条不消失 event._global_waiting = true; const send = (player, source) => { lib.skill.jsrgzhuni.chooseTarget(player, source); game.resume(); }; const solve = (result, chooser) => { let target; if (!result || !result.targets || result === "ai") { target = game.filterPlayer(current => current !== player).randomGet(); } else target = result.targets[0]; results.push([chooser, target]); if (chooser === player) { forceTargets.forEach(current => results.push([current, target])); } }; let time = 10000; if (lib.configOL && lib.configOL.choose_timeout) time = parseInt(lib.configOL.choose_timeout) * 1000; targets.forEach(current => current.showTimer(time)); //分别处理人类玩家和其他玩家 const humans = targets.filter(current => current === game.me || current.isOnline()), locals = targets.slice(0); locals.removeArray(humans); //Promise,爽!清瑶你有种抄过去 if (humans.length) { await Promise.all( humans.map((current, index) => { return new Promise(async (resolve, reject) => { if (current.isOnline()) { current.send(send, current, player); current.wait((result, player) => { solve(result, player); resolve(); }); } else if (current == game.me) { const next = lib.skill.jsrgzhuni.chooseTarget(current, player); const solver = (result, player) => { solve(result, player); resolve(); }; if (_status.connectMode) game.me.wait(solver); const result = await next.forResult(); if (_status.connectMode) game.me.unwait(result, current); else solver(result, current); } }); }) ); } if (locals.length) { for (let current of locals) { const next = lib.skill.jsrgzhuni.chooseTarget(current, player); const result = await next.forResult(); solve(result, current); } } //清除读条 delete event._global_waiting; for (var i of targets) i.hideTimer(); //统计票数 const ticketsMap = new Map(); results.forEach(data => { const [source, current] = data; source.line(current); game.log(source, forceTargets.includes(source) ? "自愿选择" : "选择了", current, "作为讨伐目标"); ticketsMap.set(current, (ticketsMap.get(current) || 0) + 1); }); console.log(ticketsMap); let maxTicket = 0; const target = ticketsMap.entries().reduce((target, data) => { console.log(data); const [current, ticket] = data; if (ticket > maxTicket) { maxTicket = ticket; return current; } else if (ticket === maxTicket) return false; else return target; }, false); //上Buff if (target) { game.log(target, "成为了", "#g【执盟】", "的讨伐目标"); player.addTempSkill("jsrgzhuni_effect"); player.markAuto("jsrgzhuni_effect", [target]); } }, ai: { order: 10, result: { player: 1 }, threaten: 1.8, }, chooseTarget(player, source) { const next = player.chooseTarget(`${get.translation(source)}发动了【执盟】,请选择一名讨伐目标`, (card, player, target) => target !== source, true); next.set("ai", target => -get.attitude(get.player(), target)); next.set("animate", false); next.set("_global_waiting", true); return next; }, subSkill: { effect: { onremove: true, mod: { targetInRange(card, player, target) { if (player.getStorage("jsrgzhuni_effect").includes(target)) { return true; } }, cardUsableTarget(card, player, target) { if (player.getStorage("jsrgzhuni_effect").includes(target)) { return true; } }, }, charlotte: true, intro: { content: "对$使用牌无距离和次数限制", }, }, }, }, jsrghezhi: { zhuSkill: true, locked: true, }, //江山如故·合 //蓄谋临时禁用 xumou_jsrg_temp: { charlotte: true, onremove: true, mod: { cardEnabled(card, player) { if (!card.storage || !card.storage.xumou_jsrg) return; if (player.getStorage("xumou_jsrg_temp").includes(get.name(card, false))) return false; }, }, }, //404诸葛亮 jsrgwentian: { audio: 2, trigger: { player: ["phaseZhunbeiBegin", "phaseJudgeBegin", "phaseDrawBegin", "phaseUseBegin", "phaseDiscardBegin", "phaseJieshuBegin"], }, usable: 1, prompt2: "观看牌堆顶的五张牌,将其中一张交给其他角色,并将其余牌置于牌堆顶或牌堆底", group: "jsrgwentian_viewas", async content(event, trigger, player) { const cards = get.cards(5); game.cardsGotoOrdering(cards); const { result } = await player.chooseButton(["问天:将一张牌交给一名其他角色", cards], true); if (result.bool) { const { result: result2 } = await player.chooseTarget(`将${get.translation(result.links)}交给一名其他角色`, lib.filter.notMe, true).set("ai", target => { return get.attitude(get.player(), target); }); if (result2.bool) { cards.removeArray(result.links); const target = result2.targets[0]; player.line(target, "green"); await target.gain(result.links, "gain2").set("giver", player); } } const next = player.chooseToMove(); next.set("list", [["牌堆顶", cards.filterInD()], ["牌堆底"]]); next.set("prompt", "问天:点击将牌移动到牌堆顶或牌堆底"); next.processAI = list => { const cards = list[0][1], player = _status.event.player; const top = []; const judges = player.getCards("j"); let stopped = false; if (!player.hasWuxie()) { for (let i = 0; i < judges.length; i++) { const judge = get.judge(judges[i]); cards.sort((a, b) => judge(b) - judge(a)); if (judge(cards[0]) < 0) { stopped = true; break; } else { top.unshift(cards.shift()); } } } let bottom; if (!stopped) { cards.sort((a, b) => get.value(b, player) - get.value(a, player)); while (cards.length) { if (get.value(cards[0], player) <= 5) break; top.unshift(cards.shift()); } } bottom = cards; return [top, bottom]; }; const { result: { moved }, } = await next; const top = moved[0]; const bottom = moved[1]; top.reverse(); game.cardsGotoPile(top.concat(bottom), ["top_cards", top], (event, card) => { if (event.top_cards.includes(card)) return ui.cardPile.firstChild; return null; }); player.popup(get.cnNumber(top.length) + "上" + get.cnNumber(bottom.length) + "下"); game.log(player, "将" + get.cnNumber(top.length) + "张牌置于牌堆顶"); game.asyncDelayx(); }, subSkill: { viewas: { audio: "jsrgwentian", enable: "chooseToUse", filter: function (event, player) { for (const name of ["wuxie", "huogong"]) { if (event.filterCard(get.autoViewAs({ name }, "unsure"), player, event)) return true; } return false; }, hiddenCard: function (player, name) { if (player.isTempBanned("jsrgwentian")) return false; return name == "wuxie"; }, viewAs: function (cards, player) { const event = get.event(), filter = event._backup.filterCard; for (const name of ["wuxie", "huogong"]) { if (filter(get.autoViewAs({ name }, "unsure"), player, event)) return { name }; } return null; }, filterCard: () => false, selectCard: -1, prompt: function () { const player = get.player(); const event = get.event(), filter = event._backup.filterCard; let str = "将牌堆顶的牌当【"; for (const name of ["wuxie", "huogong"]) { if (filter({ name }, player, event)) { str += get.translation(name); break; } } str += "】使用"; return str; }, precontent() { player.logSkill("jsrgwentian"); const cards = get.cards(); event.result.cards = cards; delete event.result.skill; game.cardsGotoOrdering(cards); const color = event.result.card.name == "wuxie" ? "black" : "red"; if (get.color(cards, false) != color) { player.tempBanSkill("jsrgwentian", "roundStart"); } }, }, }, }, jsrgchushi: { available(mode) { return mode == "identity" || (mode == "versus" && (_status.mode == "four" || _status.mode == "guandu")); }, audio: 2, enable: "phaseUse", usable: 1, filter(event, player) { const zhu = get.zhu(player); if (!zhu || !zhu.isZhu2() || !zhu.countCards("h")) return false; return !player.isZhu2() && player.countCards("h"); }, async content(event, trigger, player) { player .chooseToDebate( game.filterPlayer(current => { return (current == player || current.isZhu2()) && current.countCards("h"); }) ) .set("callback", async event => { const result = event.debateResult; if (result.bool && result.opinion) { const { opinion, targets } = result; targets.sortBySeat(); if (opinion == "red") { do { for (const current of targets) { await current.draw(); } } while ( targets .map(current => { return current.countCards("h"); }) .reduce((p, c) => { return p + c; }, 0) < 7 ); } else { player.addMark("jsrgchushi_add", 1, false); player.addTempSkill("jsrgchushi_add", "roundStart"); } } }); }, subSkill: { add: { audio: "jsrgchushi", trigger: { source: "damageBegin1" }, filter: function (event) { return event.hasNature("linked"); }, forced: true, charlotte: true, onremove: true, async content(_, trigger, player) { trigger.num += player.countMark("jsrgchushi_add"); }, ai: { damageBonus: true, skillTagFilter: function (player, tag, arg) { if (tag === "damageBonus") return arg && arg.card && game.hasNature(arg.card, "linked"); }, }, intro: { content: "造成的属性伤害+#", }, }, }, }, jsrgyinlve: { audio: 2, trigger: { global: "damageBegin4", }, filter: function (event, player) { return event.player.isIn() && ["fire", "thunder"].some(n => !player.hasSkill(`jsrgyinlve_${n}`) && event.hasNature(n)); }, check: function (event, player) { if (get.damageEffect(event.player, event.source, player, get.natureList(event.nature)) < -5) return true; return false; }, logTarget: "player", async content(event, trigger, player) { trigger.cancel(); const natures = ["fire", "thunder"]; let index; if (natures.every(n => !player.hasSkill(`jsrgyinlve_${n}`) && trigger.hasNature(n))) { const { result } = await player.chooseControl(["摸牌阶段", "弃牌阶段"]).set("prompt", "请选择要新回合内仅有的阶段"); index = result.index; } else index = [0, 1].find(i => !player.hasSkill(`jsrgyinlve_${natures[i]}`) && trigger.hasNature(natures[i])); player.addTempSkill(`jsrgyinlve_${natures[index]}`, "roundStart"); player.insertPhase().set("phaseList", [["phaseDraw", "phaseDiscard"][index]]); }, subSkill: { fire: { charlotte: true }, thunder: { charlotte: true }, }, }, //姜维 jsrgjinfa: { audio: 2, enable: "phaseUse", usable: 1, filterCard: true, position: "h", discard: false, lose: false, delay: false, check: function () { return 1 + Math.random(); }, async content(event, trigger, player) { await player.showCards(event.cards); player .chooseToDebate( game.filterPlayer(current => { return current.maxHp <= player.maxHp; }) ) .set("callback", async event => { const result = event.debateResult; if (result.bool && result.opinion) { const { cards: fixedCards } = event.getParent("jsrgjinfa"); const color = get.color(fixedCards); const { opinion, targets } = result; if (opinion == color) { const { result } = await player .chooseTarget("是否令至多两名参与议事的角色将手牌摸至体力上限?", [1, 2], (card, player, target) => { return get.event("targets").includes(target); }) .set("targets", targets) .set("ai", target => { const player = get.player(); const att = get.attitude(player, target); if (att <= 0) return -1; return att * Math.sqrt(Math.max(0.1, target.maxHp - target.countCards("h"))); }); if (result.bool) { const targets = result.targets; targets.sortBySeat(); player.line(targets, "green"); for (const current of targets) { if (current.countCards("h") < current.maxHp) await current.drawTo(current.maxHp); } } } else { await player.gain(lib.card.ying.getYing(2), "gain2"); } } const { red, black } = result; if ((red.length == 1 && red[0][0] == player) || (black.length == 1 && black[0][0] == player)) { const list = lib.group.slice(); list.remove(player.group); list.push("cancel2"); const { result: { control }, } = await player .chooseControl(list) .set("prompt", "是否变更势力?") .set("ai", () => { if (!get.event("change")) return "cancel2"; const controls = get.event("controls"); const groups = ["wei", "shu"].filter(g => controls.includes(g)); if (groups.length) return groups.randomGet(); return controls.randomGet(); }) .set("change", ["wei", "shu"].includes(player.group) ? Math.random() < 0.5 : true); if (control != "cancel2") { player.popup(control + "2", get.groupnature(control, "raw")); player.changeGroup(control); } } }); }, ai: { order: function (item, player) { if (player.countCards("h") == 1) return 10; return 1; }, result: { player: 1, }, }, }, jsrgfumou: { audio: 2, trigger: { global: "chooseToDebateAfter" }, groupSkill: true, forced: true, locked: false, filter: function (event, player) { if (player.group != "wei") return false; if (!event.targets.includes(player)) return false; if (event.red.some(i => i[0] == player)) return event.black.length; if (event.black.some(i => i[0] == player)) return event.red.length; return false; }, async content(event, trigger, player) { const targets = []; if (trigger.red.some(i => i[0] == player)) targets.addArray(trigger.black.map(i => i[0])); if (trigger.black.some(i => i[0] == player)) targets.addArray(trigger.red.map(i => i[0])); player.line(targets, "thunder"); targets.forEach(target => { target.addTempSkill("jsrgfumou_forbid"); target.markAuto( "jsrgfumou_forbid", ["red", "black"].filter(color => { return trigger[color].some(i => i[0] == target); }) ); }); game.broadcastAll(targets => { lib.skill.jsrgfumou_backup.targets = targets; }, targets); const next = player.chooseToUse(); next.set("openskilldialog", `是否将一张【影】当【出其不意】对一名与你意见不同的角色使用?`); next.set("norestore", true); next.set("_backupevent", "jsrgfumou_backup"); next.set("custom", { add: {}, replace: { window: function () {} }, }); next.backup("jsrgfumou_backup"); }, subSkill: { backup: { filterCard: function (card) { return get.itemtype(card) == "card" && get.name(card) == "ying"; }, viewAs: { name: "chuqibuyi", }, selectCard: 1, position: "hs", log: false, filterTarget: function (card, player, target) { const targets = lib.skill.jsrgfumou_backup.targets; if (!targets.includes(target) || ui.selected.targets.containsSome(targets)) return false; return lib.filter.targetEnabled.apply(this, arguments); }, ai1: function (card) { return 6 - get.value(card); }, precontent: function () { delete event.result.skill; }, }, forbid: { charlotte: true, onremove: true, mod: { cardEnabled: function (card, player) { const color = get.color(card); if (color != "unsure" && player.getStorage("jsrgfumou_forbid").includes(color)) return false; }, cardRespondable: function (card, player) { const color = get.color(card); if (color != "unsure" && player.getStorage("jsrgfumou_forbid").includes(color)) return false; }, cardSavable: function (card, player) { const color = get.color(card); if (color != "unsure" && player.getStorage("jsrgfumou_forbid").includes(color)) return false; }, }, mark: true, intro: { content: "本回合不能使用或打出$牌", }, }, }, }, jsrgxuanfeng: { audio: 2, enable: "chooseToUse", filterCard: { name: "ying" }, position: "hs", groupSkill: true, locked: false, viewAs: { name: "sha", nature: "stab", storage: { jsrgxuanfeng: true }, }, viewAsFilter(player) { if (player.group != "shu") return false; if (!player.countCards("hs", "ying")) return false; }, prompt: "将一张【影】当无距离和次数限制的刺【杀】使用", check(card) { const val = get.value(card); return 5 - val; }, mod: { targetInRange: function (card, player, target) { if (card.storage && card.storage.jsrgxuanfeng) return true; }, cardUsable: function (card) { if (card.storage && card.storage.jsrgxuanfeng) return Infinity; }, }, ai: { order: 2, }, }, //陆逊 jsrgyoujin: { audio: 2, trigger: { player: "phaseUseBegin" }, filter(event, player) { return game.hasPlayer(current => { return player.canCompare(current); }); }, direct: true, async content(event, trigger, player) { const { result } = await player .chooseTarget(get.prompt2("jsrgyoujin"), (card, player, target) => { return player.canCompare(target); }) .set("ai", target => { if (!get.event("goon")) return 0; return -get.attitude(get.player(), target); }) .set("goon", player.countCards("hs", ["shan", "caochuan"]) || player.getHp() >= 3); if (!result.bool) return; const { targets } = result, target = targets[0]; player.logSkill("jsrgyoujin", target); const { result: result2 } = await player.chooseToCompare(target).set("small", true); player.addTempSkill("jsrgyoujin_forbid"); player.markAuto("jsrgyoujin_forbid", [result2.num1]); target.addTempSkill("jsrgyoujin_forbid"); target.markAuto("jsrgyoujin_forbid", [result2.num2]); if (!result2.tie) { const targets = [target, player]; if (result2.bool) targets.reverse(); const sha = new lib.element.VCard({ name: "sha" }); if (targets[0].canUse(sha, targets[1], false)) { targets[0].useCard(sha, targets[1], false); } } }, subSkill: { forbid: { charlotte: true, onremove: true, mod: { cardEnabled2: function (card, player) { if (get.itemtype(card) == "card" && player.getStorage("jsrgyoujin_forbid").some(num => num > get.number(card))) return false; }, }, mark: true, intro: { content: "本回合不能使用或打出点数小于$的手牌", }, }, }, }, jsrgdailao: { audio: 2, enable: "phaseUse", filter(event, player) { return !player.hasCard(card => { return player.hasUseTarget(card, true, true); }); }, async content(event, trigger, player) { await player.showHandcards(); await player.draw(2); const evt = event.getParent("phase"); if (evt) { game.resetSkills(); _status.event = evt; _status.event.finish(); _status.event.untrigger(true); } }, ai: { order: 0.0001, result: { player: 1 }, }, }, jsrgzhubei: { audio: 2, trigger: { source: "damageBegin1" }, forced: true, init(player) { player.addSkill("jsrgzhubei_record"); }, filter(event, player) { return event.player.hasHistory("damage", evt => { return evt.source == player; }); }, logTarget: "player", async content(event, trigger, player) { trigger.num++; }, subSkill: { record: { trigger: { global: ["loseAfter", "equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], }, charlotte: true, silent: true, filter(event, player) { return game.hasPlayer(current => { if (current.countCards("h")) return false; const evt = event.getl(current); return evt && evt.hs && evt.hs.length; }); }, async content(event, trigger, player) { game.countPlayer(current => { if (current.countCards("h")) return false; const evt = trigger.getl(current); if (evt && evt.hs && evt.hs.length) current.addTempSkill("jsrgzhubei_lost"); }); }, }, lost: { charlotte: true }, }, mod: { cardUsableTarget(card, player, target) { if (target.hasSkill("jsrgzhubei_lost")) return true; }, }, }, //赵云 jsrglonglin: { audio: 2, trigger: { global: "useCardToPlayered", }, usable: 1, filter(event, player) { if (event.player == player) return false; if (event.card.name != "sha") return false; return event.isFirstTarget && event.player.isPhaseUsing(); }, direct: true, async content(event, trigger, player) { const juedou = new lib.element.VCard({ name: "juedou", storage: { jsrglonglin: true } }); const { result } = await player .chooseToDiscard(get.prompt2("jsrglonglin"), "he") .set("ai", card => { if (get.event("goon")) return 5 - get.value(card); return 0; }) .set( "goon", (trigger.player.canUse(juedou, player) ? Math.max(0, get.effect(player, juedou, trigger.player, trigger.player)) : 0) + trigger.targets .map(target => { return get.effect(target, trigger.card, trigger.player, player); }) .reduce((p, c) => { return p + c; }, 0) < -4 ) .set("logSkill", ["jsrglonglin", trigger.player]); if (result.bool) { trigger.excluded.addArray(trigger.targets); game.asyncDelayx(); if (trigger.player.canUse(juedou, player)) { const { result } = await trigger.player.chooseBool(`是否视为对${get.translation(player)}使用一张【决斗】?`).set("choice", get.effect(player, juedou, trigger.player, trigger.player) >= 0); if (result.bool) { player.addTempSkill("jsrglonglin_source"); trigger.player.useCard(juedou, player); } } } }, subSkill: { source: { trigger: { source: "damageSource" }, charlotte: true, forced: true, popup: false, filter(event, player) { return event.card && event.card.storage && event.card.storage.jsrglonglin; }, async content(event, trigger, player) { player.line(trigger.player); trigger.player.addTempSkill("jsrglonglin_forbid", "phaseUseAfter"); }, }, forbid: { mod: { cardEnabled: function (card, player) { if (!card.cards) return; if (card.cards.some(cardx => get.position(cardx) == "h")) return false; }, cardSavable: function (card, player) { if (!card.cards) return; if (card.cards.some(cardx => get.position(cardx) == "h")) return false; }, }, charlotte: true, mark: true, intro: { content: "不能使用手牌", }, }, }, }, jsrgzhendan: { audio: 2, trigger: { player: "damageEnd", global: "roundStart", }, filter(event, player) { let count = 0; let roundCount = 1 + (event.name != "damage"); const curLen = player.actionHistory.length; for (let i = curLen - 1; i >= 0; i--) { if ( roundCount == 1 && game.hasPlayer(current => { const history = current.actionHistory[i]; if (!history.isMe || history.isSkipped) return false; return true; }) ) { count++; } if (player.actionHistory[i].isRound) roundCount--; if (roundCount <= 0) break; } if (!player.storage.jsrgzhendan_mark && count > 0) return true; return false; }, forced: true, locked: false, group: "jsrgzhendan_viewas", async content(event, trigger, player) { let count = 0; let roundCount = 1 + (trigger.name != "damage"); const curLen = player.actionHistory.length; for (let i = curLen - 1; i >= 0; i--) { if ( roundCount == 1 && game.hasPlayer(current => { const history = current.actionHistory[i]; if (!history.isMe || history.isSkipped) return false; return true; }) ) { count++; } if (player.actionHistory[i].isRound) roundCount--; if (roundCount <= 0) break; } count = Math.min(5, count); await player.draw(count); if (trigger.name == "damage") { player.tempBanSkill("jsrgzhendan", "roundStart"); player.storage.jsrgzhendan_mark = true; player .when({ global: "roundStart" }) .assign({ lastDo: true, }) .then(() => { delete player.storage.jsrgzhendan_mark; }); } }, subSkill: { viewas: { audio: "jsrgzhendan", enable: ["chooseToUse", "chooseToRespond"], filter(event, player) { if (event.type == "wuxie") return false; if ( !_status.connectMode && !player.countCards("hs", card => { return get.type2(card) != "basic"; }) ) return false; return get.inpileVCardList(info => { if (info[0] != "basic") return false; return event.filterCard(get.autoViewAs({ name: info[2], nature: info[3] }, "unsure"), player, event); }).length; }, chooseButton: { dialog(event, player) { const vcards = get.inpileVCardList(info => { if (info[0] != "basic") return false; return event.filterCard(get.autoViewAs({ name: info[2], nature: info[3] }, "unsure"), player, event); }); return ui.create.dialog("镇胆", [vcards, "vcard"]); }, check(button) { if (get.event().getParent().type != "phase") return 1; return get.player().getUseValue({ name: button.link[2], nature: button.link[3] }); }, backup(links, player) { return { audio: "jsrgzhendan", popname: true, viewAs: { name: links[0][2], nature: links[0][3] }, filterCard(card, player) { return get.type2(card) != "basic"; }, selectCard: 1, position: "hs", }; }, prompt(links, player) { return "将一张非基本手牌当" + (get.translation(links[0][3]) || "") + get.translation(links[0][2]) + "使用或打出"; }, }, hiddenCard(player, name) { return get.type(name) == "basic" && player.countCards("hs") > 0; }, ai: { respondSha: true, respondShan: true, skillTagFilter(player) { return player.countCards("hs") > 0; }, order: 0.5, result: { player(player) { if (get.event().dying) { return get.attitude(player, get.event().dying); } return 1; }, }, }, }, viewas_backup: {}, }, }, //司马懿 jsrgyingshi: { audio: 2, trigger: { player: "turnOverAfter" }, async content(event, trigger, player) { const number = game.dead.length > 2 ? 5 : 3; const cards = get.bottomCards(number); game.cardsGotoOrdering(cards); const next = player.chooseToMove(); next.set("list", [["牌堆顶"], ["牌堆底", cards.reverse()]]); next.set("prompt", "鹰眎:点击将牌移动到牌堆顶或牌堆底"); next.processAI = list => { const cards = list[1][1], player = _status.event.player; const top = []; const judges = player.getCards("j"); let stopped = false; if (!player.hasWuxie()) { for (let i = 0; i < judges.length; i++) { const judge = get.judge(judges[i]); cards.sort((a, b) => judge(b) - judge(a)); if (judge(cards[0]) < 0) { stopped = true; break; } else { top.unshift(cards.shift()); } } } let bottom; if (!stopped) { cards.sort((a, b) => get.value(b, player) - get.value(a, player)); while (cards.length) { if (get.value(cards[0], player) <= 5) break; top.unshift(cards.shift()); } } bottom = cards; return [top, bottom]; }; const { result: { moved }, } = await next; const top = moved[0]; const bottom = moved[1]; top.reverse(); game.cardsGotoPile(top.concat(bottom), ["top_cards", top], (event, card) => { if (event.top_cards.includes(card)) return ui.cardPile.firstChild; return null; }); player.popup(get.cnNumber(top.length) + "上" + get.cnNumber(bottom.length) + "下"); game.log(player, "将" + get.cnNumber(top.length) + "张牌置于牌堆顶"); game.asyncDelayx(); }, }, jsrgtuigu: { audio: 2, trigger: { player: "phaseBegin" }, prompt2(event, player) { const num = Math.floor(game.countPlayer() / 2); return `你翻面,令你本回合的手牌上限+${num},摸${get.cnNumber(num)}张牌,视为使用一张【解甲归田】(目标角色不能使用这些牌直到其下回合结束)。`; }, group: ["jsrgtuigu_insert", "jsrgtuigu_recover"], async content(event, trigger, player) { await player.turnOver(); const num = Math.floor(game.countPlayer() / 2); player.addTempSkill("jsrgtuigu_handcard"); player.addMark("jsrgtuigu_handcard", num, false); await player.draw(num); const jiejia = new lib.element.VCard({ name: "jiejia", storage: { jsrgtuigu: true } }); if (player.hasUseTarget(jiejia)) { player.addTempSkill("jsrgtuigu_block"); player.chooseUseTarget(jiejia, true); } }, subSkill: { insert: { audio: "jsrgtuigu", trigger: { global: "roundStart" }, filter(event, player) { const curLen = player.actionHistory.length; if (curLen <= 2) return false; for (let i = curLen - 2; i >= 0; i--) { const history = player.actionHistory[i]; if (history.isMe && !history.isSkipped && !history._jsrgtuigu) return false; if (history.isRound) break; } return true; }, forced: true, locked: false, async content(event, trigger, player) { const evt = trigger, evtx = player.insertPhase(); player .when("phaseBeforeStart") .filter(evtt => evtt == evtx) .then(() => { game.players .slice() .concat(game.dead) .forEach(current => { current.getHistory()._jsrgtuigu = true; current.getStat()._jsrgtuigu = true; }); }); if (evt.player != player && !evt._finished) { evt.finish(); evt._triggered = 5; const evtxx = evt.player.insertPhase(); delete evtxx.skill; } }, }, recover: { audio: "jsrgtuigu", trigger: { player: "loseAfter", global: ["gainAfter", "equipAfter", "addJudgeAfter", "loseAsyncAfter", "addToExpansionAfter"], }, filter(event, player) { if (player.isHealthy()) return false; const evt = event.getl(player); return evt && evt.es && evt.es.length > 0; }, forced: true, locked: false, async content(event, trigger, player) { player.recover(); }, }, handcard: { markimage: "image/card/handcard.png", intro: { content(storage, player) { return "手牌上限+" + storage; }, }, onremove: true, charlotte: true, mod: { maxHandcard(player, num) { return num + player.countMark("jsrgtuigu_handcard"); }, }, }, block: { trigger: { global: "gainAfter" }, filter(event, player) { if (event.getParent().name != "jiejia") return false; const card = event.getParent(2).card; if (card && card.storage && card.storage.jsrgtuigu) return true; return false; }, charlotte: true, forced: true, silent: true, content() { trigger.player.addGaintag(trigger.cards, "jsrgtuigu"); trigger.player.addTempSkill("jsrgtuigu_blocked", { player: "phaseAfter" }); }, }, blocked: { mod: { cardEnabled2(card) { if (get.itemtype(card) == "card" && card.hasGaintag("jsrgtuigu")) return false; }, }, charlotte: true, forced: true, popup: false, onremove(player) { player.removeGaintag("jsrgtuigu"); }, }, }, }, //郭循 jsrgeqian: { audio: 2, trigger: { player: "useCardToPlayered" }, filter(event, player) { if (!event.isFirstTarget || event.targets.length != 1 || event.target == player) return false; if (event.card.name == "sha") return true; return event.getParent(3).name == "xumou_jsrg"; }, prompt2(event, player) { return `令${get.translation(event.card)}不计入次数限制,且你获得${get.translation(event.target)}一张牌,然后其可以令你本回合至其的距离+2`; }, group: "jsrgeqian_prepare", logTarget: "target", async content(event, trigger, player) { if (trigger.addCount !== false) { trigger.addCount = false; var stat = player.getStat().card, name = trigger.card.name; if (typeof stat[name] == "number") stat[name]--; } await player.gainPlayerCard(trigger.target, "he", true); const { result: { bool }, } = await trigger.target.chooseBool(`是否令${get.translation(player)}至你的距离于本回合内+2?`).set("ai", () => true); if (bool) { player.addTempSkill("jsrgeqian_distance"); if (!player.storage.jsrgeqian_distance) player.storage.jsrgeqian_distance = {}; const id = trigger.target.playerid; if (typeof player.storage.jsrgeqian_distance[id] != "number") player.storage.jsrgeqian_distance[id] = 0; player.storage.jsrgeqian_distance[id] += 2; player.markSkill("jsrgeqian_distance"); } }, subSkill: { prepare: { audio: "jsrgeqian", trigger: { player: "phaseJieshuBegin" }, filter(event, player) { return player.countCards("h") && !player.isDisabledJudge(); }, direct: true, async content(event, trigger, player) { while (player.countCards("h") > 0) { const { result: { bool, cards }, } = await player.chooseCard(get.prompt("jsrgeqian"), "你可以蓄谋任意次").set("ai", card => { const player = get.player(); if (player.hasValueTarget(card)) return player.getUseValue(card); return 0; }); if (!bool) break; await player.addJudge({ name: "xumou_jsrg" }, cards); } }, }, distance: { onremove: true, charlotte: true, mod: { globalFrom(player, target, distance) { if (!player.storage.jsrgeqian_distance) return; const dis = player.storage.jsrgeqian_distance[target.playerid]; if (typeof dis == "number") return distance + dis; }, }, intro: { content(storage, player) { if (!storage) return; const map = _status.connectMode ? lib.playerOL : game.playerMap; let str = `你本回合:`; for (const id in storage) { str += "
  • 至" + get.translation(map[id]) + "的距离+" + storage[id]; } return str; }, }, }, }, }, jsrgfusha: { audio: 2, enable: "phaseUse", limited: true, skillAnimation: true, animationColor: "fire", filter(event, player) { return ( game.countPlayer(current => { return player.inRange(current); }) == 1 ); }, filterTarget(card, player, target) { return player.inRange(target); }, selectTarget: -1, async content(event, trigger, player) { player.awakenSkill("jsrgfusha"); event.target.damage(Math.min(game.countPlayer(), player.getAttackRange())); }, ai: { order: 1, result: { target: -2, }, }, }, //大小虎 jsrgdaimou: { audio: 2, trigger: { global: "useCardToPlayer", }, filter(event, player) { if (event.card.name != "sha") return false; if (event.target != player) return !player.hasSkill("jsrgdaimou_other") && !player.isDisabledJudge(); return ( !player.hasSkill("jsrgdaimou_me") && player.hasCard(card => { return (card.viewAs || card.name) == "xumou_jsrg" && lib.filter.cardDiscardable(card, player, "jsrgdaimou"); }, "j") ); }, direct: true, async content(event, trigger, player) { if (trigger.target == player) { player.logSkill("jsrgdaimou"); player.addTempSkill("jsrgdaimou_me"); const { result: { bool, links }, } = await player .chooseButton( [ "殆谋:请弃置区域里的一张蓄谋牌", player.getCards("j", card => { return (card.viewAs || card.name) == "xumou_jsrg"; }), ], true ) .set("filterButton", button => { return lib.filter.cardDiscardable(button.link, get.player(), "jsrgdaimou"); }) .set("ai", button => { const player = get.player(); return 1 / Math.max(0.01, player.getUseValue(button.link)); }); if (bool) { player.discard(links); } } else { const { result: { bool }, } = await player.chooseBool(get.prompt("jsrgdaimou"), "你可以用牌堆顶的牌蓄谋").set("ai", () => true); if (bool) { player.logSkill("jsrgdaimou"); player.addTempSkill("jsrgdaimou_other"); player.addJudge({ name: "xumou_jsrg" }, get.cards()); } } }, subSkill: { me: { charlotte: true }, other: { charlotte: true }, }, }, jsrgfangjie: { audio: 2, trigger: { player: "phaseZhunbeiBegin" }, direct: true, async content(event, trigger, player) { if ( !player.hasCard(card => { return (card.viewAs || card.name) == "xumou_jsrg"; }, "j") ) { player.logSkill("jsrgfangjie"); await player.recover(); await player.draw(); } else { const { result: { bool, links }, } = await player .chooseButton( [ "是否弃置区域里的任意张蓄谋牌并失去〖芳洁〗?", player.getCards("j", card => { return (card.viewAs || card.name) == "xumou_jsrg"; }), ], [1, Infinity] ) .set("filterButton", button => { return lib.filter.cardDiscardable(button.link, get.player(), "jsrgdaimou"); }) .set("ai", () => 0); if (bool) { player.logSkill("jsrgfangjie"); await player.discard(links); player.removeSkills("jsrgfangjie"); } } }, }, //曹芳 jsrgzhaotu: { audio: 2, enable: "chooseToUse", viewAs: { name: "lebu" }, position: "hes", round: 1, viewAsFilter(player) { return player.countCards("hes"); }, filterCard(card, player) { return get.color(card) == "red" && get.type2(card) != "trick"; }, onuse(result, player) { player.tempBanSkill("jsrgzhaotu", null, false); result.targets[0].insertPhase(); result.targets[0].addTempSkill("jsrgzhaotu_handcard", { player: "phaseAfter" }); result.targets[0].addMark("jsrgzhaotu_handcard", 2, false); }, subSkill: { handcard: { intro: { content(storage, player) { return "手牌上限-" + storage; }, }, charlotte: true, onremove: true, mod: { maxHandcard(player, num) { return num - player.countMark("jsrgzhaotu_handcard"); }, }, }, }, ai: { order: 5, result: { target(player, target) { let dis = 0.5 - 0.75 * target.needsToDiscard(2, null, true); if (dis > 0) return dis; if (player.hasSkill("jsrgjingju") && player.hasZhuSkill("jsrgweizhui") && get.attitude(player, target) > 0) return game.countPlayer(current => { if (current === player || current === target || current.group !== "wei") return false; return player.hasZhuSkill("jsrgweizhui", current) && get.attitude(player, current) > 0; }); return dis; }, }, }, }, jsrgjingju: { audio: 2, enable: "chooseToUse", filter(event, player) { if (event.type == "wuxie" || event.jsrgjingju) return false; if ( !player.canMoveCard( null, false, game.filterPlayer(i => i != player), player, card => { return get.position(card) == "j"; } ) ) return false; return get.inpileVCardList(info => { if (info[0] != "basic") return false; return event.filterCard(get.autoViewAs({ name: info[2], nature: info[3] }, "unsure"), player, event); }).length; }, chooseButton: { dialog: function (event, player) { const vcards = get.inpileVCardList(info => { if (info[0] != "basic") return false; return event.filterCard(get.autoViewAs({ name: info[2], nature: info[3] }, "unsure"), player, event); }); return ui.create.dialog("惊惧", [vcards, "vcard"], "hidden"); }, check: function (button) { let player = _status.event.player; if (get.event().getParent().type != "phase") return 1; return ( get.player().getUseValue({ name: button.link[2], nature: button.link[3] }) + game.countPlayer(current => { if (current === player || current.group !== "wei") return false; return player.hasZhuSkill("jsrgweizhui", current) && get.attitude(player, current) > 0; }) ); }, backup: function (links, player) { return { filterCard: () => false, viewAs: { name: links[0][2], nature: links[0][3], isCard: true, }, selectCard: -1, precontent() { "step 0"; player .moveCard( `惊惧:将其他角色判定区里的牌移动至你的判定区`, game.filterPlayer(i => i != player), player, card => { return get.position(card) == "j"; } ) .set("logSkill", "jsrgjingju"); ("step 1"); if (result.bool) { delete event.result.skill; } else { event.getParent().jsrgjingju = true; event.getParent().goto(0); delete event.getParent().openskilldialog; event.finish(); } ("step 2"); game.delayx(); }, }; }, prompt: function (links, player) { return "选择" + get.translation(links[0][3] || "") + "【" + get.translation(links[0][2]) + "】的目标"; }, }, ai: { order: function () { const player = get.player(), event = _status.event; if ( player.canMoveCard(null, false, game.filterPlayer(), player, card => { return get.position(card) == "j"; }) ) { if (event.type == "dying") { if (event.filterCard({ name: "tao" }, player, event)) { return 0.5; } } else { if (event.filterCard({ name: "tao" }, player, event) || event.filterCard({ name: "shan" }, player, event)) { return 4; } if (event.filterCard({ name: "sha" }, player, event)) { return 2.9; } } } return 0; }, save: true, respondSha: true, respondShan: true, skillTagFilter: function (player, tag, arg) { return player.canMoveCard(null, false, game.filterPlayer(), player, card => { return get.position(card) == "j"; }); }, result: { player: function (player) { if (get.event().type == "dying") { return get.attitude(player, get.event().dying); } return 1; }, }, }, }, jsrgweizhui: { audio: 2, trigger: { global: "phaseJieshuBegin" }, zhuSkill: true, direct: true, filter(event, player) { return player != event.player && event.player.group == "wei" && event.player.isIn() && player.hasZhuSkill("jsrgweizhui", event.player); }, async content(event, trigger, player) { const { result: { bool, cards }, } = await trigger.player .chooseCard(`是否响应${get.translation(player)}的主公技【危坠】?`, "将一张黑色手牌当【过河拆桥】对其使用", (card, player) => { if (get.color(card) != "black") return false; return player.canUse(get.autoViewAs({ name: "guohe" }, [card]), get.event("target")); }) .set("target", player) .set("ai", card => { if (get.effect(get.event("target"), get.autoViewAs({ name: "guohe" }, [card]), player) <= 0) return 0; return 7 - get.value(card); }); if (bool) { trigger.player.logSkill("jsrgweizhui", player); trigger.player.useCard(get.autoViewAs({ name: "guohe" }, cards), cards, player); } }, }, //孙峻 jsrgyaoyan: { audio: 2, trigger: { player: "phaseZhunbeiBegin" }, prompt: "是否发动【邀宴】?", logTarget: () => game.filterPlayer(), async content(event, trigger, player) { const targets = game.filterPlayer(); const toDebateList = []; while (targets.length) { const current = targets.shift(); const { result: { bool }, } = await current.chooseBool(`是否响应${get.translation(player)}的【邀宴】,于回合结束参与议事?`).set("ai", () => Math.random() < 0.5); if (bool) { toDebateList.add(current); current.popup("同意", "wood"); game.log(current, "#g同意", "参加", player, "的议事"); } else { current.popup("拒绝", "fire"); game.log(current, "#r拒绝", "参加", player, "的议事"); } } if (toDebateList.length) { player.addTempSkill("jsrgyaoyan_hold"); player.markAuto("jsrgyaoyan_hold", toDebateList); } }, subSkill: { hold: { trigger: { player: "phaseEnd" }, charlotte: true, forced: true, popup: false, onremove: true, filter(event, player) { return player.getStorage("jsrgyaoyan_hold").some(i => i.isIn()); }, async content(event, trigger, player) { player.chooseToDebate(player.getStorage("jsrgyaoyan_hold").filter(i => i.isIn())).set("callback", async event => { const { bool, opinion, targets } = event.debateResult; if (bool && opinion) { if (opinion == "red") { const notDebated = game.filterPlayer().removeArray(targets); if (notDebated.length) { const { result } = await player .chooseTarget("获得任意名未议事的角色的各一张手牌", [1, Infinity], true, (card, player, target) => { return get.event("targets").includes(target) && target.countGainableCards(player, "h"); }) .set("targets", notDebated) .set("ai", target => { const player = get.player(); const att = get.attitude(player, target); return -att; }); if (result.bool) { const targets = result.targets; targets.sortBySeat(); player.line(targets, "green"); for (const current of targets) { await player.gainPlayerCard(current, "h", true); } } } } else { const { result: { bool, targets: targets2 }, } = await player .chooseTarget("是否对一名议事的角色造成2点伤害?", (card, player, target) => { return get.event("targets").includes(target); }) .set("targets", targets) .set("ai", target => { const player = get.player(); const eff = get.damageEffect(target, player, player); return eff; }); if (bool) { player.line(targets2[0]); targets2[0].damage(2); } } } }); }, }, }, }, jsrgbazheng: { audio: 2, trigger: { global: "debateShowOpinion" }, filter(event, player) { if (!event.targets.includes(player)) return false; const damagedPlayers = player .getHistory("sourceDamage") .map(evt => evt.player) .toUniqued(); let dissent; const colors = ["red", "black"]; for (const color of colors) { if (event[color].some(i => i[0] == player)) { dissent = colors.find(i => i != color); break; } } return event[dissent].some(i => damagedPlayers.includes(i[0])); }, forced: true, locked: false, direct: true, async content(event, trigger, player) { let myOpinion, dissent; const colors = ["red", "black"]; for (const color of colors) { if (trigger[color].some(i => i[0] == player)) { myOpinion = color; dissent = colors.find(i => i != color); break; } } const damagedPlayers = player .getHistory("sourceDamage") .map(evt => evt.player) .toUniqued(); let dissident = []; for (let i = 0; i < trigger[dissent].length; i++) { const pair = trigger[dissent][i]; if (damagedPlayers.includes(pair[0])) { dissident.push(pair[0]); trigger[myOpinion].push(pair); trigger[dissent].splice(i--, 1); } } player.logSkill("jsrgbazheng", dissident); }, }, //刘永 jsrgdanxin: { audio: 2, enable: "chooseToUse", viewAs: { name: "tuixinzhifu", storage: { jsrgdanxin: true }, }, filterCard: true, position: "hes", precontent() { player.addTempSkill("jsrgdanxin_effect"); }, subSkill: { effect: { audio: "jsrgdanxin", trigger: { global: "gainAfter", }, filter(event, player) { const level = event.player != player ? 1 : 2; if (event.player != player && event.getParent(level).name != "tuixinzhifu") return false; if (event.player == player && event.getParent(level).name != "tuixinzhifu") return false; const card = event.getParent(level + 1).card; return card && card.storage && card.storage.jsrgdanxin; }, forced: true, popup: false, charlotte: true, async content(event, trigger, player) { const level = trigger.player != player ? 1 : 2; const { targets } = trigger.getParent(level + 1); await player.showCards(trigger.cards); if (trigger.cards.some(card => get.suit(card) == "heart")) { const owners = trigger.cards .filter(card => get.suit(card) == "heart") .map(card => get.owner(card)) .toUniqued(); for (const owner of owners) { if (owner && owner.isIn()) await owner.recover(); } } if (trigger.player == player) return; player.addTempSkill("jsrgdanxin_distance"); if (!player.storage.jsrgdanxin_distance) player.storage.jsrgdanxin_distance = {}; const id = targets[0].playerid; if (typeof player.storage.jsrgdanxin_distance[id] != "number") player.storage.jsrgdanxin_distance[id] = 0; player.storage.jsrgdanxin_distance[id]++; player.markSkill("jsrgdanxin_distance"); }, }, distance: { onremove: true, charlotte: true, mod: { globalFrom(player, target, distance) { if (!player.storage.jsrgdanxin_distance) return; const dis = player.storage.jsrgdanxin_distance[target.playerid]; if (typeof dis == "number") return distance + dis; }, }, intro: { content(storage, player) { if (!storage) return; const map = _status.connectMode ? lib.playerOL : game.playerMap; let str = `你本回合:`; for (const id in storage) { str += "
  • 至" + get.translation(map[id]) + "的距离+" + storage[id]; } return str; }, }, }, }, }, jsrgfengxiang: { audio: "fengxiang", trigger: { player: "damageEnd" }, forced: true, direct: true, filter(event, player) { return game.hasPlayer(current => { return current.countCards("e"); }); }, async content(event, trigger, player) { const { result: { bool, targets }, } = await player .chooseTarget( "封乡:与一名其他角色交换装备区里的所有牌", (card, player, target) => { return target.countCards("e") + player.countCards("e") > 0 && player != target; }, true ) .set("ai", target => { const player = get.player(); const att = get.attitude(player, target); let delta = get.value(target.getCards("e"), player) - get.value(player.getCards("e"), player); if (att > 0) { if (delta < 0) delta += att / 3; } else { if (delta < 0) delta -= att / 3; } return delta; }); if (bool) { player.logSkill("jsrgfengxiang", targets[0]); const num = player.countCards("e"); await player.swapEquip(targets[0]); const delta = num - player.countCards("e"); if (delta > 0) player.draw(delta); } }, }, jsrgfuhai: { audio: "xinfu_fuhai", enable: "phaseUse", usable: 1, filter(event, player) { return game.hasPlayer(current => { return current.countCards("h") && current != player; }); }, filterTarget(card, player, target) { return target.countCards("h") && target != player; }, selectTarget: -1, multitarget: true, multiline: true, async content(event, trigger, player) { const targets = event.targets.sortBySeat(); const next = player .chooseCardOL(targets, "请展示一张手牌", true) .set("ai", card => { return -get.value(card); }) .set("aiCard", target => { const hs = target.getCards("h"); return { bool: true, cards: [hs.randomGet()] }; }); next._args.remove("glow_result"); const { result } = await next; const cards = []; const videoId = lib.status.videoId++; for (let i = 0; i < targets.length; i++) { cards.push(result[i].cards[0]); game.log(targets[i], "展示了", result[i].cards[0]); } game.broadcastAll( (targets, cards, id, player) => { var dialog = ui.create.dialog(get.translation(player) + "发动了【浮海】", cards); dialog.videoId = id; const getName = target => { if (target._tempTranslate) return target._tempTranslate; var name = target.name; if (lib.translate[name + "_ab"]) return lib.translate[name + "_ab"]; return get.translation(name); }; for (let i = 0; i < targets.length; i++) { dialog.buttons[i].querySelector(".info").innerHTML = getName(targets[i]) + "|" + get.strNumber(cards[i].number); } }, targets, cards, videoId, player ); await game.asyncDelay(4); game.broadcastAll("closeDialog", videoId); let clock = -1, anticlock = -1; for (let j = 0; j < 2; j++) { let increase = -Infinity, decrease = Infinity, count = 0; for (let i = 0; i < targets.length; i++) { const number = get.number(cards[i], false); let flag = false; if (number > increase) { increase = number; flag = true; } else increase = Infinity; if (number < decrease) { decrease = number; flag = true; } else decrease = -Infinity; if (flag) count++; else break; } targets.reverse(); cards.reverse(); if (j == 0) anticlock = Math.max(1, count); else clock = Math.max(1, count); } const { result: { index }, } = await player .chooseControl(`↖顺时针(${clock})`, `逆时针(${anticlock})↗`) .set("prompt", "请选择一个方向,摸对应数量的牌") .set("ai", () => get.event("choice")) .set("choice", clock > anticlock ? 0 : 1); player.draw(index == 0 ? clock : anticlock); }, ai: { order: 8, result: { player: 1 }, }, }, //张嫙 jsrgtongli: { audio: "tongli", trigger: { player: "useCardToPlayered" }, filter(event, player) { if (!event.isFirstTarget) return false; const type = get.type(event.card); if (type != "basic" && type != "trick") return false; const hs = player.getCards("h"); if (!hs.length) return false; const evt = event.getParent("phaseUse"); if (!evt || evt.player != player) return false; const num1 = player.getHistory("useCard", evtx => { return evtx.getParent("phaseUse") == evt; }).length; if (hs.length < num1) return false; const list = []; for (const i of hs) list.add(get.suit(i, player)); return list.length == num1; }, prompt2(event, player) { let str = "展示所有手牌,额外结算一次"; if (event.card.name == "sha" && game.hasNature(event.card)) str += get.translation(event.card.nature); return str + "【" + get.translation(event.card.name) + "】"; }, check(event, player) { return !get.tag(event.card, "norepeat"); }, async content(event, trigger, player) { await player.showHandcards(); trigger.getParent().effectCount++; }, }, jsrgshezang: { audio: "shezang", round: 1, trigger: { global: "dying" }, frequent: true, filter(event, player) { return event.player == player || player == _status.currentPhase; }, async content(event, trigger, player) { const cards = get.cards(4); game.cardsGotoOrdering(cards); const videoId = lib.status.videoId++; game.broadcastAll( (player, id, cards) => { let str = "奢葬"; if (player == game.me && !_status.auto) { str += ":获得任意张花色各不相同的牌"; } const dialog = ui.create.dialog(str, cards); dialog.videoId = id; }, player, videoId, cards ); const time = get.utc(); game.addVideo("showCards", player, ["奢葬", get.cardsInfo(event.cards)]); game.addVideo("delay", null, 2); const list = []; for (const i of cards) list.add(get.suit(i, false)); const next = player.chooseButton([1, list.length]); next.set("dialog", event.videoId); next.set("filterButton", function (button) { for (var i = 0; i < ui.selected.buttons.length; i++) { if (get.suit(ui.selected.buttons[i].link) == get.suit(button.link)) return false; } return true; }); next.set("ai", function (button) { return get.value(button.link, _status.event.player); }); const { result } = await next; if (result.bool && result.links) { const time2 = 1000 - (get.utc() - time); if (time2 > 0) { await game.asyncDelay(0, time2); } game.broadcastAll("closeDialog", videoId); player.gain(result.links, "gain2"); } }, }, jsrgchiying: { audio: "dcchiying", enable: "phaseUse", usable: 1, filterTarget: true, async content(event, trigger, player) { const target = event.target; const targets = game.filterPlayer(current => target.inRange(current) && current != player).sortBySeat(player); if (!targets.length) return; while (targets.length) { const current = targets.shift(); if (current.countCards("he")) await current.chooseToDiscard("驰应:请弃置一张牌", "he", true); } let cards = []; game.getGlobalHistory("cardMove", evt => { if (evt.getParent(3) == event) { cards.addArray(evt.cards.filter(card => get.type(card) == "basic")); } }); if (cards.length <= target.getHp()) { cards = cards.filterInD("d"); if (cards.length) target.gain(cards, "gain2"); } }, ai: { order: 6, result: { target(player, target) { const targets = game.filterPlayer(current => target.inRange(current) && current != player); let eff = 0; for (const targetx of targets) { let effx = get.effect(targetx, { name: "guohe_copy2" }, player, target); if (get.attitude(player, targetx) < 0) effx /= 2; eff += effx; } return eff * (get.attitude(player, target) <= 0 ? 0.75 : 1); }, }, }, }, //郭照 jsrgpianchong: { audio: "pianchong", trigger: { global: "phaseJieshuBegin" }, filter(event, player) { return player.getHistory("lose").length; }, frequent: true, async content(event, trigger, player) { const { result } = await player.judge(); let num = 0; game.getGlobalHistory("cardMove", evt => { if (evt.name != "cardsDiscard") { if (evt.name != "lose" || evt.position != ui.discardPile) return false; } num += evt.cards.filter(i => get.color(i, false) == result.color).length; }); if (num > 0) player.draw(num); }, }, jsrgzunwei: { audio: "zunwei", enable: "phaseUse", usable: 1, filter(event, player) { const storage = player.getStorage("jsrgzunwei"); return ( storage.length < 3 && game.hasPlayer(current => { return (player.isDamaged() && current.getHp() > player.getHp() && !storage.includes(2)) || (current.countCards("h") > player.countCards("h") && !storage.includes(0)) || (current.countCards("e") > player.countCards("e") && !storage.includes(1)); }) ); }, chooseButton: { dialog(event, player) { const list = ["选择手牌数大于你的一名角色", "选择装备数大于你的一名角色", "选择体力值大于你的一名角色"]; const choiceList = ui.create.dialog("尊位:请选择一项", "forcebutton", "hidden"); choiceList.add([ list.map((item, i) => { if (player.getStorage("jsrgzunwei").includes(i)) item = `${item}`; return [i, item]; }), "textbutton", ]); return choiceList; }, filter(button) { const player = get.player(); if (player.getStorage("jsrgzunwei").includes(button.link)) return false; if (button.link == 2) { if (!player.isDamaged()) return false; return game.hasPlayer(current => { return current.getHp() > player.getHp(); }); } if (button.link == 0) { return game.hasPlayer(current => { return current.countCards("h") > player.countCards("h"); }); } if (button.link == 1) { return game.hasPlayer(current => { return current.countCards("e") > player.countCards("e"); }); } }, backup(links) { const next = get.copy(lib.skill.jsrgzunwei.backups[links[0]]); next.audio = "zunwei"; next.filterCard = function () { return false; }; next.selectCard = -1; return next; }, check(button) { const player = get.player(); switch (button.link) { case 2: { const target = game.findPlayer(function (current) { return current.isMaxHp(); }); return (Math.min(target.hp, player.maxHp) - player.hp) * 2; } case 0: { const target = game.findPlayer(function (current) { return current.isMaxHandcard(); }); return Math.min(5, target.countCards("h") - player.countCards("h")) * 0.8; } case 1: { const target = game.findPlayer(function (current) { return current.isMaxEquip(); }); return (target.countCards("e") - player.countCards("e")) * 1.4; } } }, prompt(links) { return ["选择一名手牌数大于你的其他角色,将手牌数摸至与其相同(至多摸五张)", "选择一名装备区内牌数大于你的其他角色,将其装备区里的牌移至你的装备区,直到你装备数不小于其", "选择一名体力值大于你的其他角色,将体力值回复至与其相同"][links[0]]; }, }, backups: [ { filterTarget(card, player, target) { return target.countCards("h") > player.countCards("h"); }, async content(event, trigger, player) { player.draw(Math.min(5, event.target.countCards("h") - player.countCards("h"))); if (!player.storage.jsrgzunwei) player.storage.jsrgzunwei = []; player.storage.jsrgzunwei.add(0); }, ai: { order: 10, result: { player: function (player, target) { return Math.min(5, target.countCards("h") - player.countCards("h")); }, }, }, }, { filterTarget(card, player, target) { return target.countCards("e") > player.countCards("e"); }, async content(event, trigger, player) { if (!player.storage.jsrgzunwei) player.storage.jsrgzunwei = []; player.storage.jsrgzunwei.add(1); const target = event.target; do { if ( !target.countCards("e", card => { return player.canEquip(card); }) ) break; const { result: { bool, links }, } = await player .chooseButton([`尊位:将${get.translation(target)}的一张装备牌移至你的区域内`, target.getCards("e")], true) .set("filterButton", button => { return get.player().canEquip(button.link); }) .set("ai", get.buttonValue); if (bool) { target.$give(links[0], player, false); await player.equip(links[0]); } } while (player.countCards("e") < target.countCards("e")); }, ai: { order: 10, result: { player(player, target) { return target.countCards("e") - player.countCards("e"); }, }, }, }, { filterTarget(card, player, target) { if (player.isHealthy()) return false; return target.hp > player.hp; }, async content(event, trigger, player) { player.recover(event.target.hp - player.hp); if (!player.storage.jsrgzunwei) player.storage.jsrgzunwei = []; player.storage.jsrgzunwei.add(2); }, ai: { order: 10, result: { player: function (player, target) { return Math.min(target.hp, player.maxHp) - player.hp; }, }, }, }, ], ai: { order: 10, result: { player: 1, }, }, subSkill: { backup: {}, }, }, //江山如故·转 //404郭嘉 jsrgqingzi: { audio: 2, trigger: { player: "phaseZhunbeiBegin" }, filter: function (event, player) { return game.hasPlayer(current => { if (current == player) return false; return current.hasCard(card => { return lib.filter.canBeDiscarded(card, player, current); }, "e"); }); }, derivation: "xinshensu", direct: true, content: function () { "step 0"; player .chooseTarget(get.prompt("jsrgqingzi"), "弃置任意名其他角色装备区里的一张牌,然后令这些角色获得〖神速〗直到你的下回合开始", [1, Infinity], (card, player, target) => { return ( target != player && target.hasCard(card => { return lib.filter.canBeDiscarded(card, player, target); }, "e") ); }) .set("ai", target => { var player = _status.event.player; return target.hasCard(card => { return (lib.filter.canBeDiscarded(card, player, target) && get.value(card, target) > 3) || (target.hp == 1 && get.value(card, target) > 0); }); }); ("step 1"); if (result.bool) { var targets = result.targets.slice(); targets.sortBySeat(); event.targets = targets; event.num = 0; player.logSkill("jsrgqingzi", targets); player.addSkill("jsrgqingzi_clear"); } else event.finish(); ("step 2"); var target = targets[num]; if ( target.hasCard(card => { return lib.filter.canBeDiscarded(card, player, target); }, "e") ) { player.discardPlayerCard(target, "e", true); target.addAdditionalSkills("jsrgqingzi_" + player.playerid, "xinshensu"); player.markAuto("jsrgqingzi_clear", [target]); } event.num++; if (event.num < targets.length) event.redo(); }, subSkill: { clear: { audio: "jsrgqingzi", charlotte: true, trigger: { global: "die", player: "phaseBegin", }, forced: true, popup: false, forceDie: true, onremove: true, filter: function (event, player) { if (event.name == "die") { return player == event.player || player.getStorage("jsrgqingzi_clear").includes(event.player); } return player.getStorage("jsrgqingzi_clear").length > 0; }, content: function () { "step 0"; var targets = player.getStorage("jsrgqingzi_clear"); if (trigger.name == "die" && player == trigger.player) { for (var target of targets) { target.removeAdditionalSkill(`jsrgqingzi_${player.playerid}`); } player.removeSkill("jsrgqingzi_clear"); event.finish(); return; } if (trigger.name == "phase") event.targets = targets.slice(0).sortBySeat(); else event.targets = [trigger.player]; ("step 1"); var target = targets.shift(); var storage = player.getStorage("jsrgqingzi_clear"); if (storage.includes(target)) { storage.remove(target); target.removeAdditionalSkill(`jsrgqingzi_${player.playerid}`); } if (targets.length > 0) { event.redo(); } else if (!storage.length) { player.removeSkill("jsrgqingzi_clear"); } }, }, }, }, jsrgdingce: { audio: 2, trigger: { player: "damageEnd" }, filter: function (event, player) { if (!event.source || !event.source.isIn()) return false; return player.hasCard(card => { return lib.filter.cardDiscardable(card, player, "jsrgdingce"); }); }, direct: true, content: function () { "step 0"; var target = trigger.source; event.target = target; player .chooseToDiscard(get.prompt("jsrgdingce", target), "弃置你与其的各一张手牌。若这两张牌颜色相同,你视为使用一张【洞烛先机】。") .set("ai", card => { if (_status.event.goon) return 6 - get.value(card); return 0; }) .set( "goon", get.attitude(player, target) < 0 || player .getCards("h") .concat(target.getCards("h")) .filter(card => { return get.value(card) < 5.5; }).length >= 2 ) .set("logSkill", ["jsrgdingce", target]); ("step 1"); if (result.bool) { event.card = result.cards[0]; if (target.countDiscardableCards(player, "h")) { var next = player.discardPlayerCard(target, "h", true); if (target == player) next.set("ai", button => { var card = button.link; return (get.color(card, false) == _status.event.color ? 7.5 : 5) - get.value(card); }).set("color", get.color(event.card, false)); } else event.finish(); } else event.finish(); ("step 2"); if (result.bool) { var card = result.cards[0]; if (get.color(event.card, false) == get.color(card, false)) { game.delayex(); player.chooseUseTarget("dongzhuxianji", true); } } }, }, jsrgzhenfeng: { audio: 2, enable: "phaseUse", locked: false, filter: function (event, player) { if (!event.jsrgzhenfeng) return false; return event.jsrgzhenfeng.some(info => event.filterCard( { name: info[2], nature: info[3], storage: { jsrgzhenfeng: true }, isCard: true, }, player, event ) ); }, onChooseToUse: function (event) { if (!event.jsrgzhenfeng && !game.online) { var str = ""; game.countPlayer(current => { current.getSkills(null, false, false).forEach(skill => { var info = get.info(skill); if (!info || info.charlotte) return; var translation = get.skillInfoTranslation(skill, current); str += translation; }); }); event.set("jsrgzhenfeng", lib.skill.jsrgzhenfeng.getInclusion(str, null, event.player)); } }, getInclusion: function (str, checkCard, player) { let list = []; const names = Object.keys(lib.card); for (const name of names) { let type = get.type(name); if (!["basic", "trick"].includes(type)) continue; if (player && player.getStorage("jsrgzhenfeng_effect").includes(type)) continue; const reg = `【${get.translation(name)}】`; if (name == "sha") { if (str.includes(reg)) { if (checkCard && checkCard.name == name) return true; list.push([type, "", name]); } for (let nature of lib.inpile_nature) { const reg1 = `【${get.translation(nature) + get.translation(name)}】`, reg2 = `${get.translation(nature)}【${get.translation(name)}】`; if (str.includes(reg1) || str.includes(reg2)) { if (checkCard && checkCard.name == name && checkCard.nature == nature) return true; list.push([type, "", name, nature]); } } } else { if (!str.includes(reg)) continue; if (checkCard && checkCard.name == name) return true; list.push([type, "", name]); } } if (checkCard) return false; return list; }, chooseButton: { dialog: function (event, player) { var list = event.jsrgzhenfeng.filter(info => { return event.filterCard( { name: info[2], nature: info[3], storage: { jsrgzhenfeng: true }, isCard: true, }, player, event ); }); return ui.create.dialog("针锋", [list, "vcard"]); }, filter: function (button, player) { return _status.event.getParent().filterCard( { name: button.link[2], nature: button.link[3], storage: { jsrgzhenfeng: true }, isCard: true, }, player, _status.event.getParent() ); }, check: function (button) { var player = _status.event.player; var card = { name: button.link[2], nature: button.link[3], storage: { jsrgzhenfeng: true }, isCard: true, }; var eff = player.getUseValue(card); if (["wugu", "zhulu_card", "yiyi", "lulitongxin", "lianjunshengyan", "diaohulishan"].includes(button.link[2])) eff /= 5; var info = get.info(card); if (info.toself) { var str = player .getSkills(null, false, false) .map(skill => { var info = get.info(skill); if (!info || info.charlotte) return; return get.skillInfoTranslation(skill, player); }) .join("\n"); if (lib.skill.jsrgzhenfeng.getInclusion(str, card)) eff += get.damageEffect(player, player, player); } return eff; }, backup: function (links, player) { return { audio: "jsrgzhenfeng", filterCard: () => false, selectCard: -1, popname: true, viewAs: { name: links[0][2], nature: links[0][3], storage: { jsrgzhenfeng: true }, isCard: true, }, precontent: function () { delete event.result.skill; player.logSkill("jsrgzhenfeng"); event.getParent().addCount = false; player.addTempSkill("jsrgzhenfeng_effect", "phaseUseAfter"); player.markAuto("jsrgzhenfeng_effect", [get.type(event.result.card)]); }, }; }, prompt: function (links, player) { return "视为使用一张" + (get.translation(links[0][3]) || "") + get.translation(links[0][2]); }, }, mod: { cardUsable: function (card) { if (card.storage && card.storage.jsrgzhenfeng) return Infinity; }, targetInRange: function (card) { if (card.storage && card.storage.jsrgzhenfeng) return true; }, }, ai: { order: 1, result: { player: 1, }, }, subSkill: { effect: { audio: "jsrgzhenfeng", trigger: { global: "useCardToBegin", }, charlotte: true, forced: true, onremove: true, filter: function (event, player) { if (!event.card.storage || !event.card.storage.jsrgzhenfeng) return false; // debugger var str = event.target .getSkills(null, false, false) .map(skill => { var info = get.info(skill); if (!info || info.charlotte) return; return get.skillInfoTranslation(skill, event.target); }) .join("\n"); return lib.skill.jsrgzhenfeng.getInclusion(str, event.card); }, logTarget: "target", content: function () { trigger.target.damage(); }, }, }, }, //张飞 jsrgbaohe: { audio: 2, trigger: { global: "phaseUseEnd" }, filter: function (event, player) { return ( player.countCards("he") >= 2 && game.hasPlayer(current => { return current.inRange(event.player) && player.canUse("sha", current, false); }) ); }, direct: true, content: function () { "step 0"; player .chooseToDiscard(get.prompt2("jsrgbaohe"), 2, "he") .set("ai", card => { var val = _status.event.val; if (val > 20) return 6 - get.value(card); if (val > 0) return 4 - get.value(card); return 0; }) .set( "val", game .filterPlayer(current => { return current.inRange(trigger.player) && player.canUse("sha", current, false); }) .map(i => get.effect(i, { name: "sha" }, player, player)) .reduce((p, c) => { return p + c; }, 0) ) .set("logSkill", "jsrgbaohe"); ("step 1"); if (result.bool) { var targets = game.filterPlayer(current => { return current.inRange(trigger.player) && player.canUse("sha", current, false); }); if (targets.length) { game.delayex(); player.useCard({ name: "sha", isCard: true, storage: { jsrgbaohe: true } }, targets, false); player.addTempSkill("jsrgbaohe_add"); } } }, subSkill: { add: { audio: "jsrgbaohe", trigger: { global: "useCard", }, charlotte: true, forced: true, filter: function (event, player) { let evt = event.getParent(3), respondTo = event.respondTo; if (evt.name != "useCard" || !Array.isArray(respondTo) || !respondTo[1].storage || !respondTo[1].storage.jsrgbaohe) return false; return evt.targets.length > evt.num + 1; }, logTarget: function (event) { let evt = event.getParent(3); return evt.targets.slice(evt.num + 1); }, content: function () { "step 0"; var evt = trigger.getParent(3); var targets = evt.targets.slice(evt.num + 1); var map = evt.customArgs; for (var target of targets) { var id = target.playerid; if (!map[id]) map[id] = {}; if (typeof map[id].extraDamage != "number") { map[id].extraDamage = 0; } map[id].extraDamage++; } game.delayx(); }, }, }, }, jsrgxushi: { audio: 2, enable: "phaseUse", usable: 1, filterCard: true, filterTarget: lib.filter.notMe, selectCard: [1, Infinity], selectTarget: [1, Infinity], position: "he", filterOk: function () { return ui.selected.cards.length == ui.selected.targets.length; }, check: function (card) { var player = get.player(); if ( ui.selected.cards.length >= game.countPlayer(current => { return current != player && get.attitude(player, current) > 0; }) ) return 0; return 5 - get.value(card); }, prompt: "按顺序选择卡牌和角色,并将卡牌交给对应顺序的角色。然后你获得两倍数量的【影】。", complexSelect: true, multitarget: true, multiline: true, discard: false, lose: false, delay: false, contentBefore: function () { event.getParent()._jsrgxushi_targets = targets.slice(); }, content: function () { "step 0"; var targets = event.getParent()._jsrgxushi_targets; var list = []; for (var i = 0; i < targets.length; i++) { var target = targets[i]; var card = cards[i]; list.push([target, card]); player.line(target); } game.loseAsync({ gain_list: list, player: player, cards: cards, giver: player, animate: "giveAuto", }).setContent("gaincardMultiple"); ("step 1"); player.gain(lib.card.ying.getYing(2 * cards.length), "gain2"); }, ai: { order: 2.5, result: { target: function (player, target) { var card = ui.selected.cards[ui.selected.targets.length]; if (!card) return 0; if (get.value(card) < 0) return -1; if (get.value(card) < 1.5 && player.hasSkill("jsrgbaohe")) return (get.sgnAttitude(player, target) + 0.01) / 5; return Math.sqrt(5 - Math.min(4, target.countCards("h"))); }, }, }, }, jsrgzhuiming: { audio: 2, trigger: { player: "useCardToPlayered", }, filter: function (event, player) { if (event.card.name != "sha") return false; return event.isFirstTarget && event.targets.length == 1 && event.target.isIn(); }, direct: true, content: function* (event, map) { var player = map.player, trigger = map.trigger, target = trigger.target; var colors = Object.keys(lib.color).remove("none"); var result = yield player .chooseControl(colors, "cancel2") .set("prompt", get.prompt("jsrgzhuiming")) .set("prompt2", `声明一种颜色并令${get.translation(trigger.target)}弃置任意张牌`) .set("ai", () => { var player = get.player(), target = get.event("target"), att = get.attitude(player, target) > 0 ? 1 : -1; var list = get .event("controls") .map(i => [ i, target .getCards("he") .map(get.value) .reduce((p, c) => p + c, 0), ]) .sort((a, b) => { return att * (a[1] - b[1]); }); return list[0][0]; }) .set("target", target); var color = result.control; if (color == "cancel2") { event.finish(); return; } player.logSkill("jsrgzhuiming", target); player.popup(color, color == "red" ? "fire" : "thunder"); game.log(player, "声明了", color); var prompt = `追命:${get.translation(player)}声明了${get.translation(color)}`, prompt2 = `请弃置任意张牌,然后其展示你一张牌,若此牌颜色为${get.translation(color)},此【杀】不计入次数限制、不可被响应且伤害+1`; yield target .chooseToDiscard(prompt, prompt2, [1, Infinity], "he", true) .set("ai", card => { var color = get.event("color"), player = get.player(); if (get.position(card) == "e" && get.color(card) == color) return 2; if (player.getHp() <= 2 && get.color(card) == color) return Math.random() < 0.5; return 0; }) .set("color", color); if (target.countCards("he")) result = yield player .choosePlayerCard(target, "he", true) .set("ai", button => { var color = get.event("color"), att = get.event("att"); if (get.position(button.link) == "e" && get.color(button.link) == color) { return 100 * att; } return 1 + Math.random(); }) .set("color", color) .set("att", get.attitude(player, target) > 0 ? 1 : -1); else { event.finish(); return; } var card = result.cards[0]; player.showCards(card, `${get.translation(target)}因【追命】被展示`); if (get.color(card) == color) { trigger.directHit.addArray(game.players); var evt = trigger.getParent(); if (evt.addCount !== false) { evt.addCount = false; player.getStat().card.sha--; } var map = trigger.getParent().customArgs; var id = target.playerid; if (!map[id]) map[id] = {}; if (typeof map[id].extraDamage != "number") { map[id].extraDamage = 0; } map[id].extraDamage++; game.log(trigger.card, "不计入次数限制、不可被响应、伤害+1"); } }, }, //娄圭 jsrgshacheng: { audio: 2, trigger: { global: "useCardAfter" }, filter: function (event, player) { if (event.card.name != "sha") return false; return event.targets.some(i => i.isIn() && i.hasHistory("lose", evt => evt.cards2.length)) && player.getExpansions("jsrgshacheng").length; }, direct: true, group: "jsrgshacheng_build", content: function () { "step 0"; if (_status.connectMode) game.broadcastAll(function () { _status.noclearcountdown = true; }); var targets = trigger.targets.filter(i => i.isIn() && i.hasHistory("lose", evt => evt.cards2.length)); player .chooseTarget(get.prompt("jsrgshacheng"), "令一名目标角色摸X张牌,然后移去一张“城”(X为对应角色本回合失去过的牌数且至多为5)", (card, player, target) => { return get.event("targets").includes(target); }) .set("targets", targets) .set("ai", target => { return target == get.event("targetx") ? 1 : 0; }) .set( "targetx", (() => { let info = []; targets.filter(target => { let att = get.attitude(player, target); if (att <= 0) return false; if (Math.abs(att) > 1) att = Math.sign(att) * Math.sqrt(Math.abs(att)); info.push([ target, att * target .getHistory("lose") .map(evt => evt.cards2.length) .reduce((p, c) => p + c, 0), ]); return false; }); if (!info.length) return null; info = info.sort((a, b) => { return b[1] - a[1]; })[0]; if (info[1] <= 0) return null; return info[0]; })() ); ("step 1"); if (result.bool) { event.target = result.targets[0]; var cards = player.getExpansions("jsrgshacheng"); if (cards.length == 1) event._result = { bool: true, links: cards }; else player.chooseButton([`沙城:移去一张“城”`, cards], true); } else { if (_status.connectMode) { game.broadcastAll(function () { delete _status.noclearcountdown; game.stopCountChoose(); }); } event.finish(); } ("step 2"); if (_status.connectMode) { game.broadcastAll(function () { delete _status.noclearcountdown; game.stopCountChoose(); }); } if (result.bool) { player.logSkill("jsrgshacheng", target); player.loseToDiscardpile(result.links); target.draw( Math.min( 5, target .getHistory("lose") .map(evt => evt.cards2.length) .reduce((p, c) => p + c, 0) ) ); } }, marktext: "城", intro: { content: "expansion", markcount: "expansion", }, onremove: function (player, skill) { var cards = player.getExpansions(skill); if (cards.length) player.loseToDiscardpile(cards); }, subSkill: { build: { trigger: { global: "phaseBefore", player: "enterGame", }, forced: true, locked: false, filter: function (event, player) { return event.name != "phase" || game.phaseNumber == 0; }, content: function () { var cards = get.cards(2); player.addToExpansion(cards, "gain2").gaintag.add("jsrgshacheng"); }, }, }, }, jsrgninghan: { audio: 2, init: player => { game.addGlobalSkill("jsrgninghan_frozen"); }, onremove: player => { if (!game.hasPlayer(current => current.hasSkill("jsrgninghan"), true)) game.removeGlobalSkill("jsrgninghan_frozen"); }, trigger: { global: "damageEnd" }, filter: function (event, player) { if (!event.hasNature("ice")) return false; return event.cards && event.cards.filterInD().length; }, forced: true, content: function () { var cards = trigger.cards.filterInD(); player.addToExpansion(cards, "gain2").gaintag.add("jsrgshacheng"); }, subSkill: { frozen: { mod: { cardnature: function (card, player) { if (card.name === "sha" && get.suit(card) === "club") return "ice"; }, aiOrder: (player, card, num) => { if (num && card.name === "sha" && game.hasNature(card, "ice")) { let lg = game.findPlayer(current => current.hasSkill("jsrgninghan")); if (lg) return num + 0.15 * Math.sign(get.attitude(player, lg)); } }, }, trigger: { player: "dieAfter" }, filter: (event, player) => { return !game.hasPlayer(current => !current.hasSkill("jsrgninghan"), true); }, silent: true, forceDie: true, content: () => { game.removeGlobalSkill("jsrgninghan_frozen"); }, }, }, ai: { combo: "jsrgshacheng", }, }, //张任 jsrgfuni: { audio: 2, trigger: { global: "roundStart" }, group: ["jsrgfuni_unlimit", "jsrgfuni_zero"], forced: true, direct: true, content: function* (event, map) { var player = map.player, trigger = map.trigger; var count = Math.ceil(game.countPlayer() / 2); var result = yield player.chooseTarget(`伏匿:请选择至多${get.cnNumber(count)}名角色`, `令这些角色获得共计${get.cnNumber(count)}张【影】`, true, [1, count]).set("ai", target => { return get.attitude(get.player(), target) + get.event().getRand(target.playerid); }); if (result.bool) { var targets = result.targets.slice().sortBySeat(_status.currentPhase); player.logSkill("jsrgfuni", targets); } else event.finish(); yield null; var num = count / targets.length; if (num == 1 || num == count) { result = { bool: true, links: targets.map(current => { return `${num}|${current.playerid}`; }), }; } else { var dialog = ["伏匿:选择每名角色要获得的【影】数"]; var len = count - targets.length + 1; for (var target of targets) { dialog.addArray([ `
    ${get.translation(target)}
    `, [ Array.from({ length: len }).map((_, i) => { return [`${i + 1}|${target.playerid}`, get.cnNumber(i + 1, true)]; }), "tdnodes", ], ]); } result = yield player .chooseButton(dialog, true) .set("filterButton", button => { var total = 0, info = button.link.split("|"); var numFix = 0; for (var buttonx of ui.selected.buttons) { var infox = buttonx.link.split("|"); var num = parseInt(infox[0]); total += num; if (infox[1] == info[1]) numFix = num; } return total + parseInt(info[0]) - numFix <= get.event("count"); }) .set("count", count) .set("filterOk", () => { var total = 0; for (var buttonx of ui.selected.buttons) { total += parseInt(buttonx.link.split("|")[0]); } return total == get.event("count"); }) .set("selectButton", () => { return [get.event("len"), Math.max(get.event("len"), ui.selected.buttons.length) + 1]; }) .set("len", targets.length) .set("custom", { add: {}, replace: { button: function (button) { if (!_status.event.isMine()) return; if (button.classList.contains("selectable") == false) return; if (button.classList.contains("selected")) { ui.selected.buttons.remove(button); button.classList.remove("selected"); if (_status.multitarget || _status.event.complexSelect) { game.uncheck(); game.check(); } } else { var current = button.parentNode.querySelector(".selected"); if (current) { ui.selected.buttons.remove(current); current.classList.remove("selected"); } button.classList.add("selected"); ui.selected.buttons.add(button); } game.check(); }, }, }) .set("processAI", () => { return get.event("aiResult"); }) .set( "aiResult", (() => { var result = targets.map(i => { return [i == player ? 2 : 1, i.playerid]; }); var rest = count - targets.length - 1; while (rest--) result[Math.floor(Math.random() * result.length)][0]++; return { bool: true, links: result.map(i => `${i[0]}|${i[1]}`), }; })() ); } if (result.bool) { var links = result.links; var list = []; for (var link of links) { var info = link.split("|"); var id = info[1]; var target = (_status.connectMode ? lib.playerOL : game.playerMap)[id]; player.line(target); var yings = lib.card.ying.getYing(parseInt(info[0])); list.push([target, yings]); game.log(target, "获得了", yings); } game.loseAsync({ gain_list: list, animate: "gain2", }).setContent("gaincardMultiple"); } }, subSkill: { zero: { priority: Infinity, mod: { attackRange: () => 0, }, }, unlimit: { audio: "jsrgfuni", trigger: { global: ["loseAfter", "loseAsyncAfter", "cardsDiscardAfter"], }, filter: function (event, player) { return event.getd().some(i => get.name(i, false) == "ying"); }, forced: true, content: function () { player.addTempSkill("jsrgfuni_buff"); }, }, buff: { charlotte: true, trigger: { player: "useCard1" }, forced: true, popup: false, content: function () { trigger.directHit.addArray(game.players); game.log(trigger.card, "不可被响应"); }, mark: true, intro: { content: "使用牌无距离限制且不能被响应", }, mod: { targetInRange: () => true, }, }, }, ai: { expose: 0.15, halfneg: true, }, }, jsrgchuanxin: { audio: 2, trigger: { global: "phaseJieshuBegin" }, filter: function (event, player) { return ( player.countCards("hes") && game.hasPlayer(current => player.canUse( { name: "sha", storage: { jsrgchuanxin: true }, }, current ) ) ); }, direct: true, content: function () { var next = player.chooseToUse(); next.set("openskilldialog", `###${get.prompt("jsrgchuanxin")}###将一张牌当【杀】使用,且当一名角色受到此【杀】伤害时,此伤害+X(X为其本回合回复过的体力值)。`); next.set("norestore", true); next.set("_backupevent", "jsrgchuanxin_backup"); next.set("addCount", false); next.set("logSkill", "jsrgchuanxin"); next.set("custom", { add: {}, replace: { window: function () {} }, }); next.backup("jsrgchuanxin_backup"); }, subSkill: { backup: { filterCard: function (card) { return get.itemtype(card) == "card"; }, viewAs: { name: "sha", storage: { jsrgchuanxin: true }, }, selectCard: 1, position: "hes", ai1: function (card) { var player = get.player(); var maxVal = 5.5; if (get.name(card, false) == "ying" && player.hasSkill("jsrgchuanxin")) maxVal -= 3; return maxVal - get.value(card); }, precontent: function () { delete event.result.skill; player.addTempSkill("jsrgchuanxin_add"); }, }, add: { trigger: { global: "damageBegin3" }, filter: function (event, player) { if (!event.card || !event.card.storage || !event.card.storage.jsrgchuanxin) return false; if (event.getParent().type != "card") return false; return game.hasGlobalHistory("changeHp", evt => { return evt.getParent().name == "recover" && evt.player == event.player; }); }, forced: true, charlotte: true, content: function () { var num = game .getGlobalHistory("changeHp", evt => { return evt.getParent().name == "recover" && evt.player == trigger.player; }) .map(evt => evt.num) .reduce((p, c) => p + c, 0); trigger.num += num; game.log(trigger.card, "的伤害+" + num); }, }, }, }, //黄忠 jsrgcuifeng: { audio: 2, enable: "phaseUse", limited: true, skillAnimation: true, animationColor: "orange", locked: false, chooseButton: { dialog: function (event, player) { var list = []; for (var name of lib.inpile) { var info = lib.card[name]; if (!info || info.notarget || (info.selectTarget && info.selectTarget != 1) || !get.tag({ name: name }, "damage")) continue; if (name == "sha") { list.push(["基本", "", "sha"]); for (var nature of lib.inpile_nature) list.push(["基本", "", name, nature]); } else if (get.type(name) == "trick") list.push(["锦囊", "", name]); else if (get.type(name) == "basic") list.push(["基本", "", name]); } return ui.create.dialog("摧锋", [list, "vcard"]); }, filter: function (button, player) { return _status.event.getParent().filterCard( { name: button.link[2], nature: button.link[3], isCard: true, storage: { jsrgcuifeng: true }, }, player, _status.event.getParent() ); }, check: function (button) { var player = _status.event.player; var effect = player.getUseValue({ name: button.link[2], nature: button.link[3], storage: { jsrgcuifeng: true }, }); if (effect > 0) return effect; return 0; }, backup: function (links, player) { return { audio: "jsrgcuifeng", selectCard: -1, filterCard: () => false, popname: true, viewAs: { name: links[0][2], nature: links[0][3], isCard: true, storage: { jsrgcuifeng: true }, }, precontent: function () { player.logSkill("jsrgcuifeng"); player.awakenSkill("jsrgcuifeng"); delete event.result.skill; if (!player.storage.jsrgcuifeng_check) player .when("phaseEnd") .then(() => { var num = 0; player.checkHistory("sourceDamage", evt => { if (evt.card.storage.jsrgcuifeng) num += evt.num; }); if (num == 0 || num > 1) { player.restoreSkill("jsrgcuifeng"); game.log(player, "重置了", "#g【摧锋】"); } delete player.storage.jsrgcuifeng_check; }) .translation("摧锋"); player.setStorage("jsrgcuifeng_check", true); }, }; }, prompt: function (links, player) { return "请选择" + (get.translation(links[0][3]) || "") + get.translation(links[0][2]) + "的目标"; }, }, mod: { targetInRange: card => { if (card.storage && card.storage.jsrgcuifeng) return true; }, }, ai: { order: 1.9, result: { player: 1, }, }, }, jsrgdengnan: { audio: 2, enable: "phaseUse", limited: true, skillAnimation: true, animationColor: "orange", chooseButton: { dialog: function (event, player) { var list = []; for (var name of lib.inpile) { var info = lib.card[name]; if (!info || info.type != "trick" || info.notarget || get.tag({ name: name }, "damage")) continue; list.push(["锦囊", "", name]); } return ui.create.dialog("登难", [list, "vcard"]); }, filter: function (button, player) { return _status.event.getParent().filterCard({ name: button.link[2], isCard: true }, player, _status.event.getParent()); }, check: function (button) { var player = _status.event.player; return player.getUseValue(button.link[2]); }, backup: function (links, player) { return { audio: "jsrgdengnan", selectCard: -1, filterCard: () => false, popname: true, viewAs: { name: links[0][2], isCard: true, storage: { jsrgdengnan: true }, }, precontent: function () { player.logSkill("jsrgdengnan"); player.awakenSkill("jsrgdengnan"); delete event.result.skill; if (!player.storage.jsrgdengnan_check) player .when("phaseEnd") .then(() => { var targets = []; player.checkHistory("useCard", evt => { if (evt.card.storage.jsrgdengnan) targets.addArray(evt.targets); }); if ( targets.every(current => { return current.hasHistory("damage"); }) ) { player.restoreSkill("jsrgdengnan"); game.log(player, "重置了", "#g【登难】"); } delete player.storage.jsrgdengnan_check; }) .translation("登难"); player.setStorage("jsrgdengnan_check", true); }, }; }, prompt: function (links, player) { return "请选择" + (get.translation(links[0][3]) || "") + get.translation(links[0][2]) + "的目标"; }, }, ai: { order: 2, result: { player: 1, }, }, }, //夏侯荣 jsrgfenjian: { audio: 2, enable: "chooseToUse", locked: false, filter: function (event, player) { return ["juedou", "tao"].some(name => { return ( !player.getStorage("jsrgfenjian_used").includes(name) && event.filterCard( { name: name, isCard: true, storage: { jsrgfenjian: true }, }, player, event ) ); }); }, hiddenCard: function (player, name) { if (["juedou", "tao"].some(i => i == name && !player.getStorage("jsrgfenjian_used").includes(name))) return true; return false; }, chooseButton: { dialog: function (event, player) { var dialog = ui.create.dialog("奋剑", [["juedou", "tao"].filter(name => !player.getStorage("jsrgfenjian_used").includes(name)), "vcard"]); dialog.direct = true; return dialog; }, filter: function (button, player) { var evt = _status.event.getParent(); return evt.filterCard( { name: button.link[2], isCard: true, storage: { jsrgfenjian: true }, }, player, evt ); }, check: function (button) { if (button.link[2] === "tao") { let dying = _status.event.getParent(2).dying; if (dying) return get.effect( dying, { name: "tao", isCard: true, storage: { jsrgfenjian: true }, }, _status.event.player ); } return _status.event.player.getUseValue({ name: button.link[2], isCard: true, storage: { jsrgfenjian: true }, }); }, backup: function (links) { return { audio: "jsrgfenjian", viewAs: { name: links[0][2], isCard: true, storage: { jsrgfenjian: true }, }, filterCard: () => false, selectCard: -1, precontent: function () { player.logSkill("jsrgfenjian"); delete event.result.skill; player.addTempSkill("jsrgfenjian_effect"); player.addMark("jsrgfenjian_effect", 1, false); if (!player.storage.jsrgfenjian_used) player.when({ global: "phaseAfter" }).then(() => { delete player.storage.jsrgfenjian_used; }); player.markAuto("jsrgfenjian_used", [event.result.card.name]); }, }; }, prompt: function (links) { return "奋剑:令你本回合受到的伤害+1,视为使用" + get.translation(links[0][2]); }, }, mod: { targetEnabled: function (card, player, target) { if (player == target && card.storage && card.storage.jsrgfenjian) return false; }, }, ai: { order: function (item, player) { return Math.max(get.order({ name: "juedou" }), get.order({ name: "tao" })) + 0.2; }, result: { player: player => { if (_status.event.dying) return 2 * get.sgnAttitude(player, _status.event.dying); return 1; }, }, }, subSkill: { effect: { audio: "jsrgfenjian", charlotte: true, trigger: { player: "damageBegin3" }, forced: true, onremove: true, content: function () { trigger.num += player.countMark("jsrgfenjian_effect"); }, intro: { content: "本回合受到的伤害+#" }, }, }, }, //孙尚香 jsrgguiji: { audio: 2, enable: "phaseUse", filter: function (event, player) { if (player.hasSkill("jsrgguiji_used")) return false; return game.hasPlayer(current => lib.skill.jsrgguiji.filterTarget("keiki", player, current)); }, filterTarget: function (card, player, target) { return target.countCards("h") < player.countCards("h") && target.hasSex("male"); }, content: function () { "step 0"; player.swapHandcards(target); player.addSkill("jsrgguiji_swapback"); player.markAuto("jsrgguiji_swapback", target); player.addTempSkill("jsrgguiji_used"); }, ai: { order: 6, result: { target: function (player, target) { var val = player .getCards("h") .map(i => get.value(i)) .reduce((p, c) => p + c, 0); var val2 = target .getCards("h") .map(i => get.value(i)) .reduce((p, c) => p + c, 0); return val - val2; }, }, }, subSkill: { used: { charlotte: true }, swapback: { audio: "jsrgguiji", trigger: { global: ["phaseUseEnd", "dieAfter"], }, filter: function (event, player) { return player.getStorage("jsrgguiji_swapback").includes(event.player); }, charlotte: true, direct: true, check: function (event, player) { return ( player .getCards("h") .map(i => get.value(i)) .reduce((p, c) => p + c, 0) < event.player .getCards("h") .map(i => get.value(i)) .reduce((p, c) => p + c, 0) + 4 * Math.random() ); }, content: function () { "step 0"; player.unmarkAuto("jsrgguiji_swapback", [trigger.player]); if (trigger.name == "phaseUse") { player .chooseBool(get.prompt("jsrgguiji_swapback", trigger.player), "与其交换手牌。") .set("ai", () => { return get.event("bool"); }) .set("bool", lib.skill.jsrgguiji_swapback.check(trigger, player) > 0); } else { event.finish(); } ("step 1"); if (result.bool) { player.logSkill("jsrgguiji_swapback", trigger.player); player.swapHandcards(trigger.player); } }, intro: { content: "$的下个出牌阶段结束时,你可以与其交换手牌", }, }, }, }, jsrgjiaohao: { audio: 2, trigger: { player: "phaseZhunbeiBegin" }, filter: function (event, player) { return [1, 2, 3, 4, 5].some(i => player.countEmptySlot(i)); }, forced: true, locked: false, global: "jsrgjiaohao_g", content: function () { "step 0"; var count = Math.ceil([1, 2, 3, 4, 5].map(i => player.countEmptySlot(i)).reduce((p, c) => p + c, 0) / 2); player.gain(lib.card.ying.getYing(count), "gain2"); }, subSkill: { g: { audio: "jsrgjiaohao", enable: "phaseUse", usable: 1, filter: function (event, player) { return game.hasPlayer(current => { if (current == player || !current.hasSkill("jsrgjiaohao")) return false; return player.hasCard(card => { return get.type(card) == "equip" && current.canEquip(card); }); }); }, filterTarget: function (card, player, target) { if (target.isMin()) return false; return target != player && target.hasSkill("jsrgjiaohao") && target.canEquip(card); }, selectTarget: function () { var num = game.countPlayer(current => { return current.hasSkill("jsrgjiaohao"); }); return num > 1 ? 1 : -1; }, filterCard: function (card) { return get.type(card) == "equip"; }, check: function (card) { var player = get.player(); if (player.countCards("he", { subtype: get.subtype(card) }) > 1) { return 11 - get.equipValue(card); } return 6 - get.value(card); }, prompt: function () { var list = game.filterPlayer(current => { return current.hasSkill("jsrgjiaohao"); }); return `将一张装备牌置于${get.translation(list)}${list.length > 1 ? "中的一人" : ""}的装备区`; }, discard: false, lose: false, prepare: function (cards, player, targets) { player.$give(cards, targets[0], false); }, content: function () { target.equip(cards[0]); }, ai: { order: 10, result: { target: function (player, target) { var card = ui.selected.cards[0]; if (card) return get.effect(target, card, target, target); return 0; }, }, }, }, }, }, //庞统 jsrgmanjuan: { audio: 2, trigger: { player: "loseEnd", global: ["equipEnd", "addJudgeEnd", "gainEnd", "loseAsyncEnd", "addToExpansionEnd"], }, filter: function (event, player) { return (player.countCards("h") == 0) ^ player.hasSkill("jsrgmanjuan_in"); }, forced: true, locked: false, firstDo: true, silent: true, content: function () { "step 0"; if (!player.countCards("h")) { var cards = []; game.checkGlobalHistory("cardMove", evt => { if ((evt.name == "lose" && evt.position == ui.discardPile) || evt.name == "cardsDiscard") { cards.addArray(evt.cards.filterInD("d")); } }); var cardsx = cards.map(card => { var cardx = ui.create.card(); cardx.init(get.cardInfo(card)); cardx._cardid = card.cardid; return cardx; }); player.directgains(cardsx, null, "jsrgmanjuan"); player.addSkill("jsrgmanjuan_in"); } else { player.removeSkill("jsrgmanjuan_in"); } }, subSkill: { in: { audio: "jsrgmanjuan", trigger: { global: ["loseAfter", "loseAsyncAfter", "cardsDiscardAfter", "equipAfter"], }, forced: true, locked: false, silent: true, filter: function (event, player) { var cards = event.getd(); return cards.length; }, onremove: function (player) { var cards2 = player.getCards("s", card => { return card.hasGaintag("jsrgmanjuan"); }); if (player.isOnline2()) { player.send( function (cards, player) { cards.forEach(i => i.delete()); if (player == game.me) ui.updatehl(); }, cards2, player ); } cards2.forEach(i => i.delete()); if (player == game.me) ui.updatehl(); }, group: ["jsrgmanjuan_use", "jsrgmanjuan_lose"], content: function () { var cards = []; var idList = player.getCards("s", card => card.hasGaintag("jsrgmanjuan")).map(i => i._cardid); game.checkGlobalHistory("cardMove", evt => { if ((evt.name == "lose" && evt.position == ui.discardPile) || evt.name == "cardsDiscard") { cards.addArray(evt.cards.filter(i => get.position(i, true) == "d" && !idList.includes(i.cardid))); } }); var cards2 = cards.map(card => { var cardx = ui.create.card(); cardx.init(get.cardInfo(card)); cardx._cardid = card.cardid; return cardx; }); player.directgains(cards2, null, "jsrgmanjuan"); }, mod: { cardEnabled2: function (card, player) { if (get.itemtype(card) == "card" && card.hasGaintag("jsrgmanjuan") && player.getStorage("jsrgmanjuan_used").includes(get.number(card, false))) return false; }, }, }, use: { trigger: { player: ["useCardBefore", "respondBefore"], }, charlotte: true, forced: true, popup: false, firstDo: true, filter: function (event, player) { var cards = player.getCards("s", card => card.hasGaintag("jsrgmanjuan") && card._cardid); return ( event.cards && event.cards.some(card => { return cards.includes(card); }) ); }, content: function () { var idList = player.getCards("s", card => card.hasGaintag("jsrgmanjuan")).map(i => i._cardid); var cards = []; game.checkGlobalHistory("cardMove", evt => { if ((evt.name == "lose" && evt.position == ui.discardPile) || evt.name == "cardsDiscard") { cards.addArray(evt.cards.filter(i => idList.includes(i.cardid))); } }); var cards2 = []; for (var card of trigger.cards) { var cardx = cards.find(cardx => cardx.cardid == card._cardid); if (cardx) cards2.push(cardx); } var cards3 = trigger.cards.slice(); trigger.cards = cards2; trigger.card.cards = cards2; if (player.isOnline2()) { player.send( function (cards, player) { cards.forEach(i => i.delete()); if (player == game.me) ui.updatehl(); }, cards3, player ); } cards3.forEach(i => i.delete()); if (player == game.me) ui.updatehl(); if (!player.storage.jsrgmanjuan_used) { player.when({ global: "phaseAfter" }).then(() => { delete player.storage.jsrgmanjuan_used; }); } player.markAuto( "jsrgmanjuan_used", cards3.map(card => get.number(card, false)) ); }, }, lose: { trigger: { global: ["loseEnd", "equipEnd", "addJudgeEnd", "gainEnd", "loseAsyncEnd", "addToExpansionEnd", "cardsGotoOrderingBegin", "phaseAfter"], }, charlotte: true, forced: true, popup: false, firstDo: true, filter: function (event, player) { if (event.name == "phase") return true; var idList = player.getCards("s", card => card.hasGaintag("jsrgmanjuan")).map(i => i._cardid); return ( event.cards && event.cards.some(card => { return idList.includes(card.cardid); }) ); }, content: function () { var cards2; if (trigger.name == "phase") { cards2 = player.getCards("s", card => { return card.hasGaintag("jsrgmanjuan"); }); } else { var idList = []; game.checkGlobalHistory("cardMove", evt => { if ((evt.name == "lose" && evt.position == ui.discardPile) || evt.name == "cardsDiscard") { idList.addArray(evt.cards.filter(i => get.position(i, true) == "d").map(i => i.cardid)); } }); cards2 = player.getCards("s", card => { return card.hasGaintag("jsrgmanjuan") && !idList.includes(card._cardid); }); } if (player.isOnline2()) { player.send( function (cards, player) { cards.forEach(i => i.delete()); if (player == game.me) ui.updatehl(); }, cards2, player ); } cards2.forEach(i => i.delete()); if (player == game.me) ui.updatehl(); }, }, }, }, jsrgyangming: { audio: 2, enable: "phaseUse", usable: 1, filter: function (event, player) { return game.hasPlayer(current => { return player.canCompare(current); }); }, filterTarget: function (card, player, current) { return player.canCompare(current); }, content: function () { "step 0"; target.addTempSkill("jsrgyangming_lose", "phaseUseAfter"); ("step 1"); player.chooseToCompare(target).set( "small", get.attitude(player, target) > 0 && (player.countCards("h", card => { return get.value(card) < 6; }) <= 1 || target.countCards("h", card => { return get.value(card) < 6; }) <= 1) ); ("step 2"); if (result.winner != target) { if (!player.canCompare(target)) event._result = { bool: false }; else player .chooseBool("是否与其重复此拼点流程?") .set("ai", () => get.event("bool")) .set("bool", get.effect(target, "jsrgyangming", player, player) > 0); game.broadcastAll(target => { target.storage.jsrgyangming_lose++; }, target); } else { if (target.storage.jsrgyangming_lose) target.draw(target.storage.jsrgyangming_lose); player.recover(); event.finish(); } ("step 3"); if (result.bool) { event.goto(1); } }, ai: { order: 1, expose: 0.15, result: { target: function (player, target) { var maxnum = 0; var cards2 = target.getCards("h"); for (var i = 0; i < cards2.length; i++) { if (get.number(cards2[i]) > maxnum) { maxnum = get.number(cards2[i]); } } if (maxnum > 10) maxnum = 10; if (maxnum < 5 && cards2.length > 1) maxnum = 5; var cards = player.getCards("h"); for (var i = 0; i < cards.length; i++) { if (get.number(cards[i]) < maxnum) return 1; } return 0; }, }, }, subSkill: { lose: { init(player, skill) { player.storage[skill] = 0; }, onremove: true, charlotte: true, }, }, }, //韩遂 jsrgniluan: { audio: "niluan", trigger: { player: "phaseZhunbeiBegin" }, direct: true, content: function () { "step 0"; var damaged = game.filterPlayer(current => { return current.hasAllHistory("sourceDamage", evt => evt.player == player); }); var undamaged = game.filterPlayer().removeArray(damaged); player.chooseCardTarget({ prompt: get.prompt("jsrgniluan"), prompt2: `${undamaged.length ? "选择一张牌弃置并选择一名未对你造成过伤害的角色,你对其造成1点伤害" : ""}${undamaged.length && damaged.length ? ";
    或" : ""}${damaged.length ? "仅选择一名对你造成过伤害的角色,你令其摸两张牌" : ""}。`, damaged: damaged, aiTarget: (() => { if ( undamaged.includes(player) && !undamaged.some(i => { if (i === player) return false; let att = get.attitude(player, i); if (att > 0) return true; return att < 0 && i.getHp(true) + i.hujia < 2; }) && (player.hp > 2 || get.damageEffect(player, player, player) >= 0) ) return player; var info = game .filterPlayer() .map(current => { let damage = undamaged.includes(current), card = { name: damage ? "damage" : "draw" }; return [current, get.effect(current, card, player, player) * (damage ? 0.7 : 2)]; }) .sort((a, b) => b[1] - a[1])[0]; if (info[1] > 0) return info[0]; return null; })(), filterCard: lib.filter.cardDiscardable, selectCard: function () { if (get.event("damaged").length == 0) return 1; if (get.event("damaged").length == game.countPlayer()) return 0; return [0, 1]; }, position: "he", filterTarget: function (card, player, target) { var damaged = get.event("damaged"); return damaged.includes(target) ^ (ui.selected.cards.length > 0); }, selectTarget: 1, ai1: function (card) { if (get.event("damaged").includes(get.event("aiTarget"))) return 0; return 6 - get.value(card); }, ai2: function (target) { return target == get.event("aiTarget") ? 10 : 0; }, }); ("step 1"); if (result.bool) { var cards = result.cards, target = result.targets[0]; player.logSkill("jsrgniluan", target); if (cards && cards.length) { player.discard(cards); game.delayex(); target.damage(); } else { target.draw(2); } } }, }, jsrghuchou: { audio: 2, trigger: { source: "damageBegin1" }, filter: function (event, player) { const history = _status.globalHistory; for (let i = history.length - 1; i >= 0; i--) { let evts = history[i]["useCard"]; for (let j = evts.length - 1; j >= 0; j--) { var evt = evts[j]; let card = evt.card, targets = evt.targets; if (!get.tag(card, "damage") || !targets.includes(player)) continue; return event.player == evt.player; } } return false; }, forced: true, content: function () { trigger.num++; }, ai: { damageBonus: true, skillTagFilter: (player, tag, arg) => { if (tag === "damageBonus" && arg && arg.target) { const history = _status.globalHistory; for (let i = history.length - 1; i >= 0; i--) { let evts = history[i]["useCard"]; for (let j = evts.length - 1; j >= 0; j--) { var evt = evts[j]; let card = evt.card, targets = evt.targets; if (!get.tag(card, "damage") || !targets.includes(player)) continue; return arg.target === evt.player; } } return false; } }, effect: { player: (card, player, target) => { if ( get.tag(card, "damage") && target && lib.skill.jsrghuchou.ai.skillTagFilter(player, "damageBonus", { card: card, target: target, }) && !target.hasSkillTag("filterDamage", null, { player: player, card: card, }) ) return [1, 0, 2, 0]; }, }, }, }, jsrgjiemeng: { audio: 2, zhuSkill: true, forced: true, init: () => { game.addGlobalSkill("jsrgjiemeng_effect"); }, onremove: () => { if (!game.hasPlayer(i => i.hasSkill("jsrgjiemeng"), true)) game.removeGlobalSkill("jsrgjiemeng_effect"); }, subSkill: { effect: { mod: { globalFrom: function (from, to, distance) { if (from.group != "qun") return; if (to.hasZhuSkill("jsrgjiemeng")) return; return distance - game.countPlayer(current => current.group == "qun"); }, }, trigger: { player: "dieAfter" }, filter: () => { return !game.hasPlayer(i => i.hasSkill("jsrgjiemeng"), true); }, silent: true, forceDie: true, content: () => { game.removeGlobalSkill("jsrgjiemeng_effect"); }, }, }, }, //张楚 jsrghuozhong: { audio: "dcjizhong", global: "jsrghuozhong_g", subSkill: { g: { audio: "dcjizhong", enable: "phaseUse", usable: 1, filter: function (event, player) { if (player.hasJudge("bingliang")) return false; if (!game.hasPlayer(current => current.hasSkill("jsrghuozhong"))) return false; return player.countCards("hes", card => get.color(card) == "black" && get.type2(card) != "trick") > 0; }, viewAs: { name: "bingliang" }, position: "hes", discard: false, prompt: function () { var list = game.filterPlayer(target => { return target.hasSkill("jsrghuozhong"); }); return `将一张黑色非锦囊牌当【兵粮寸断】置于自己的判定区,然后令${get.translation(list)}${list.length > 1 ? "中的一人" : ""}摸两张牌。`; }, filterCard: function (card, player, event) { return get.color(card) == "black" && get.type2(card) != "trick" && player.canAddJudge({ name: "bingliang", cards: [card] }); }, selectTarget: -1, filterTarget: function (card, player, target) { return player == target; }, check: function (card) { return 6 - get.value(card); }, precontent: function* (event, map) { var player = map.player; var targets = game.filterPlayer(current => current.hasSkill("jsrghuozhong")); var result; if (targets.length) result = { bool: true, targets: targets }; else result = yield player .chooseTarget("请选择一名传教士,发动其的【惑众】", true, (card, player, target) => { return get.event("targets").includes(target); }) .set("targets", targets); if (result.bool) { var target = result.targets[0]; player.logSkill("jsrghuozhong", target); var next = game.createEvent("jsrghuozhong_draw", false); next.set("player", player); next.set("target", target); event.next.remove(next); event.getParent().after.push(next); next.setContent(function () { target.draw(2); }); } }, ai: { result: { player: function (player) { if (game.hasPlayer(current => get.attitude(player, current) > 2 && current.hasSkill("jsrghuozhong"))) return 1; return 0; }, }, order: 9, }, }, }, }, jsrgrihui: { audio: "dcrihui", locked: false, trigger: { source: "damageSource" }, filter: function (event, player) { return ( event.getParent().type == "card" && event.card && event.card.name == "sha" && game.hasPlayer(current => { return current != player && current.countCards("j"); }) ); }, prompt: "是否发动【日彗】?", prompt2: function (event, player) { var list = game.filterPlayer(current => { return current != player && current.countCards("j"); }); return `令${get.translation(list)}${list.length > 1 ? "各" : ""}摸一张牌。`; }, logTarget: function (event, player) { return game.filterPlayer(current => { return current != player && current.countCards("j"); }); }, group: "jsrgrihui_sha", content: function () { game.asyncDraw(lib.skill.jsrgrihui.logTarget(trigger, player)); }, mod: { cardUsableTarget: function (card, player, target) { if (card.name == "sha" && !player.getStorage("jsrgrihui_targeted").includes(target)) return true; }, }, subSkill: { sha: { trigger: { player: "useCardToPlayered" }, forced: true, silent: true, firstDo: true, content: function () { player.addTempSkill("jsrgrihui_targeted"); player.markAuto("jsrgrihui_targeted", trigger.target); }, }, targeted: { charlotte: true, onremove: true, }, }, }, //夏侯恩 jsrghujian: { audio: "twfujian", trigger: { global: "phaseEnd", }, filter: function (event, player) { if (!Array.from(ui.discardPile.childNodes).some(i => i.name == "chixueqingfeng")) return false; return game.hasGlobalHistory("everything", evt => ["useCard", "respond"].includes(evt.name) && evt.player.isIn()); }, popup: false, forced: true, locked: false, group: "jsrghujian_begin", content: function () { "step 0"; var cards = Array.from(ui.discardPile.childNodes).filter(i => i.name == "chixueqingfeng"); if (cards.length) { event.cards = cards; var history = _status.globalHistory, target = null; for (var i = history.length - 1; i >= 0 && !target; i--) { var evts = history[i]["everything"]; for (var j = evts.length - 1; j >= 0; j--) { var evt = evts[j]; if (!["useCard", "respond"].includes(evt.name)) continue; target = evt.player; break; } } if (target && target.isIn()) { event.target = target; target.chooseBool(`是否响应${get.translation(player)}的【护剑】?`, "获得弃牌堆里的【赤血青锋】。"); } else event.finish(); } else event.finish(); ("step 1"); if (result.bool) { player.logSkill("jsrghujian"); player.line(target); target.gain(cards, "gain2"); } }, subSkill: { begin: { audio: "twfujian", trigger: { global: "phaseBefore", player: "enterGame", }, forced: true, locked: false, filter: function (event, player) { return event.name != "phase" || game.phaseNumber == 0; }, content: function () { player.gain(game.createCard2("chixueqingfeng", "spade", 6), "gain2"); }, }, }, }, jsrgshili: { audio: "twjianwei", enable: "phaseUse", usable: 1, viewAs: { name: "juedou", }, filterCard: { type: "equip" }, position: "hs", viewAsFilter: function (player) { return player.hasCard({ type: "equip" }, "hs"); }, check: function (card) { return (get.name(card, false) == "chixueqingfeng" ? 20 : 12) - _status.event.player.getUseValue(card); }, ai: { order: 0.001, }, }, //范疆张达 jsrgfushan: { audio: 2, trigger: { player: "phaseUseBegin" }, forced: true, locked: false, filter: function (event, player) { return game.hasPlayer(i => i != player); }, content: function* (event, map) { var player = map.player, trigger = map.trigger, targets = game.filterPlayer(i => i != player); var shas = player.mayHaveSha(target, "use", null, "count") - player.getCardUsable("sha", true); for (var target of targets) { var att = get.attitude(target, player); var result = yield target .chooseCard("he", `负山:是否交给${get.translation(player)}一张牌?`, `若如此做,其此阶段使用【杀】的次数上限+1`) .set("att", att) .set("ai", card => { if (!get.event("goon")) return -get.value(card); var isSha = get.name(card, get.event("target")) == "sha"; if (get.event("att") < 0) return (isSha ? 0 : 5) - get.value(card); return (isSha ? 10 : 0) - get.value(card); }) .set("goon", (att > 0 && shas >= 0) || (att < 0 && target.hp > player.getCardUsable("sha", true) && shas < -1 / Math.max(1, player.hp))) .set("target", player); if (result.bool) { target.give(result.cards, player); target.line(player); player.addTempSkill("jsrgfushan_sha", "phaseAfter"); player.addMark("jsrgfushan_sha", 1, false); player.markAuto("jsrgfushan_given", target); } } player .when("phaseUseAfter") .filter(evt => evt == trigger) .then(() => { player.logSkill("jsrgfushan"); if ( player.getCardUsable("sha", true) > player.getHistory("useCard", evt => { return evt.getParent("phaseUse") == trigger && evt.card.name == "sha" && evt.addCount !== false; }).length && player.storage.jsrgfushan_given && player.storage.jsrgfushan_given.every(i => i.isIn()) ) { player.loseHp(2); } else { player.drawTo(player.maxHp); } delete player.storage.jsrgfushan_given; }); }, subSkill: { sha: { charlotte: true, onremove: true, marktext: "负", intro: { content: "使用【杀】的次数上限+#" }, mod: { cardUsable: function (card, player, num) { if (card.name == "sha") return num + player.countMark("jsrgfushan_sha"); }, }, }, }, }, //江山如故·承 //404孙策 jsrgduxing: { audio: 2, enable: "phaseUse", viewAs: { name: "juedou", storage: { jsrgduxing: true }, isCard: true, }, viewAsFilter: function (player) { if (player.hasSkill("jsrgduxing_used")) return false; }, filterCard: () => false, selectCard: -1, selectTarget: [1, Infinity], precontent: function () { player.logSkill("jsrgduxing"); delete event.result.skill; var targets = event.result.targets; for (var target of targets) { target.addTempSkill("jsrgduxing_allsha"); } player.addTempSkill("jsrgduxing_restore"); player.addTempSkill("jsrgduxing_used", "phaseUseAfter"); }, ai: { order: 5, result: { player: function (player, target) { var eff = Math.sign(get.effect(target, { name: "juedou" }, player, player)); if ( player.hasSkillTag( "directHit_ai", true, { target: target, card: { name: "juedou" }, }, true ) || ui.selected.targets.concat(target).reduce((p, c) => { return p + c.countCards("h"); }, 0) < player.countCards("h", "sha") ) { return 0; } return -114514; }, target: -1.5, }, }, subSkill: { allsha: { charlotte: true, mod: { cardname: function (card, player, name) { return "sha"; }, }, }, used: { charlotte: true, }, restore: { charlotte: true, trigger: { global: "useCardAfter", }, forced: true, popup: false, forceDie: true, forceOut: true, filter: function (event, player) { return event.card.name == "juedou" && event.card.storage && event.card.storage.jsrgduxing; }, content: function () { game.countPlayer(current => { current.removeSkill("jsrgduxing_allsha"); }, true); }, }, }, }, jsrgzhiheng: { audio: 2, trigger: { source: "damageBegin1", }, forced: true, filter: function (event, player) { if (event.getParent().type != "card") return false; var respondEvts = []; respondEvts.addArray(event.player.getHistory("useCard")).addArray(event.player.getHistory("respond")); respondEvts = respondEvts.filter(i => i.respondTo).map(evt => evt.respondTo); return respondEvts.some(list => { return list[0] == player; }); }, content: function () { trigger.num++; }, }, jsrgzhasi: { audio: 2, trigger: { player: "damageBegin4", }, limited: true, skillAnimation: true, animationColor: "wood", filter: function (event, player) { return event.num >= player.getHp(); }, content: function () { player.awakenSkill("jsrgzhasi"); trigger.cancel(); player.changeSkills(["rezhiheng"], ["jsrgzhiheng"]); player.addSkill("jsrgzhasi_undist"); }, derivation: "rezhiheng", subSkill: { undist: { group: "undist", trigger: { player: ["useCardAfter", "damageEnd"], }, filter: function (event, player) { if (event.name == "useCard") return event.targets.some(target => { return target != player; }); return true; }, forced: true, popup: false, charlotte: true, content: function () { player.removeSkill("jsrgzhasi_undist"); }, mark: true, intro: { content: "诈死中,不计入距离和座次的计算", }, }, }, }, jsrgbashi: { audio: 2, trigger: { player: "chooseToRespondBefore" }, zhuSkill: true, filter: function (event, player) { if (event.responded) return false; if (player.storage.jsrgbashiing) return false; if (!player.hasZhuSkill("jsrgbashi")) return false; if (!event.filterCard({ name: "sha" }, player, event) && !event.filterCard({ name: "shan" }, player, event)) return false; return game.hasPlayer(function (current) { return current != player && current.group == "wu"; }); }, check: function (event, player) { if (get.damageEffect(player, event.player, player) >= 0) return false; return true; }, content: function () { "step 0"; event.targets = game.filterPlayer(); ("step 1"); var target = event.targets.shift(); event.target = target; if (!target) event.finish(); else if (!target.isIn() || target == player) event.redo(); else if (target.group == "wu") { if ((target == game.me && !_status.auto) || get.attitude(target, player) > 2 || target.isOnline()) { player.storage.jsrgbashiing = true; var list = ["sha", "shan"].filter(name => trigger.filterCard({ name: name }, player, trigger)); var names = list.map(i => "【" + get.translation(i) + "】").join("或"); var next = target.chooseToRespond("是否替" + get.translation(player) + "打出一张" + names + "?", { name: list }); next.set("ai", function () { var event = _status.event; return get.attitude(event.player, event.source) - 2; }); next.set("skillwarn", "替" + get.translation(player) + "打出一张" + names); next.autochoose = function () { if (!lib.filter.autoRespondSha.apply(this, arguments)) return false; return lib.filter.autoRespondShan.apply(this, arguments); }; next.set("source", player); } } ("step 2"); delete player.storage.jsrgbashiing; if (result.bool) { event.finish(); var name = result.card.name; trigger.result = { bool: true, card: { name: name, isCard: true } }; trigger.responded = true; trigger.animate = false; if (typeof target.ai.shown == "number" && target.ai.shown < 0.95) { target.ai.shown += 0.3; if (target.ai.shown > 0.95) target.ai.shown = 0.95; } } else { event.goto(1); } }, ai: { respondSha: true, respondShan: true, skillTagFilter: function (player, tag, arg) { if (arg == "use") return false; if (player.storage.jsrgbashiing) return false; if (!player.hasZhuSkill("jsrgbashi")) return false; return game.hasPlayer(function (current) { return current != player && current.group == "wu"; }); }, }, }, //许攸 jsrglipan: { forbid: ["guozhan"], audio: 2, trigger: { player: "phaseEnd", }, direct: true, content: function () { "step 0"; var list = lib.group.slice(); list.remove(player.group); var getV = function (group) { var val = 1; if (group == "wei" || group == "qun") val++; game.countPlayer(current => { if (current.group != group) return false; var att = get.attitude(player, current); if (att > 0) val++; else if (att == 0) val += 0.5; else val--; }); return val; }; var maxGroup = list.slice().sort((a, b) => { return getV(b) - getV(a); })[0]; list.push("cancel2"); player .chooseControl(list) .set("prompt", get.prompt("jsrglipan")) .set("prompt2", "变更为另一个势力") .set("ai", () => { return _status.event.choice; }) .set("choice", maxGroup); ("step 1"); var group = result.control; if (group == "cancel2") return; player.logSkill("jsrglipan"); player.popup(group + "2", get.groupnature(group, "raw")); player.changeGroup(group); var num = game.countPlayer(current => { return current.group == group && current != player; }); if (num > 0) player.draw(num); var next = player.phaseUse(); next.jsrglipan = true; event.next.remove(next); trigger.next.push(next); player.addTempSkill("jsrglipan_backfire"); }, subSkill: { backfire: { trigger: { player: "phaseUseEnd", }, charlotte: true, forced: true, popup: false, filter: function (event, player) { return event.jsrglipan; }, content: function () { "step 0"; var targets = game.filterPlayer(current => { return current.group == player.group; }); targets.sortBySeat(); event.targets = targets; ("step 1"); var target = targets.shift(); event.target = target; if (target && target.isIn() && target.canUse({ name: "juedou" }, player)) { target.chooseCardTarget({ position: "hes", prompt: "是否将一张牌当【决斗】对" + get.translation(player) + "使用?", filterCard: function (card, player) { return player.canUse(get.autoViewAs({ name: "juedou" }, [card]), _status.event.getParent().player); }, filterTarget: function (card, player, target) { var source = _status.event.getParent().player; if (target != source && !ui.selected.targets.includes(source)) return false; card = get.autoViewAs({ name: "juedou" }, [card]); return lib.filter.filterTarget.apply(this, arguments); }, selectTarget: function () { var card = get.card(), player = get.player(); if (!card) return; card = get.autoViewAs({ name: "juedou" }, [card]); var range = [1, 1]; game.checkMod(card, player, range, "selectTarget", player); return range; }, ai1: function (card) { var player = _status.event.player, target = _status.event.getParent().player; var eff = get.effect(target, get.autoViewAs({ name: "juedou" }, [card]), player, player); if (eff <= 0) return 0; return (player.hp == 1 ? 10 : 6) - get.value(card); }, ai2: function (target) { if (target == _status.event.getParent().player) return 100; return get.effect(target, { name: "juedou" }, _status.event.player); }, }); } ("step 2"); if (result.bool) { var cards = result.cards; var cardx = get.autoViewAs({ name: "juedou" }, cards); var targets = result.targets.filter(targetx => { return target.canUse(cardx, targetx); }); if (targets.length) target.useCard(cardx, cards, targets); } if (targets.length) event.goto(1); }, }, }, }, jsrgqingxi: { audio: 2, enable: "phaseUse", filter: function (event, player) { if (player.group != "qun") return false; return game.hasPlayer(current => lib.skill.jsrgqingxi.filterTarget("", player, current)); }, groupSkill: true, filterTarget: function (card, player, target) { if (target.countCards("h") >= player.countCards("h")) return false; return !player.getStorage("jsrgqingxi_used").includes(target); }, content: function () { "step 0"; player.addTempSkill("jsrgqingxi_used", "phaseUseAfter"); player.markAuto("jsrgqingxi_used", [target]); var num = player.countCards("h") - target.countCards("h"); if (num > 0) player.chooseToDiscard(num, true, "轻袭:弃置" + get.cnNumber(num) + "张手牌"); ("step 1"); var card = { name: "sha", nature: "stab", isCard: true, }; if (player.canUse(card, target, false)) player.useCard(card, target, false); }, ai: { order: 8, result: { target: (player, target) => { let num = player.countCards("h") - target.countCards("h"), eff = get.effect(target, { name: "sha", nature: "stab" }, player, target), val = 0, ph = _status.event.getTempCache("jsrgqingxi_result", "ph"); if (!ph) { ph = player.getCards("h").sort((a, b) => { return get.value(a) - get.value(b); }); _status.event.putTempCache("jsrgqingxi_result", "ph", ph); } ph.slice(0, num).forEach(i => { val += get.value(i, player); }); eff = Math.sign(eff) * Math.sqrt(Math.abs(eff)); if (val > 2 * Math.abs(eff)) return 0; return eff / num; }, }, }, subSkill: { used: { onremove: true, charlotte: true, }, }, }, jsrgjinmie: { audio: 2, enable: "phaseUse", usable: 1, filter: function (event, player) { if (player.group != "wei") return false; return game.hasPlayer(current => current.countCards("h") > player.countCards("h")); }, groupSkill: true, filterTarget: function (card, player, target) { return target.countCards("h") > player.countCards("h"); }, content: function () { "step 0"; var card = { name: "sha", nature: "fire", storage: { jsrgjinmie: target }, isCard: true, }; if (player.canUse(card, target, false)) { player.useCard(card, target, false); player.addTempSkill("jsrgjinmie_effect"); } }, ai: { order: 0.5, result: { target: function (player, target) { var eff = get.effect(target, { name: "sha", nature: "fire" }, player, target) / 30; if ( !target.mayHaveShan( player, "use", target.getCards("h", i => { return i.hasGaintag("sha_notshan"); }) ) ) eff *= 2; var del = target.countCards("h") - player.countCards("h") + 1.5; eff *= Math.sqrt(del); return eff; }, }, }, subSkill: { effect: { trigger: { source: "damageSource", }, filter: function (event, player) { return event.card && event.card.storage && event.card.storage.jsrgjinmie && event.card.storage.jsrgjinmie.isIn(); }, forced: true, popup: false, charlotte: true, content: function () { "step 0"; var target = trigger.card.storage.jsrgjinmie; var del = target.countCards("h") - player.countCards("h"); if (del > 0) { player.line(target); player.discardPlayerCard(target, "h", true, del); } // else if(del<0){ // player.line(target); // target.draw(-del); // } }, }, }, }, //吕布 jsrgwuchang: { forbid: ["guozhan"], audio: 2, trigger: { player: "gainAfter", global: "loseAsyncAfter", }, forced: true, filter: function (event, player) { var cards = event.getg(player); if (!cards.length) return false; return game.hasPlayer(current => { if (current == player) return false; return event.getl(current).cards2.length; }); }, group: "jsrgwuchang_add", content: function () { "step 0"; var targets = game.filterPlayer(current => { if (current == player) return false; return trigger.getl(current).cards2.length; }); var target = targets[0]; player.changeGroup(target.group); player.popup(target.group + "2", get.groupnature(target.group, "raw")); }, subSkill: { add: { trigger: { source: "damageBegin1", }, filter: function (event, player) { if (!event.card || !["sha", "juedou"].includes(event.card.name) || event.getParent().type != "card") return false; return event.player.group == player.group; }, forced: true, content: function () { "step 0"; trigger.num++; var group = "qun"; player.changeGroup(group); player.popup(group + "2", get.groupnature(group, "raw")); }, }, }, }, jsrgqingjiao: { audio: 2, enable: "phaseUse", filter: function (event, player) { if (player.group != "qun") return false; if (!player.countCards("hes")) return false; return ( (!player.hasSkill("jsrgqingjiao_tuixinzhifu") && game.hasPlayer(current => { return current.countCards("h") > player.countCards("h"); })) || (!player.hasSkill("jsrgqingjiao_chenghuodajie") && game.hasPlayer(current => { return current.countCards("h") < player.countCards("h"); })) ); }, groupSkill: true, position: "hes", filterCard: true, selectCard: 1, discard: false, lose: false, delay: false, filterTarget: function (card, player, target) { var mod = game.checkMod(ui.selected.cards[0], player, "unchanged", "cardEnabled2", player); if (!mod) return false; var del = target.countCards("h") - player.countCards("h"); if (del == 0) return false; var name = del > 0 ? "tuixinzhifu" : "chenghuodajie"; if (player.hasSkill("jsrgqingjiao_" + name)) return false; return player.canUse({ name: name, cards: ui.selected.cards }, target); }, content: function () { var del = target.countCards("h") - player.countCards("h"); var name = del > 0 ? "tuixinzhifu" : "chenghuodajie"; player.useCard({ name: name }, target, cards); player.addTempSkill("jsrgqingjiao_" + name, "phaseUseAfter"); }, ai: { order: 7, result: { player: function (player, target) { var name = target.countCards("h") > player.countCards("h") ? "tuixinzhifu" : "chenghuodajie"; var list = []; if (ui.selected.cards.length) list.addArray(ui.selected.cards); var card = get.autoViewAs({ name: name }, list); return get.effect(target, card, player, player); }, }, }, subSkill: { tuixinzhifu: { charlotte: true, }, chenghuodajie: { charlotte: true, }, }, }, jsrgchengxu: { audio: 2, trigger: { player: "useCard" }, forced: true, locked: false, filter: function (event, player) { if (player.group != "shu") return false; return game.hasPlayer(current => { return current != player && current.group == player.group; }); }, groupSkill: true, content: function () { trigger.directHit.addArray( game.filterPlayer(current => { return current != player && current.group == player.group; }) ); }, ai: { directHit_ai: true, skillTagFilter: function (player, tag, arg) { return player.group == "shu" && player.group == arg.target.group; }, }, }, //张郃 jsrgqiongtu: { audio: 2, enable: "chooseToUse", groupSkill: true, viewAs: { name: "wuxie", suit: "none", number: null, isCard: true, }, filter: function (event, player) { if (!player.countCards("he", card => _status.connectMode || get.type(card) != "basic")) return false; return player.group == "qun" && !player.hasSkill("jsrgqiongtu_check"); }, viewAsFilter: function (player) { if (!player.countCards("he", card => _status.connectMode || get.type(card) != "basic")) return false; return player.group == "qun" && !player.hasSkill("jsrgqiongtu_check"); }, filterCard: function (card) { return get.type(card) != "basic"; }, position: "he", popname: true, ignoreMod: true, precontent: function () { "step 0"; player.logSkill("jsrgqiongtu"); delete event.result.skill; var card = event.result.cards[0]; event.card = card; event.result.card = { name: event.result.card.name, storage: { jsrgqiongtu: true }, isCard: true, }; event.result.cards = []; player.addToExpansion(card, player, "give").gaintag.add("jsrgqiongtu"); player.addTempSkill("jsrgqiongtu_check"); }, marktext: "途", intro: { content: "expansion", markcount: "expansion", }, onremove: function (player, skill) { var cards = player.getExpansions(skill); if (cards.length) player.loseToDiscardpile(cards); delete player.storage[skill]; }, subSkill: { check: { trigger: { global: "useCardAfter", }, filter: function (event, player) { return event.card.name == "wuxie" && event.card.storage && event.card.storage.jsrgqiongtu; }, forced: true, popup: false, charlotte: true, content: function () { "step 0"; game.delayx(); var evt = trigger.getParent(4); if (evt.name == "phaseJudge") { state = evt.cancelled; } else { state = evt._neutralized; } if (state) { player.draw(); } else { player.changeGroup("wei"); var cards = player.getExpansions("jsrgqiongtu"); if (cards.length) player.gain(cards, "gain2"); } }, }, }, }, jsrgxianzhu: { audio: 2, enable: "chooseToUse", filter: function (event, player) { return ( player.group == "wei" && player.hasCard(card => { return _status.connectMode || get.type(card) == "trick"; }, "hs") ); }, groupSkill: true, locked: false, viewAs: { name: "sha", storage: { jsrgxianzhu: true }, }, position: "hs", filterCard: function (card) { return get.type(card) == "trick"; }, check: function (card) { var player = _status.event.player; var cardx = { name: "sha", storage: { jsrgxianzhu: true }, cards: [card], }; if ( game.hasPlayer(current => { return player.canUse(cardx, current) && get.effect(current, card, player, player) > 0 && get.effect(current, cardx, player, player) > 0; }) ) return 15 - get.value(card); return 0; }, onuse: function (links, player) { player.addTempSkill("jsrgxianzhu_after"); }, mod: { cardUsable: function (card) { if (card.storage && card.storage.jsrgxianzhu) return Infinity; }, }, subSkill: { after: { trigger: { global: "damageSource", }, filter: function (event, player) { var targets = event.getParent(2).targets; if (!targets || targets.length != 1) return false; if (!event.card || !event.card.storage || !event.card.storage.jsrgxianzhu) return false; var target = event.player, card = event.cards[0]; if (!target.isIn()) return false; if (get.type(card) != "trick") return false; if (!player.canUse(card, target, false)) return false; return true; }, forced: true, charlotte: true, group: "jsrgxianzhu_inf", content: function () { var card = { name: trigger.cards[0].name, isCard: true, }; player.useCard(card, trigger.player, false); game.delayx(); }, }, inf: { trigger: { player: "useCard1" }, forced: true, popup: false, firstDo: true, filter: function (event, player) { if (event.card.storage && event.card.storage.jsrgxianzhu && event.addCount !== false) return true; return false; }, content: function () { trigger.addCount = false; var stat = player.getStat().card, name = trigger.card.name; if (typeof stat[name] == "number") stat[name]--; }, }, }, }, //邹氏 jsrgguyin: { audio: 2, trigger: { player: "phaseZhunbeiBegin", }, check: function (event, player) { return player.isTurnedOver() || game.countPlayer2(current => current.hasSex("male")) >= 2; }, content: function () { "step 0"; player.turnOver(); ("step 1"); var targets = game.filterPlayer(current => current != player && current.hasSex("male")); event.targets = targets; player.line(targets); game.delayx(); ("step 2"); var target = targets.shift(); event.target = target; target .chooseBool("是否响应" + get.translation(player) + "的【孤吟】?", "你可以翻面。") .set("ai", () => { return _status.event.bool; }) .set( "bool", (function () { return target.isTurnedOver() || (get.attitude(target, player) > 0 && (game.countPlayer2(current => current.hasSex("male")) >= 3 || (target.getHp() <= 1 && player.hasSkill("jsrgzhangdeng")))); })() ); ("step 3"); if (result.bool) { target.turnOver(); } if (targets.length) event.goto(2); ("step 4"); var targets = game.filterPlayer(current => { return current == player || current.isTurnedOver(); }); event.targets = targets; event.num = 0; event.index = 0; ("step 5"); var target = targets[event.index]; if (target.isIn()) { target.draw(); event.num++; } event.index++; if (event.index >= targets.length) event.index = 0; ("step 6"); if (event.num >= game.countPlayer2(current => current.hasSex("male"))) event.finish(); else event.goto(5); }, }, jsrgzhangdeng: { audio: 2, trigger: { global: "logSkill", }, filter: function (event, player) { return ( event.player .getHistory("useSkill", evt => { return evt.skill == "jsrgzhangdeng_jiu"; }) .map(evt => evt.event) .indexOf(event.log_event) == 1 ); }, global: "jsrgzhangdeng_jiu", forced: true, locked: false, content: function () { player.turnOver(false); }, subSkill: { jiu: { audio: "jsrgzhangdeng", enable: "chooseToUse", filter: function (event, player) { return ( player.isTurnedOver() && game.hasPlayer(current => { return current.hasSkill("jsrgzhangdeng") && current.isTurnedOver(); }) ); }, viewAs: { name: "jiu", isCard: true }, viewAsFilter: function (player) { return ( player.isTurnedOver() && game.hasPlayer(current => { return current.hasSkill("jsrgzhangdeng") && current.isTurnedOver(); }) ); }, filterCard: () => false, selectCard: -1, precontent: function () { player.logSkill("jsrgzhangdeng_jiu"); var targets = game.filterPlayer(current => { return current.hasSkill("jsrgzhangdeng") && current.isTurnedOver(); }); player.line(targets[0]); delete event.result.skill; }, }, }, }, //关羽 jsrgguanjue: { audio: 2, trigger: { player: ["useCard", "respond"], }, filter: function (event, player) { return lib.suit.includes(get.suit(event.card)); }, forced: true, content: function () { "step 0"; var targets = game.filterPlayer(current => current != player); var suit = get.suit(trigger.card); for (var target of targets) { target.addTempSkill("jsrgguanjue_ban"); target.markAuto("jsrgguanjue_ban", [suit]); } }, subSkill: { ban: { onremove: true, charlotte: true, mod: { cardEnabled: function (card, player) { if (player.getStorage("jsrgguanjue_ban").includes(get.suit(card))) return false; }, cardRespondable: function (card, player) { if (player.getStorage("jsrgguanjue_ban").includes(get.suit(card))) return false; }, cardSavable: function (card, player) { if (player.getStorage("jsrgguanjue_ban").includes(get.suit(card))) return false; }, }, mark: true, marktext: "绝", intro: { content: "本回合内不能使用或打出$的牌", }, }, }, }, jsrgnianen: { audio: 2, enable: ["chooseToUse", "chooseToRespond"], filter: function (event, player) { if (!player.countCards("hes")) return false; if (player.hasSkill("jsrgnianen_blocker")) return false; for (var name of lib.inpile) { if (get.type2(name) != "basic") continue; var card = { name: name }; if (event.filterCard(get.autoViewAs(card, "unsure"), player, event)) return true; if (name == "sha") { for (var nature of lib.inpile_nature) { card.nature = nature; if (event.filterCard(get.autoViewAs(card, "unsure"), player, event)) return true; } } } return false; }, derivation: "mashu", chooseButton: { dialog: function (event, player) { var list = []; for (var name of lib.inpile) { if (name == "sha") { if (event.filterCard(get.autoViewAs({ name }, "unsure"), player, event)) list.push(["基本", "", "sha"]); for (var nature of lib.inpile_nature) { if (event.filterCard(get.autoViewAs({ name, nature }, "unsure"), player, event)) list.push(["基本", "", "sha", nature]); } } else if (get.type(name) == "basic" && event.filterCard(get.autoViewAs({ name }, "unsure"), player, event)) list.push(["基本", "", name]); } var dialog = ui.create.dialog("念恩", [list, "vcard"]); dialog.direct = true; return dialog; }, filter: function (button, player) { return _status.event.getParent().filterCard(get.autoViewAs({ name: button.link[2], nature: button.link[3] }, "unsure"), player, _status.event.getParent()); }, check: function (button) { if (_status.event.getParent().type != "phase") return 1; var player = _status.event.player; if (["wugu", "zhulu_card", "yiyi", "lulitongxin", "lianjunshengyan", "diaohulishan"].includes(button.link[2])) return 0; return player.getUseValue({ name: button.link[2], nature: button.link[3], }); }, backup: function (links, player) { return { audio: "jsrgnianen", filterCard: true, popname: true, check: function (card) { return 8 - get.value(card); }, position: "hes", viewAs: { name: links[0][2], nature: links[0][3] }, precontent: function () { player.logSkill("jsrgnianen"); delete event.result.skill; var card = event.result.card; if (get.color(card, player) != "red" || get.name(card) != "sha" || get.natureList(card).length) { player.addTempSkill("jsrgnianen_blocker"); player.addAdditionalSkill("jsrgnianen_blocker", "mashu"); } }, }; }, prompt: function (links, player) { return "将一张牌当做" + (get.translation(links[0][3]) || "") + get.translation(links[0][2]) + "使用"; }, }, hiddenCard: function (player, name) { if (!lib.inpile.includes(name)) return false; var type = get.type2(name); return type == "basic" && player.countCards("hes") > 0 && !player.hasSkill("jsrgnianen_blocker"); }, ai: { fireAttack: true, respondSha: true, respondShan: true, skillTagFilter: function (player) { if (!player.countCards("hes") || player.hasSkill("jsrgnianen_blocker")) return false; }, order: 1, result: { player: function (player) { if (_status.event.dying) return get.attitude(player, _status.event.dying); return 1; }, }, }, subSkill: { blocker: { charlotte: true, mark: true, marktext: "恩", intro: { content: "视为拥有〖马术〗" }, }, }, }, //生鱼片 jsrglunshi: { audio: 2, enable: "phaseUse", usable: 1, filterTarget: function (card, player, target) { return game.hasPlayer(current => { return current.inRangeOf(target); }); }, content: function () { "step 0"; var num = game.countPlayer(current => { return current.inRangeOf(target); }); var len = target.countCards("h"); num = Math.max(0, Math.min(len + num, 5) - len); if (num > 0) target.draw(num); ("step 1"); var num = game.countPlayer(current => { return current.inRange(target); }); if (num > 0) target.chooseToDiscard(num, "he", true, get.translation(player) + "对你发动了【论势】", "请弃置" + get.cnNumber(num) + "张牌"); }, ai: { order: 6, result: { target: function (player, target) { var num1 = game.countPlayer(current => { return current.inRangeOf(target); }), num2 = game.countPlayer(current => { return current.inRange(target); }); var len = target.countCards("h"); num1 = Math.max(0, Math.min(len + num1, 5) - len); return (num1 - num2 + 1) / 2; }, }, }, }, jsrgguitu: { audio: 2, trigger: { player: "phaseZhunbeiBegin", }, direct: true, filter: function (event, player) { return ( game.countPlayer(current => { return current.getEquips(1).length; }) >= 2 ); }, content: function () { "step 0"; player .chooseTarget( get.prompt2("jsrgguitu"), (card, player, target) => { return target.getEquips(1).length; }, [1, 2] ) .set("filterOk", () => { var num = 0; for (var target of ui.selected.targets) { num += target.getEquips(1).length; } return num >= 2; }) .set("ai", target => { var sign = -1; var val = 0; if (ui.selected.targets.length) { sign = 1; var targetx = ui.selected.targets[0]; var cards = targetx.getEquips(1); var list = cards.map(card => { return [card, get.value(card, targetx)]; }); list.sort((a, b) => { return b[1] - a[1]; }); val = get.attitude(_status.event.player, targetx) * list[0][1]; } var cards = target.getEquips(1); var list = cards.map(card => { return [card, get.value(card, target)]; }); list.sort((a, b) => { return b[1] - a[1]; }); return get.attitude(_status.event.player, target) * list[0][1] * sign - val; }); ("step 1"); if (result.bool) { var targets = result.targets.slice(); targets.sortBySeat(); event.targets = targets; player.logSkill("jsrgguitu", targets); event.rangeList = targets.map(target => { return target.getAttackRange(); }); var weapons = []; for (var target of targets) { weapons.addArray(target.getEquips(1)); } if (weapons.length > 2) { var list = ["诡图:选择要交换的武器牌"]; for (var target of targets) { list.addArray(['
    ' + get.translation(target) + "的武器牌
    ", target.getEquips(1)]); } player .chooseButton(list, true, 2) .set("filterButton", button => { var count = _status.event.count; if (count == 1) return true; for (var i = 0; i < ui.selected.buttons.length; i++) { if (get.owner(button.link) == get.owner(ui.selected.buttons[i].link)) return false; } return true; }) .set("count", targets.length) .set("ai", button => { var player = _status.event.player; var card = button.link; var owner = get.owner(card); var att = get.attitude(player, owner); var val = -get.value(card) * att; return val; }); } else event._result = { bool: true, links: weapons }; } else event.finish(); ("step 2"); if (result.bool) { var links = result.links; var list = []; for (var target of targets) { var weapons = target.getEquips(1); weapons = weapons.filter(i => links.includes(i)); if (weapons.length) { list.push([target, weapons]); } } if (list.length == 2) { event.players = list.map(i => i[0]); event.cards = list.map(i => i[1]); } else { event.players = [list[0][0], list[0][0]]; event.cards = list[0][1]; } game.loseAsync({ player: event.players[0], target: event.players[1], cards1: event.cards[0], cards2: event.cards[1], }).setContent("swapHandcardsx"); } else event.finish(); ("step 3"); for (var i = 0; i < event.cards[1].length; i++) { if (get.position(event.cards[1][i], true) == "o") event.players[0].equip(event.cards[1][i]); } for (var i = 0; i < event.cards[0].length; i++) { if (get.position(event.cards[0][i], true) == "o") event.players[1].equip(event.cards[0][i]); } ("step 4"); var rangeList = targets.map(target => { return target.getAttackRange(); }); for (var i = 0; i < targets.length; i++) { if (rangeList[i] < event.rangeList[i]) { targets[i].recover(); } } }, }, //甄宓 jsrgjixiang: { audio: 2, trigger: { global: ["chooseToUseBegin", "chooseToRespondBegin"], }, filter: function (event, player) { if (player != _status.currentPhase) return false; if (player == event.player) return false; if (!player.countCards("he")) return false; for (var name of lib.inpile) { if (get.type(name) != "basic") continue; if (player.getStorage("jsrgjixiang_used").includes(name)) continue; var card = { name: name, isCard: true }; if (event.filterCard(card, event.player, event)) return true; if (name == "sha") { for (var nature of lib.inpile_nature) { card.nature = nature; if (event.filterCard(card, event.player, event)) return true; } } } return false; }, direct: true, global: "jsrgjixiang_save", content: function () { "step 0"; var list = []; for (var name of lib.inpile) { if (get.type(name) != "basic") continue; var card = { name: name }; if (trigger.filterCard(card, trigger.player, trigger)) list.push(name); } var listx = []; for (var name of list) { if (player.getStorage("jsrgjixiang_used").includes(name)) continue; listx.push([get.type2(name), "", name]); if (name == "sha") { for (var nature of lib.inpile_nature) { if (trigger.filterCard({ name: name, nature: nature }, player, trigger)) { listx.push([get.type2(name), "", name, nature]); } } } } var evt = trigger.getParent(); var names = ""; for (var i = 0; i < list.length; i++) { names += "【" + get.translation(list[i]) + "】"; names += i < list.length - 2 ? "、" : "或"; } names = names.slice(0, names.length - 1); var reason = trigger.name == "chooseToUse" ? "使用" : "打出"; var used = player.getStorage("jsrgjixiang_used").filter(name => list.includes(name)); var str = get.translation(trigger.player) + (evt.card ? "因" + get.translation(evt.card) : "") + "需要" + reason + "一张" + names + ",是否弃置一张牌视为其" + reason + "之" + (used.length ? "(你不能以此法令其" + reason + get.translation(used) + ")" : "") + "?若如此做,你摸一张牌并令〖称贤〗此阶段可发动次数上限+1。"; event.str = str; if (!listx.length) event.finish(); else if (listx.length == 1) event._result = { bool: true, links: listx }; else { event.asked = true; player.chooseButton(["###" + get.prompt("jsrgjixiang", trigger.player) + '###
    ' + str + "
    ", [listx, "vcard"]]).set("ai", () => Math.random() + 1); } event.list = list; ("step 1"); if (result.bool) { var name = result.links[0][2], nature = result.links[0][3]; var card = { name: name, nature: nature, isCard: true }; event.card = card; var evt = trigger.getParent(); var reason = trigger.name == "chooseToUse" ? "使用" : "打出"; var prompt = event.asked ? "济乡:是否弃置一张牌" + (trigger.filterTarget ? "并选择目标角色" : "") + "?" : get.prompt("jsrgjixiang", trigger.player); var str = event.asked ? "若如此做,视为" + get.translation(trigger.player) + reason + get.translation(card) + ",然后你摸一张牌并令〖称贤〗此阶段可发动次数上限+1。" : event.str; var next = player.chooseCardTarget({ prompt: prompt, prompt2: str, filterCard: lib.filter.cardDiscardable, position: "he", goon: get.attitude(player, trigger.player) > 1 && (evt.card ? get.effect(trigger.player, evt.card, evt.player, player) < 0 : get.effect(trigger.player, { name: event.list[0] }, trigger.player, player) > 0), ai1: function (card) { if (_status.event.goon) return 6 - get.value(card); return 0; }, _get_card: card, }); var keys = ["filterTarget", "selectTarget", "ai2"]; for (var key of keys) delete next[key]; for (var i in trigger) { if (!(i in next)) next[i] = trigger[i]; } next.filterTargetx = trigger.filterTarget || (() => false); next.filterTarget = function (card, player, target) { var filter = this.filterTargetx; if (typeof filter != "function") filter = () => filter; card = _status.event._get_card; player = _status.event.getTrigger().player; return this.filterTargetx.apply(this, arguments); }; if (typeof next.selectTarget != "number" && typeof next.selectTarget != "function" && get.itemtype(next.selectTarget) != "select") next.selectTarget = -1; } else event.finish(); ("step 2"); if (result.bool) { var cardx = result.cards[0]; var targets = result.targets || []; event.targets = targets; player.logSkill("jsrgjixiang", trigger.player); player.addTempSkill("jsrgjixiang_used"); player.markAuto("jsrgjixiang_used", [card.name]); player.discard(cardx); trigger.untrigger(); trigger.set("responded", true); var result = { bool: true, card: card, }; if (targets.length) result.targets = targets; trigger.result = result; player.draw(); var phaseName; for (var name of lib.phaseName) { var evt = trigger.getParent(name); if (!evt || evt.name != name) continue; phaseName = name; break; } if (phaseName) { player.addTempSkill("jsrgjixiang_add", phaseName + "After"); player.addMark("jsrgjixiang_add", 1, false); } } }, subSkill: { used: { charlotte: true, onremove: true, mark: true, marktext: "乡", intro: { content: "已触发过牌名:$", }, }, add: { charlotte: true, onremove: true, mark: true, intro: { markcount: (storage, player) => 2 + (storage || 0), content: (storage, player) => "〖称贤〗剩余可发动次数为" + (2 + (storage || 0)), }, }, save: { charlotte: true, ai: { save: true, skillTagFilter: function (player, arg, target) { return _status.currentPhase && _status.currentPhase != player && _status.currentPhase.hasSkill("jsrgjixiang") && _status.currentPhase.countCards("he"); }, }, }, }, }, jsrgchengxian: { audio: 2, enable: "phaseUse", filter: function (event, player) { if (!player.countCards("hs")) return false; if (2 + player.countMark("jsrgjixiang_add") <= 0) return false; for (var name of lib.inpile) { if (get.type(name) != "trick") continue; if (player.getStorage("jsrgchengxian_used").includes(name)) continue; if (event.filterCard({ name: name }, player, event)) return true; } return false; }, chooseButton: { dialog: function (event, player) { var list = []; for (var name of lib.inpile) { if (player.getStorage("jsrgchengxian_used").includes(name)) continue; var info = get.info({ name: name }); if (!info || info.type != "trick") continue; if (info.notarget) continue; if (!info.selectTarget) continue; if (get.type(name) == "trick" && event.filterCard({ name: name }, player, event)) list.push(["锦囊", "", name]); } var dialog = ui.create.dialog("称贤", [list, "vcard"]); return dialog; }, filter: function (button, player) { return _status.event.getParent().filterCard({ name: button.link[2], nature: button.link[3] }, player, _status.event.getParent()); }, check: function (button) { if (_status.event.getParent().type != "phase") return 1; var player = _status.event.player; if (["wugu", "zhulu_card", "yiyi", "lulitongxin", "lianjunshengyan", "diaohulishan"].includes(button.link[2])) return 0; return player.getUseValue({ name: button.link[2], nature: button.link[3], }); }, backup: function (links, player) { return { audio: "jsrgchengxian", filterCard: function (card, player) { var num = game.countPlayer(current => { return player.canUse(card, current); }); if (!num) return false; var cardx = get.copy(lib.skill.jsrgchengxian_backup.viewAs); cardx.cards = [card]; var num2 = game.countPlayer(current => { return player.canUse(cardx, current); }); return num == num2; }, popname: true, check: function (card) { return 8 - get.value(card); }, position: "hs", viewAs: { name: links[0][2] }, precontent: function () { player.logSkill("jsrgchengxian"); player.addTempSkill("jsrgjixiang_add"); if (typeof player.storage.jsrgjixiang_add != "number") player.storage.jsrgjixiang_add = 0; player.storage.jsrgjixiang_add--; player.addTempSkill("jsrgchengxian_used"); player.markAuto("jsrgchengxian_used", [event.result.card.name]); delete event.result.skill; }, }; }, prompt: function (links, player) { return "将一张合法目标数与" + (get.translation(links[0][3]) || "") + get.translation(links[0][2]) + "相同的手牌当此牌使用"; }, }, //理解错了,下面这个不用了 getNumber: function (card, player) { var rangex = null; var info = get.info(card); if (!info) return null; if (info.notarget) return null; if (info.selectTarget != undefined) { var select = get.select(info.selectTarget); if (select[0] < 0) { if (!info.toself) { var count = game.countPlayer(current => { return lib.filter.targetEnabled(card, player, current); }); } else count = 1; rangex = [count, count]; } else rangex = select; } return rangex; }, ai: { order: 1, result: { player: function (player) { if (_status.event.dying) return get.attitude(player, _status.event.dying); return 1; }, }, }, subSkill: { used: { charlotte: true, onremove: true, mark: true, intro: { content: "已使用过$", }, }, }, }, //张辽 jsrgzhengbing: { audio: 2, enable: "phaseUse", usable: 3, filter: function (event, player) { return player.group == "qun"; }, filterCard: lib.filter.cardRecastable, check: function (card) { var player = _status.event.player, val = 5 + ["shan", "tao"].includes(get.name(card)) * 1.5; if (player.needsToDiscard() > 2 && get.name(card) == "sha" && player.countCards("hs", "sha") > 1) val += 0.5; return val - get.value(card); }, position: "he", groupSkill: true, lose: false, discard: false, delay: false, content: function () { "step 0"; player.recast(cards); switch (get.name(cards[0])) { case "sha": player.addTempSkill("jsrgzhengbing_sha"); player.addMark("jsrgzhengbing_sha", 2, false); break; case "shan": player.draw(); break; case "tao": player.changeGroup("wei"); } }, ai: { order: 7, result: { player: 1 }, }, subSkill: { sha: { charlotte: true, onremove: true, mod: { maxHandcard: function (player, num) { return num + player.countMark("jsrgzhengbing_sha"); }, }, intro: { content: "手牌上限+#", }, }, }, }, jsrgtuwei: { audio: 2, trigger: { player: "phaseUseBegin", }, filter: function (event, player) { return ( player.group == "wei" && game.hasPlayer(current => { return player.inRange(current) && current.countGainableCards(player, "he") > 0; }) ); }, groupSkill: true, direct: true, content: function () { "step 0"; player .chooseTarget( get.prompt("jsrgtuwei"), "获得攻击范围内任意名角色的各一张牌。然后回合结束时这些角色中未受过伤害的角色依次获得你的一张牌。", (card, player, target) => { return player.inRange(target) && target.countGainableCards(player, "he") > 0; }, [1, Infinity] ) .set("ai", target => { var player = _status.event.player; return get.effect(target, { name: "shunshou_copy2" }, player, player); }); ("step 1"); if (result.bool) { var targets = result.targets.slice(); targets.sortBySeat(); player.logSkill("jsrgtuwei", targets); player.gainMultiple(result.targets, "he"); player.addTempSkill("jsrgtuwei_backfire"); player.markAuto("jsrgtuwei_backfire", targets); } }, subSkill: { backfire: { audio: "jsrgtuwei", trigger: { player: "phaseEnd", }, charlotte: true, onremove: true, forced: true, filter: function (event, player) { return player.getStorage("jsrgtuwei_backfire").some(target => { return !target.getHistory("damage").length && target.isIn(); }); }, content: function () { "step 0"; var targets = player.getStorage("jsrgtuwei_backfire").filter(target => { return !target.getHistory("damage").length && target.isIn(); }); event.targets = targets.sortBySeat(); ("step 1"); var target = targets.shift(); if (target.isIn() && player.countGainableCards(target, "he")) { target.line(player); target.gainPlayerCard(player, true, "he"); } if (player.countCards("he") && targets.length) event.redo(); }, ai: { effect: { player: function (card, player, target) { if (player != target && get.tag(card, "damage") && target && player.getStorage("jsrgtuwei_backfire").includes(target) && !target.getHistory("damage").length) return [1, 1, 1, 0]; }, }, }, }, }, }, //许贡 jsrgbiaozhao: { audio: 2, trigger: { player: "phaseZhunbeiBegin" }, filter: function (event, player) { return game.countPlayer(current => current != player) >= 2; }, direct: true, content: function () { "step 0"; player .chooseTarget(get.prompt2("jsrgbiaozhao"), lib.filter.notMe, 2) .set("ai", target => { var player = _status.event.player; var att = get.attitude(player, target); if (!ui.selected.targets.length) return att * (Math.sqrt(target.countCards("hs")) + 0.1); return -att / Math.sqrt(target.countCards("hs") + 0.1); }) .set("targetprompt", ["用牌无限制", "打你变疼"]); ("step 1"); if (result.bool) { var targets = result.targets; player.logSkill("jsrgbiaozhao", targets); player.addTempSkill("jsrgbiaozhao_syujin", { player: ["phaseBegin", "die"] }); if (!player.storage.jsrgbiaozhao_syujin) player.storage.jsrgbiaozhao_syujin = []; player.storage.jsrgbiaozhao_syujin.push(targets); targets[0].addSkill("jsrgbiaozhao_A"); targets[0].markAuto("jsrgbiaozhao_A", [targets[1]]); targets[1].addSkill("jsrgbiaozhao_B"); targets[1].addMark("jsrgbiaozhao_B" + player.playerid, 1, false); targets[1].markAuto("jsrgbiaozhao_B", [player]); } }, subSkill: { syujin: { charlotte: true, onremove: function (player, skill) { var list = player.storage.jsrgbiaozhao_syujin; for (var targets of list) { targets[0].unmarkAuto("jsrgbiaozhao_A", [targets[1]]); targets[1].unmarkAuto("jsrgbiaozhao_B", [player]); delete targets[1].storage["jsrgbiaozhao_B" + player.playerid]; if (!targets[0].getStorage("jsrgbiaozhao_A")) targets[0].removeSkill("jsrgbiaozhao_A"); if (!targets[1].getStorage("jsrgbiaozhao_B")) targets[1].removeSkill("jsrgbiaozhao_B"); } delete player.storage.jsrgbiaozhao_syujin; }, }, A: { charlotte: true, onremove: true, mark: true, marktext: "表", intro: { content: "对$使用牌无次数和距离限制", }, mod: { targetInRange: function (card, player, target) { if (player.getStorage("jsrgbiaozhao_A").includes(target)) return true; }, cardUsableTarget: function (card, player, target) { if (player.getStorage("jsrgbiaozhao_A").includes(target)) return true; }, }, }, B: { trigger: { source: "damageBegin1", }, charlotte: true, forced: true, onremove: function (player, skill) { for (var i in player.storage) { if (i.indexOf("jsrgbiaozhao_B") == 0) delete player.storage[i]; } }, filter: function (event, player) { return event.card && player.getStorage("jsrgbiaozhao_B").includes(event.player); }, content: function () { trigger.num += player.countMark("jsrgbiaozhao_B" + trigger.player.playerid) || 1; }, mark: true, marktext: "召", intro: { content: function (storage, player) { var str = ""; for (var target of storage) { str += "对" + get.translation(target) + "使用牌造成的伤害+" + player.countMark("jsrgbiaozhao_B" + target.playerid); } return str; }, }, }, }, }, jsrgyechou: { audio: 2, trigger: { player: "die" }, forceDie: true, direct: true, skillAnimation: true, animationColor: "wood", content: function () { "step 0"; player.chooseTarget(get.prompt2("jsrgyechou"), lib.filter.notMe).set("ai", target => { var player = _status.event.player; return -get.attitude(player, target); }); ("step 1"); if (result.bool) { var target = result.targets[0]; player.logSkill("jsrgyechou", target); target.addSkill("jsrgyechou_effect"); target.addMark("jsrgyechou_effect", 1, false); } }, subSkill: { effect: { trigger: { player: "damageBegin3", }, filter: function (event, player) { return event.num >= player.getHp(); }, forced: true, charlotte: true, onremove: true, content: function () { trigger.num *= 2 * player.countMark("jsrgyechou_effect"); }, mark: true, marktext: "仇", intro: { content: "当你受到伤害值不小于体力值的伤害时,此伤害翻&倍", }, ai: { effect: { target: function (card, player, target) { if (get.tag(card, "damage")) { if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; if (target.hp == 1) return 2; } }, }, }, }, }, }, //淳于琼 jsrgcangchu: { audio: "recangchu", trigger: { global: "phaseJieshuBegin", }, filter: function (event, player) { if (player.hasSkill("jsrgshishou_blocker")) return false; return player.getHistory("gain").length; }, direct: true, content: function () { "step 0"; var num = 0; player.getHistory("gain", evt => { num += evt.cards.length; }); event.num = num; player.chooseTarget(get.prompt("jsrgcangchu"), "令至多" + get.cnNumber(num) + "名角色各摸" + get.cnNumber(num > game.countPlayer() ? 2 : 1) + "张牌", [1, num]).set("ai", target => { var player = _status.event.player; return get.attitude(player, target) / Math.sqrt(target.countCards("hs") + 1); }); ("step 1"); if (result.bool) { var targets = result.targets.slice(); targets.sortBySeat(); player.logSkill("jsrgcangchu", targets); game.asyncDraw(targets, num > game.countPlayer() ? 2 : 1); game.delayex(); } }, }, jsrgshishou: { audio: "reshishou", trigger: { player: "useCard", }, forced: true, filter: function (event, player) { return event.card.name == "jiu"; }, group: "jsrgshishou_burn", content: function () { "step 0"; player.draw(3); player.addTempSkill("jsrgshishou_nouse"); }, mod: { aiOrder: function (player, card, num) { if (card.name == "jiu") return 0.01; }, }, ai: { halfneg: true, effect: { player_use(card, player, target) { if (card.name == "jiu") return [1, 1]; }, }, }, subSkill: { nouse: { charlotte: true, mod: { cardEnabled: function (card, player) { return false; }, cardUsable: function (card, player) { return false; }, cardSavable: function (card, player) { return false; }, }, mark: true, marktext: "失", intro: { content: "喝醉了,不能再使用牌", }, }, burn: { audio: "reshishou", trigger: { player: "damageEnd", }, forced: true, filter: function (event, player) { return event.hasNature("fire"); }, content: function () { player.addTempSkill("jsrgshishou_blocker", { player: "phaseEnd" }); }, }, blocker: { charlotte: true, mark: true, marktext: "守", intro: { content: "〖仓储〗失效直到下回合结束", }, }, }, }, //江山如故·起 sbyingmen: { trigger: { global: "phaseBefore", player: "enterGame", }, forced: true, filter: function (event, player) { return event.name != "phase" || game.phaseNumber == 0; }, content: function () { if (!_status.characterlist) lib.skill.pingjian.initList(); var characters = _status.characterlist.randomRemove(4); lib.skill.sbyingmen.addVisitors(characters, player); game.delayx(); }, ai: { combo: "sbpingjian", }, group: "sbyingmen_reload", subSkill: { reload: { trigger: { player: "phaseBegin" }, forced: true, locked: false, filter: function (event, player) { return player.getStorage("sbyingmen").length < 4; }, content: function () { if (!_status.characterlist) lib.skill.pingjian.initList(); var characters = _status.characterlist.randomRemove(4 - player.getStorage("sbyingmen").length); lib.skill.sbyingmen.addVisitors(characters, player); game.delayx(); }, }, }, getSkills: function (characters, player) { var skills = []; for (var name of characters) { if (Array.isArray(lib.character[name].skills)) { for (var skill of lib.character[name].skills) { var list = get.skillCategoriesOf(skill, player); list.remove("锁定技"); if (list.length > 0) continue; var info = get.info(skill); if (info && (!info.unique || info.gainable)) { // lib.skill.rehuashen.createAudio(name,skill,'jsrg_xushao'); skills.add(skill); } } } } return skills; }, addVisitors: function (characters, player) { player.addSkillBlocker("sbyingmen"); game.log(player, "将", "#y" + get.translation(characters), "加入了", "#g“访客”"); game.broadcastAll( function (player, characters) { player.tempname.addArray(characters); player.$draw( characters.map(function (name) { var cardname = "huashen_card_" + name; lib.card[cardname] = { fullimage: true, image: "character:" + name, }; lib.translate[cardname] = get.rawName2(name); return game.createCard(cardname, " ", " "); }), "nobroadcast" ); }, player, characters ); player.markAuto("sbyingmen", characters); var storage = player.getStorage("sbyingmen"); var skills = lib.skill.sbyingmen.getSkills(storage, player); player.addInvisibleSkill(skills); }, removeVisitors: function (characters, player) { var skills = lib.skill.sbyingmen.getSkills(characters, player); var characters2 = player.getStorage("sbyingmen").slice(0); characters2.removeArray(characters); skills.removeArray(lib.skill.sbyingmen.getSkills(characters2, player)); game.broadcastAll((player, characters) => player.tempname.removeArray(characters), player, characters); player.unmarkAuto("sbyingmen", characters); _status.characterlist.addArray(characters); player.removeInvisibleSkill(skills); }, onremove: function (player, skill) { lib.skill.sbyingmen.removeVisitors(player.getStorage("sbyingmen"), player); player.removeSkillBlocker("sbyingmen"); }, skillBlocker: function (skill, player) { if (!player.invisibleSkills.includes(skill) || skill == "sbpingjian" || skill == "sbpingjian") return false; return !player.hasSkill("sbpingjian"); }, marktext: "客", intro: { name: "访客", mark: function (dialog, storage, player) { if (!storage || !storage.length) return "当前没有“访客”"; dialog.addSmall([storage, "character"]); var skills = lib.skill.sbyingmen.getSkills(storage, player); if (skills.length) dialog.addText("
  • 当前可用技能:" + get.translation(skills), false); }, }, }, sbpingjian: { trigger: { player: ["useSkill", "logSkillBegin"] }, forced: true, locked: false, filter: function (event, player) { var skill = event.sourceSkill || event.skill; return player.invisibleSkills.includes(skill) && lib.skill.sbyingmen.getSkills(player.getStorage("sbyingmen"), player).includes(skill); }, content: function () { "step 0"; var visitors = player.getStorage("sbyingmen").slice(0); var drawers = visitors.filter(function (name) { return lib.character[name].skills && lib.character[name].skills.includes(trigger.sourceSkill); }); event.drawers = drawers; if (visitors.length == 1) event._result = { bool: true, links: visitors }; else { var dialog = ["评鉴:请选择移去一张“访客”"]; if (drawers.length) dialog.push('
    如果移去' + get.translation(drawers) + ",则你摸一张牌
    "); dialog.push([visitors, "character"]); player.chooseButton(dialog, true); } ("step 1"); if (result.bool) { lib.skill.sbyingmen.removeVisitors(result.links, player); game.log(player, "移去了", "#y" + get.translation(result.links[0])); if (event.drawers.includes(result.links[0])) { player.addTempSkill("sbpingjian_draw"); player.storage.sbpingjian_draw.push(trigger.skill); } } }, group: "sbpingjian_trigger", subSkill: { draw: { charlotte: true, init: function (player, skill) { if (!player.storage[skill]) player.storage[skill] = []; }, onremove: true, trigger: { player: ["useSkillAfter", "logSkill"] }, forced: true, popup: false, filter: function (event, player) { return player.getStorage("sbpingjian_draw").includes(event.skill); }, content: function () { player.storage.sbpingjian_draw.remove(trigger.skill); player.draw(); if (!player.storage.sbpingjian_draw.length) player.removeSkill("sbpingjian_draw"); }, }, trigger: { trigger: { player: "triggerInvisible" }, forced: true, forceDie: true, popup: false, charlotte: true, priority: 10, filter: function (event, player) { if (event.revealed) return false; var info = get.info(event.skill); if (info.charlotte) return false; var skills = lib.skill.sbyingmen.getSkills(player.getStorage("sbyingmen"), player); game.expandSkills(skills); return skills.includes(event.skill); }, content: function () { "step 0"; if (get.info(trigger.skill).silent) { event.finish(); } else { var info = get.info(trigger.skill); var event = trigger, trigger = event._trigger; var str; var check = info.check; if (info.prompt) str = info.prompt; else { if (typeof info.logTarget == "string") { str = get.prompt(event.skill, trigger[info.logTarget], player); } else if (typeof info.logTarget == "function") { var logTarget = info.logTarget(trigger, player, trigger.triggername, trigger.indexedData); if (get.itemtype(logTarget).indexOf("player") == 0) str = get.prompt(event.skill, logTarget, player); } else { str = get.prompt(event.skill, null, player); } } if (typeof str == "function") { str = str(trigger, player, trigger.triggername, trigger.indexedData); } var next = player.chooseBool("评鉴:" + str); next.set("yes", !info.check || info.check(trigger, player, trigger.triggername, trigger.indexedData)); next.set("hsskill", event.skill); next.set("forceDie", true); next.set("ai", function () { return _status.event.yes; }); if (typeof info.prompt2 == "function") { next.set("prompt2", info.prompt2(trigger, player, trigger.triggername, trigger.indexedData)); } else if (typeof info.prompt2 == "string") { next.set("prompt2", info.prompt2); } else if (info.prompt2 != false) { if (lib.dynamicTranslate[event.skill]) next.set("prompt2", lib.dynamicTranslate[event.skill](player, event.skill)); else if (lib.translate[event.skill + "_info"]) next.set("prompt2", lib.translate[event.skill + "_info"]); } if (trigger.skillwarn) { if (next.prompt2) { next.set("prompt2", '' + trigger.skillwarn + "。" + next.prompt2); } else { next.set("prompt2", trigger.skillwarn); } } } ("step 1"); if (result.bool) { if (!get.info(trigger.skill).cost) { trigger.revealed = true; } } else { trigger.untrigger(); trigger.cancelled = true; } }, }, }, ai: { combo: "sbyingmen", }, }, jsrgchaozheng: { audio: 2, trigger: { player: "phaseZhunbeiBegin" }, logTarget: function (event, player) { return game.filterPlayer(i => i != player); }, prompt: "是否发动【朝争】?", content: function () { player.chooseToDebate(game.filterPlayer(i => i != player)).set("callback", lib.skill.jsrgchaozheng.callback); }, callback: function () { var result = event.debateResult; if (result.bool && result.opinion) { var opinion = result.opinion, targets = result.red.map(i => i[0]); targets.sortBySeat(); targets.forEach(i => i[opinion == "red" ? "recover" : "loseHp"]()); if (targets.length == 0 || result.black.length == 0) player.draw(result.targets.length); } }, }, jsrgshenchong: { audio: 2, enable: "phaseUse", limited: true, filterTarget: lib.filter.notMe, skillAnimation: true, animationColor: "soil", content: function () { "step 0"; player.awakenSkill("jsrgshenchong"); target.addSkillLog("jsrgfeiyang"); target.addSkillLog("jsrgbahu"); ("step 1"); player.addSkill("jsrgshenchong_die"); player.markAuto("jsrgshenchong_die", [target]); }, ai: { order: 1, result: { target: 1 }, }, subSkill: { die: { audio: "jsrgshenchong", trigger: { player: "die" }, charlotte: true, forced: true, forceDie: true, filter: function (event, player) { return player.getStorage("jsrgshenchong_die").length; }, content: function () { var targets = player.getStorage("jsrgshenchong_die"); player.line(targets); targets.sortBySeat().forEach(current => { current.clearSkills(true); current.chooseToDiscard(current.countCards("h"), "h", true); }); }, }, }, }, jsrgfeiyang: { trigger: { player: "phaseJudgeBegin" }, direct: true, filter: function (event, player) { return player.countCards("j") && player.countCards("h") > 1; }, content: function () { "step 0"; player .chooseToDiscard("h", 2, get.prompt("jsrgfeiyang"), "弃置两张手牌并弃置判定区里的一张牌") .set("logSkill", "jsrgfeiyang") .set("ai", function (card) { if (_status.event.goon) return 6 - get.value(card); return 0; }) .set( "goon", (() => { if (player.hasSkillTag("rejudge") && player.countCards("j") < 2) return false; return player.hasCard(function (card) { if (get.tag(card, "damage") && get.damageEffect(player, player, _status.event.player, get.natureList(card)) >= 0) return false; return ( get.effect( player, { name: card.viewAs || card.name, cards: [card], }, player, player ) < 0 ); }, "j"); })() ); ("step 1"); if (result.bool) { player.discardPlayerCard(player, "j", true); } }, }, jsrgbahu: { trigger: { player: "phaseZhunbeiBegin" }, forced: true, content: function () { player.draw(); }, mod: { cardUsable: function (card, player, num) { if (card.name == "sha") return num + 1; }, }, }, jsrgjulian: { audio: 2, trigger: { player: "phaseJieshuBegin" }, filter: function (event, player) { return player.hasZhuSkill("jsrgjulian") && lib.skill.jsrgjulian.logTarget(null, player).length; }, prompt: "是否发动【聚敛】?", prompt2: "你可以获得其他所有群势力角色的各一张牌", logTarget: function (event, player) { return game.filterPlayer(current => { return current.group == "qun" && current.countGainableCards(player, "he") > 0 && current != player; }); }, content: function () { game.filterPlayer(current => { return current.group == "qun" && current != player; }) .sortBySeat() .forEach(i => { player.gainPlayerCard(i, "he", true); }); }, group: "jsrgjulian_draw", zhuSkill: true, subSkill: { draw: { audio: "jsrgjulian", trigger: { global: "gainAfter" }, filter: function (event, player) { var source = event.player; if (source == player || source.group != "qun") return false; var evt = event.getParent("phaseDraw"); return (!evt || evt.player != source) && event.getParent().name == "draw" && event.getParent(2).name != "jsrgjulian_draw" && player.hasZhuSkill("jsrgjulian", event.player); }, direct: true, usable: 2, content: function () { "step 0"; var source = trigger.player; event.source = source; source.chooseBool("是否响应" + get.translation(player) + "的【聚敛】摸一张牌?"); ("step 1"); if (result.bool) { source.logSkill("jsrgjulian_draw", player); source.draw(); } else player.storage.counttrigger.jsrgjulian_draw--; }, }, give: { charlotte: true, onremove: true, }, }, }, //何进 jsrgzhaobing: { audio: 2, trigger: { player: "phaseJieshuBegin" }, direct: true, filter: function (event, player) { var hs = player.getCards("h"); if (!hs.length) return false; for (var i of hs) { if (!lib.filter.cardDiscardable(i, player, "jsrgzhaobing")) return false; } return true; }, content: function () { "step 0"; var cards = player.getCards("h"); var num = cards.length; var prompt2 = "弃置所有手牌,令至多" + get.cnNumber(num) + "名其他角色依次选择一项:1.正面向上交给你一张【杀】;2.失去1点体力"; player .chooseTarget(get.prompt("jsrgzhaobing"), prompt2, [1, num], lib.filter.notMe) .set("ai", target => { if (!_status.event.goon) return 0; return 2 - get.attitude(_status.event.player, target); }) .set( "goon", num / 2 < game.countPlayer(current => { return 2 - get.attitude(player, current) > 0; }) ); ("step 1"); if (result.bool) { player.logSkill("jsrgzhaobing", result.targets); event.targets = result.targets; event.targets.sortBySeat(); player.chooseToDiscard(true, "h", player.countCards("h")); } else event.finish(); ("step 2"); var target = targets.shift(); event.target = target; target .chooseCard("诏兵:交给" + get.translation(player) + "一张【杀】,或失去1点体力", card => { return get.name(card) == "sha"; }) .set("ai", card => { if (_status.event.goon) return 0; return 6 - get.value(card); }) .set("goon", get.effect(target, { name: "losehp" }, target, target) >= 0); ("step 3"); if (result.bool) target.give(result.cards, player, true); else target.loseHp(); if (targets.length) event.goto(2); }, ai: { expose: 0.2, }, }, jsrgzhuhuan: { audio: "mouzhu", trigger: { player: "phaseZhunbeiBegin" }, filter: function (event, player) { var hs = player.getCards("h", "sha"); if (!hs.length) return false; for (var i of hs) { if (!lib.filter.cardDiscardable(i, player, "jsrgzhuhuan")) return false; } return true; }, direct: true, content: function () { "step 0"; player.chooseTarget(get.prompt2("jsrgzhuhuan"), lib.filter.notMe).set("ai", target => { var player = _status.event.player; return get.damageEffect(target, player, player); }); ("step 1"); if (result.bool) { var target = result.targets[0]; event.target = target; player.logSkill("jsrgzhuhuan", target); var hs = player.getCards("h", "sha"); event.num = hs.length; player.discard(hs); } else event.finish(); ("step 2"); target .chooseToDiscard(get.translation(player) + "对你发动了【诛宦】", "弃置" + get.cnNumber(num) + "张牌并失去1点体力;或点击“取消”令其回复1点体力且其摸" + get.cnNumber(num) + "张牌") .set("ai", card => { if (_status.event.goon) return 0; return 5.5 - get.value(card); }) .set("goon", target.hp <= 2 || get.attitude(target, player) >= 0 || player.isHealthy()); ("step 3"); if (result.bool) { target.loseHp(); } else { player.draw(num); player.recover(); } }, ai: { expose: 0.2, }, }, jsrgyanhuo: { inherit: "spyanhuo", forced: true, }, //孙坚 jsrgpingtao: { audio: 2, enable: "phaseUse", usable: 1, filterTarget: lib.filter.notMe, content: function () { "step 0"; var att = get.attitude(target, player); target .chooseCard(get.translation(player) + "对你发动了【平讨】", "交给其一张牌并令其此回合使用【杀】的次数上限+1;或点击“取消”令其视为对你使用一张【杀】", "he") .set("ai", card => { if (_status.event.give) { if (card.name == "sha" || card.name == "tao" || card.name == "jiu") return 0; return 8 - get.value(card); } if (_status.event.att < 0 && card.name == "sha") return -1; return 4 - get.value(card); }) .set("give", (att >= 0 || (target.hp == 1 && target.countCards("hs", "shan") <= 1)) && get.effect(target, { name: "sha" }, player, target) < 0) .set("att", att); ("step 1"); if (result.bool) { target.give(result.cards, player); player.addTempSkill("jsrgpingtao_sha"); player.addMark("jsrgpingtao_sha", 1, false); } else if (player.canUse("sha", target, false)) { player.useCard({ name: "sha", isCard: true }, target, false); } }, ai: { expose: 0.15, order: 5, result: { target: -1 }, }, subSkill: { sha: { charlotte: true, onremove: true, marktext: "讨", intro: { content: "本回合使用【杀】的次数上限+#", }, mod: { cardUsable: function (card, player, num) { if (card.name == "sha") return num + player.countMark("jsrgpingtao_sha"); }, }, }, }, }, jsrgjuelie: { audio: 2, trigger: { player: "useCardToPlayered" }, filter: function (event, player) { return player.countCards("he") && event.card.name == "sha"; }, direct: true, content: function () { "step 0"; player .chooseToDiscard(get.prompt("jsrgjuelie", trigger.target), "当你使用【杀】指定一名角色为目标后,你可以弃置任意张牌,然后弃置其等量的牌", [1, Infinity], "he") .set("ai", card => { if (ui.selected.cards.length >= _status.event.max) return 0; if (_status.event.goon) return 4.5 - get.value(card); return 0; }) .set("max", trigger.target.countDiscardableCards(player, "he")) .set("goon", get.attitude(player, trigger.target) < 0) .set("logSkill", ["jsrgjuelie_discard", trigger.target]); ("step 1"); if (result.bool) { var num = result.cards.length; if (trigger.target.countDiscardableCards(player, "he")) player.discardPlayerCard("平讨:弃置" + get.translation(trigger.target) + get.cnNumber(num) + "张牌", num, "he", trigger.target, true); } /* else event.finish(); 'step 2' if(player.isMinHandcard()||player.isMinHp()){ var id=trigger.target.playerid; var map=trigger.getParent().customArgs; if(!map[id]) map[id]={}; if(typeof map[id].extraDamage!='number'){ map[id].extraDamage=0; } map[id].extraDamage++; } */ }, shaRelated: true, ai: { unequip_ai: true, skillTagFilter: function (player, tag, arg) { if (!arg || !arg.name || arg.name != "sha") return false; if (!arg.target) return false; var card = arg.target.getEquip(2); return ( card && get.value(card) > 0 && player.hasCard(cardx => { return lib.filter.cardDiscardable(cardx, player, "jsrgjuelie_discard") && get.value(cardx) < 5; }) ); }, }, group: "jsrgjuelie_pojun", subSkill: { pojun: { trigger: { source: "damageBegin1" }, filter: function (event, player) { if (!player.isMinHandcard() && !player.isMinHp()) return false; return event.getParent().name == "sha"; }, forced: true, locked: false, logTarget: "player", content: function () { trigger.num++; }, }, }, }, //皇甫嵩 jsrgguanhuo: { audio: 2, trigger: { player: "useCardAfter" }, filter: function (event, player) { return ( event.card.storage && event.card.storage.jsrgguanhuo && !game.hasPlayer2(current => { return current.hasHistory("damage", evt => evt.card == event.card); }) ); }, forced: true, locked: false, group: "jsrgguanhuo_viewas", content: function () { "step 0"; var count = player.getHistory("useSkill", evt => { return evt.skill == "jsrgguanhuo_viewas" && evt.event.getParent("phaseUse") === trigger.getParent("phaseUse"); }).length; if (count == 1) { player.addTempSkill("jsrgguanhuo_ex", "phaseUseAfter"); player.addMark("jsrgguanhuo_ex", 1, false); trigger.targets.forEach(i => i.removeSkill("huogong2")); } else { player.removeSkills("jsrgguanhuo"); } }, ai: { effect: { player: function (card, player) { if ( _status.event.getParent().skill == "jsrgguanhuo_viewas" && player.getHistory("useSkill", evt => { return evt.skill == "jsrgguanhuo_viewas" && evt.event.getParent("phaseUse") === _status.event.getParent("phaseUse"); }).length == 1 ) return "zeroplayertarget"; if ( _status.event.type == "phase" && _status.event.skill == "jsrgguanhuo_viewas" && player.getHistory("useSkill", evt => { return evt.skill == "jsrgguanhuo_viewas" && evt.event.getParent("phaseUse") === _status.event.getParent("phaseUse"); }).length > 1 && player.countCards("h") <= 3 ) return [0, 0]; }, }, }, subSkill: { viewas: { audio: "jsrgguanhuo", enable: "phaseUse", viewAs: { name: "huogong", isCard: true, storage: { jsrgguanhuo: true, }, }, filterCard: () => false, selectCard: -1, prompt: "视为使用一张【火攻】", ai: { order: function (item, player) { return get.order({ name: "huogong" }) + 0.01; }, }, }, ex: { trigger: { source: "damageBegin1" }, filter: function (event, player) { return event.card && event.card.name == "huogong" && event.getParent().type == "card"; }, forced: true, charlotte: true, onremove: true, intro: { content: "当你造成渠道为【火攻】的伤害时,此伤害+#" }, content: function () { trigger.num += player.countMark("jsrgguanhuo_ex"); }, }, }, }, jsrgjuxia: { audio: 2, trigger: { target: "useCardToTargeted" }, usable: 1, countSkill: function (player) { return player.getSkills(null, false, false).filter(function (skill) { var info = get.info(skill); if (!info || info.charlotte) return false; if (info.zhuSkill) return player.hasZhuSkill(skill); return true; }).length; }, filter: function (event, player) { return event.player != player && lib.skill.jsrgjuxia.countSkill(event.player) > lib.skill.jsrgjuxia.countSkill(player); }, direct: true, content: function () { "step 0"; var goon = get.effect(player, trigger.card, trigger.player, trigger.player) < 1; if (goon && !event.isMine() && !event.isOnline()) game.delayx(); trigger.player .chooseBool("是否对" + get.translation(player) + "发动【居下】?", "令" + get.translation(trigger.card) + "对其无效,然后其摸两张牌") .set("ai", () => { return _status.event.goon; }) .set("goon", goon); ("step 1"); if (result.bool) { trigger.player.logSkill("jsrgjuxia", player); trigger.excluded.add(player); player.draw(2); } else player.storage.counttrigger.jsrgjuxia--; }, ai: { effect: { target_use(card, player, target) { if (lib.skill.jsrgjuxia.countSkill(target) >= lib.skill.jsrgjuxia.countSkill(player)) return; if (card && (card.cards || card.isCard) && get.attitude(target, player) > 0 && (!target.storage.counttrigger || !target.storage.counttrigger.jsrgjuxia)) return [0, 0.5, 0, 0.5]; }, }, }, }, //许劭 jsrgyingmen: { audio: 2, trigger: { global: "phaseBefore", player: ["enterGame", "phaseBegin"], }, forced: true, filter: function (event, player, name) { if (player.getStorage("jsrgyingmen").length >= 4) return false; if (name == "phaseBefore") return game.phaseNumber == 0; return event.name != "phase" || event.player == player; }, update: function (player) { var id = player.playerid; var characters = player.getStorage("jsrgyingmen"); var skillName = "jsrgpingjian_" + id; var skillsx = [], skillsx2 = []; var map = {}; var skillsy = lib.skill[skillName] ? lib.skill[skillName].group : []; for (var name of characters) { var skills = lib.character[name][3].slice(); skills = skills.filter(skill => { var list = get.skillCategoriesOf(skill, player); list.removeArray(["锁定技", "Charlotte"]); if (list.length) return false; var info = get.info(skill); return info && (!info.unique || info.gainable); }); game.expandSkills(skills); for (var i = 0; i < skills.length; i++) { var skill = skills[i]; var info = get.info(skill); if (info.silent || info.charlotte) continue; if (!info.forced && !info.frequent && (!info.mod || (info.charlotte && info.mod))) continue; var infox = get.copy(info); var newname = skill + "_" + id; map[newname] = infox; if (info.audio) infox.audio = typeof info.audio != "number" ? info.audio : skill; // if(infox.group) delete infox.group; if (infox.frequent) delete infox.frequent; if (infox.forceDie) delete infox.forceDie; var popup = infox.popup; if (infox.forced && infox.direct) { delete infox.direct; infox.popup = false; } if (infox.forced && !infox.prompt2) { var skillx = skill; while (true) { var prompt2 = lib.translate[skillx + "_info"]; if (prompt2 && prompt2.length) { infox.prompt2 = prompt2; break; } var ind = skillx.lastIndexOf("_"); if (ind == -1) break; skillx = skillx.slice(0, ind); } } if (popup != false && !infox.silent) infox.forced = false; if (!infox.charlotte && infox.mod) delete infox.mod; skillsx2.add(skill); skills[i] = newname; } if (skills.length) { skillsx.addArray(skills); } } var skillsRemoving = skillsy.removeArray(skillsx); player.removeSkill(skillsRemoving); game.broadcastAll( function (name, skillsx, skillsx2, id, map) { for (var i in map) lib.skill[i] = map[i]; lib.skill[name] = { unique: true, group: skillsx, }; lib.translate[name] = "评鉴"; for (var i of skillsx2) { lib.translate[i + "_" + id] = lib.translate[i]; lib.translate[i + "_" + id + "_info"] = lib.translate[i + "_info"]; } }, skillName, skillsx, skillsx2, id, map ); player.addSkill(skillName); player.addSkill("jsrgpingjian_blocker"); player.addSkillTrigger(skillName); }, bannedList: ["zishu", "weishu", "xinfu_zhanji", "kyouko_rongzhu"], content: function () { "step 0"; if (!_status.characterlist) lib.skill.pingjian.initList(); var num = player.getStorage("jsrgyingmen").length; var list = []; _status.characterlist.randomSort(); for (var i = 0; i < _status.characterlist.length; i++) { var name = _status.characterlist[i]; var skills = lib.character[name][3].slice(); if ( skills.some(skill => { return lib.skill.jsrgyingmen.bannedList.includes(skill); }) ) continue; list.push(name); _status.characterlist.remove(name); if (list.length >= 4 - num) break; } if (list.length) { player.markAuto("jsrgyingmen", list); if (player.hasSkill("jsrgpingjian", null, false, false)) lib.skill.jsrgyingmen.update(player); game.log(player, "将", "#g" + get.translation(list), "置为", "#y访客"); game.broadcastAll( function (player, list) { var cards = []; for (var i = 0; i < list.length; i++) { var cardname = "huashen_card_" + list[i]; lib.card[cardname] = { fullimage: true, image: "character:" + list[i], }; lib.translate[cardname] = get.rawName2(list[i]); cards.push(game.createCard(cardname, "", "")); } player.$draw(cards, "nobroadcast"); }, player, list ); } }, ai: { combo: "jsrgpingjian", }, marktext: "客", intro: { name: "访客(盈门/评鉴)", mark: function (dialog, storage, player) { dialog.addText("剩余“访客”"); if (storage) dialog.addSmall([storage, "character"]); else dialog.addText("无"); }, }, }, jsrgpingjian: { audio: 2, trigger: { player: ["logSkill", "useSkillAfter"] }, forced: true, locked: false, onremove: function (player) { player.removeSkill("jsrgpingjian_" + player.playerid); }, filter: function (event, player) { var skill = event.skill, name = event.event ? event.event.name : ""; var visitors = player.getStorage("jsrgyingmen"); for (var visitor of visitors) { var skills = lib.character[visitor][3].slice(); game.expandSkills(skills); var info = get.info(skill); if (info && (info.charlotte || info.silent)) continue; if ( skills.some(skillx => { return skill.indexOf(skillx) == 0 || name.indexOf(skillx + "_" + player.playerid) == 0; }) ) return true; } return false; }, content: function () { "step 0"; var current; var skill = trigger.skill, name = trigger.event ? trigger.event.name : ""; var visitors = player.getStorage("jsrgyingmen"); for (var visitor of visitors) { var skills = lib.character[visitor][3].slice(); game.expandSkills(skills); var info = get.info(skill); if (info && info.charlotte) continue; if ( skills.some(skillx => { return skill.indexOf(skillx) == 0 || name.indexOf(skillx + "_" + player.playerid) == 0; }) ) { current = visitor; break; } } event.current = current; player .chooseButton(['###评鉴:移去一名访客###
    若移去的访客为' + get.translation(current) + ",则你摸一张牌
    ", [player.getStorage("jsrgyingmen"), "character"]], true) .set("ai", button => { if (button.link == _status.event.toremove) return 1; return Math.random(); }) .set( "toremove", (function () { var list = player.getStorage("jsrgyingmen"); var rand = Math.random(); if (rand < 0.33) return list[0]; if (rand < 0.66) return current; return list.randomGet(); })() ); ("step 1"); if (result.bool) { var visitor = result.links[0]; game.log(player, "从", "#y访客", "中移去了", "#g" + get.translation(visitor)); player.popup(visitor); player.unmarkAuto("jsrgyingmen", [visitor]); _status.characterlist.add(visitor); if (visitor == event.current) player.draw(); lib.skill.jsrgyingmen.update(player); } }, subSkill: { blocker: { init: function (player, skill) { player.addSkillBlocker(skill); }, onremove: function (player, skill) { player.removeSkillBlocker(skill); }, charlotte: true, locked: true, skillBlocker: function (skill, player) { if (skill != "jsrgpingjian_" + player.playerid) return false; if (player._jsrgpingjian_blockerChecking) return; player._jsrgpingjian_blockerChecking = true; var own = player.hasSkill("jsrgpingjian"); delete player._jsrgpingjian_blockerChecking; return !own; }, }, }, }, //董白 jsrgshichong: { audio: 2, zhuanhuanji: true, trigger: { player: "useCardToPlayered" }, direct: true, filter: function (event, player) { return event.target != player && event.targets.length == 1 && event.target.isIn() && event.target.countCards("h"); }, mark: true, marktext: "☯", intro: { content: function (storage, player) { var str = "转换技。当你使用牌指定其他角色为唯一目标后,"; if (storage) return str + "目标角色可以交给你一张手牌。"; return str + "你可以获得目标角色一张手牌。"; }, }, content: function () { "step 0"; if (!player.storage.jsrgshichong) { player .chooseBool(get.prompt("jsrgshichong", trigger.target), "你可以获得该角色的一张手牌") .set("ai", () => { return _status.event.bool; }) .set("bool", get.attitude(player, trigger.target) <= 0); } else { trigger.target .chooseCard("是否发动" + get.translation(player) + "的【恃宠】?", "你可以选择一张手牌,并交给该角色") .set("ai", card => { if (_status.event.goon) return 5 - get.value(card); return 0 - get.value(card); }) .set("goon", get.attitude(trigger.target, player) > 2); } ("step 1"); if (result.bool) { if (!player.storage.jsrgshichong) { player.logSkill("jsrgshichong", trigger.target); player.gainPlayerCard(trigger.target, "h", true); } else { trigger.target.logSkill("jsrgshichong", player); trigger.target.give(result.cards, player); } player.changeZhuanhuanji("jsrgshichong"); } }, }, jsrglianzhu: { audio: 2, enable: "phaseUse", usable: 1, filterCard: { color: "black" }, position: "h", filterTarget: lib.filter.notMe, lose: false, discard: false, delay: false, content: function () { "step 0"; player.showCards(cards, get.translation(player) + "发动了【连诛】"); ("step 1"); player.give(cards, target); ("step 2"); event.targets = game .filterPlayer(current => { return current.group == target.group && current != player; }) .sortBySeat(); game.delayx(); ("step 3"); var target = targets.shift(); if (player.canUse("guohe", target)) { player.useCard({ name: "guohe", isCard: true }, target); } if (targets.length) event.redo(); }, ai: { order: 4, result: { target: function (player, target) { var targets = game.filterPlayer(current => { return current.group == target.group && current != player; }); var eff = targets.reduce((p, c) => { return p + get.effect(c, { name: "guohe" }, player, player); }, 0); if (ui.selected.cards.length) eff += get.value(ui.selected.cards[0], target); return eff; }, }, }, }, //桥玄 jsrgjuezhi: { audio: 2, trigger: { source: "damageBegin1" }, filter: function (event, player) { if (_status.currentPhase != player || player.hasSkill("jsrgjuezhi_used", null, null, false)) return false; return event.card && event.getParent().type == "card" && lib.skill.jsrgjuezhi.getNum(event.player, player) > 0; }, forced: true, locked: false, getNum: function (target, player) { return target.countCards("e", card => { var subtype = get.subtypes(card); for (var i of subtype) { if (player.hasDisabledSlot(i)) return true; } return false; }); }, group: "jsrgjuezhi_disable", content: function () { player.addTempSkill("jsrgjuezhi_used", ["phaseZhunbeiAfter", "phaseJudgeAfter", "phaseDrawAfter", "phaseUseAfter", "phaseDiscardAfter", "phaseJieshuAfter"]); trigger.num += lib.skill.jsrgjuezhi.getNum(trigger.player, player); }, subSkill: { disable: { audio: "jsrgjuezhi", trigger: { player: "loseAfter", global: ["equipAfter", "addJudgeAfter", "gainAfter", "loseAsyncAfter", "addToExpansionAfter"], }, direct: true, filter: function (event, player) { var evt = event.getl(player); return evt && evt.es && evt.es.length > 0; }, content: function () { "step 0"; event.cards = trigger.getl(player).es; ("step 1"); var card = cards.shift(), subtypes = get.subtypes(card).filter(slot => player.hasEnabledSlot(slot)); event.subtypes = subtypes; if (subtypes.length > 0) { player.chooseBool(get.prompt("jsrgjuezhi_disable"), "废除你的" + get.translation(subtypes) + "栏").set("ai", () => 1); } else event._result = { bool: false }; ("step 2"); if (result.bool) { player.logSkill("jsrgjuezhi_disable"); player.disableEquip(event.subtypes); } if (cards.length > 0) event.goto(1); }, }, used: { charlotte: true }, }, }, jsrgjizhao: { audio: 2, trigger: { player: ["phaseZhunbeiBegin", "phaseJieshuBegin"] }, direct: true, content: function () { "step 0"; player.chooseTarget(get.prompt2("jsrgjizhao")).set("ai", target => { var player = _status.event.player; if (player.countCards("j")) return player == target ? 10 : 0.1; return 6 - get.attitude(player, target); }); ("step 1"); if (result.bool) { var target = result.targets[0]; event.target = target; player.logSkill("jsrgjizhao", target); target.chooseToUse({ filterCard: function (card, player, event) { if (get.itemtype(card) != "card" || (get.position(card) != "h" && get.position(card) != "s")) return false; return lib.filter.filterCard.apply(this, arguments); }, prompt: "急召:使用一张手牌,否则" + get.translation(player) + "可以移动你区域里的一张牌", addCount: false, goon: target != player || !player.countCards("j"), ai1: function (card) { if (_status.event.goon) return get.order(card); return 0; }, }); } else { event.finish(); return; } ("step 2"); if (result.bool) { event.finish(); return; } var targets = game.filterPlayer(current => { if (current == target) return false; var hs = target.getCards("h"); if (hs.length) return true; var js = target.getCards("j"); for (var i = 0; i < js.length; i++) { if (current.canAddJudge(js[i])) return true; } if (current.isMin()) return false; var es = target.getCards("e"); for (var i = 0; i < es.length; i++) { if (current.canEquip(es[i])) return true; } return false; }); if (targets.length) { var next = player.chooseTarget(function (card, player, target) { return _status.event.targets.includes(target); }); next.set("from", target); next.set("targets", targets); next.set("ai", function (target) { var player = _status.event.player; var att = get.attitude(player, target); var sgnatt = get.sgn(att); var from = _status.event.from; var es = from.getCards("e"); var i; var att2 = get.sgn(get.attitude(player, from)); for (i = 0; i < es.length; i++) { if (sgnatt != 0 && att2 != 0 && sgnatt != att2 && get.sgn(get.value(es[i], from)) == -att2 && get.sgn(get.effect(target, es[i], player, target)) == sgnatt && target.canEquip(es[i])) { return Math.abs(att); } } if ( i == es.length && (!from.countCards("j", function (card) { return target.canAddJudge(card); }) || att2 <= 0) ) { if (from.countCards("h") > 0) return att; return 0; } return -att * att2; }); next.set("targetprompt", "移动目标"); next.set("prompt", "急召:是否移动" + get.translation(target) + "的一张牌?"); } else event.finish(); ("step 3"); if (result.bool) { var target2 = result.targets[0]; event.targets = [target, target2]; player.line2(event.targets, "green"); } else { event.finish(); } ("step 4"); game.delay(); ("step 5"); if (targets.length == 2) { player .choosePlayerCard( "hej", true, function (button) { var player = _status.event.player; var targets0 = _status.event.targets0; var targets1 = _status.event.targets1; if (get.attitude(player, targets0) > 0 && get.attitude(player, targets1) < 0) { if (get.position(button.link) == "j") return 12; if (get.value(button.link, targets0) < 0 && get.effect(targets1, button.link, player, targets1) > 0) return 10; return 0; } else { if (get.position(button.link) == "j") return -10; if (get.position(button.link) == "h") return 10; return get.value(button.link) * get.effect(targets1, button.link, player, targets1); } }, targets[0] ) .set("targets0", targets[0]) .set("targets1", targets[1]) .set("filterButton", function (button) { var targets1 = _status.event.targets1; if (get.position(button.link) == "h") { return true; } else if (get.position(button.link) == "j") { return targets1.canAddJudge(button.link); } else { return targets1.canEquip(button.link); } }); } else { event.finish(); } ("step 6"); if (result.bool && result.links.length) { var link = result.links[0]; if (get.position(link) == "h") event.targets[1].gain(link, event.targets[0], "giveAuto"); else { event.targets[0].$give(link, event.targets[1], false); if (get.position(link) == "e") event.targets[1].equip(link); else if (link.viewAs) event.targets[1].addJudge({ name: link.viewAs }, [link]); else event.targets[1].addJudge(link); } game.log(event.targets[0], "的", get.position(link) == "h" ? "一张手牌" : link, "被移动给了", event.targets[1]); game.delay(); } }, ai: { effect: { target: function (card, player, target, current) { if (get.type(card) == "delay" && current < 0) { if (target.countCards("j")) return; return "zerotarget"; } }, }, }, }, //杨彪 jsrgzhaohan: { audio: "zhaohan", trigger: { player: "phaseZhunbeiBegin" }, forced: true, //locked:false, filter: function (event, player) { if (game.shuffleNumber == 0) return player.isDamaged(); return true; }, content: function () { player[game.shuffleNumber > 0 ? "loseHp" : "recover"](); }, }, jsrgrangjie: { audio: "rangjie", trigger: { player: "damageEnd" }, filter: function (event, player) { return player.canMoveCard(); }, check: function (event, player) { return player.canMoveCard(true); }, content: function () { "step 0"; event.num = trigger.num; ("step 1"); event.num--; if (player.canMoveCard()) player.moveCard(true); ("step 2"); if (result.bool) { var card = result.card; var suit = get.suit(card, false); var cards = Array.from(ui.discardPile.childNodes); var gains = []; var history = game.getGlobalHistory("cardMove", evt => { if (evt.name == "lose") return evt.position == ui.discardPile; return evt.name == "cardsDiscard"; }); for (var i = history.length - 1; i >= 0; i--) { var evt = history[i]; var cards2 = evt.cards.filter(card => { return cards.includes(card) && get.suit(card, false) == suit; }); if (cards2.length) { gains.addArray(cards2); cards.removeArray(cards2); } if (!cards.length) break; } if (gains.length) { player.chooseButton(["让节:是否获得一张" + get.translation(suit) + "牌?", gains]).set("ai", get.buttonValue); } else event._result = { bool: false }; } ("step 3"); if (result.bool) { player.gain(result.links, "gain2"); } ("step 4"); if (event.num > 0 && player.hasSkill("jsrgrangjie")) { player .chooseBool(get.prompt2("jsrgrangjie")) .set("ai", () => _status.event.bool) .set("bool", lib.skill.jsrgrangjie.check(trigger, player)); } else event.finish(); ("step 5"); if (result.bool) { player.logSkill("jsrgrangjie"); event.goto(1); } }, ai: { maixie: true, maixie_hp: true, effect: { target: function (card, player, target) { if (get.tag(card, "damage")) { if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; if (target._jsrgrangjie_aiChecking) return; target._jsrgrangjie_aiChecking = true; var moveCard = target.canMoveCard(true); delete target._jsrgrangjie_aiChecking; if (!moveCard || !target.hasFriend()) return; var num = 1; if (get.attitude(player, target) > 0) { if (player.needsToDiscard()) num = 0.5; else num = 0.3; } if (target.hp >= 4) return [1, num * 2]; if (target.hp == 3) return [1, num * 1.5]; if (target.hp == 2) return [1, num * 0.5]; } }, }, }, }, jsrgyizheng: { audio: "yizheng", enable: "phaseUse", usable: 1, filter: function (event, player) { return game.hasPlayer(function (current) { return current.countCards("h") > player.countCards("h") && player.canCompare(current); }); }, filterTarget: function (card, player, current) { return current.countCards("h") > player.countCards("h") && player.canCompare(current); }, content: function () { "step 0"; player.chooseToCompare(target); ("step 1"); if (result.bool) { target.skip("phaseDraw"); target.addTempSkill("yizheng2", { player: "phaseDrawSkipped" }); event.finish(); } else { target .chooseControl("1", "2", "cancel") .set("prompt", "是否对" + get.translation(player) + "造成至多2点伤害?") .set("ai", () => { return _status.event.choice; }) .set("choice", get.damageEffect(player, target, target) > 0 ? (get.attitude(target, player) > 0 ? 0 : 1) : "cancel2"); } ("step 2"); if (result.control != "cancel2") { var num = result.index + 1; target.line(player); player.damage(target, num); } }, ai: { order: 1, result: { target: function (player, target) { if (target.skipList.includes("phaseDraw") || target.hasSkill("pingkou")) return 0; var hs = player.getCards("h").sort(function (a, b) { return b.number - a.number; }); var ts = target.getCards("h").sort(function (a, b) { return b.number - a.number; }); if (!hs.length || !ts.length) return 0; if (hs[0].number > ts[0].number) return -1; return 0; }, }, }, }, //孔融 jsrglirang: { audio: "splirang", trigger: { global: "phaseDrawBegin" }, direct: true, filter: function (event, player) { return event.player != player && !player.hasSkill("jsrglirang_used") && player.countCards("he") > 1; }, content: function () { "step 0"; player .chooseCard(get.prompt("jsrglirang", trigger.player), "你可以选择两张牌,将这些牌交给该角色。若如此做,你获得其本回合弃牌阶段弃置的所有牌。", 2, "he") .set("ai", card => { if (!_status.event.give) return 0; var player = _status.event.player, target = _status.event.target; return target.getUseValue(card) - player.getUseValue(card) + 0.5; }) .set("give", get.attitude(player, trigger.player) > 0) .set("target", trigger.player); ("step 1"); if (result.bool) { player.logSkill("jsrglirang", trigger.player); var cards = result.cards; player.give(cards, trigger.player); player.addTempSkill("jsrglirang_used", "roundStart"); player.addTempSkill("jsrglirang_given"); player.markAuto("jsrglirang_used", [trigger.player]); } }, subSkill: { used: { charlotte: true, onremove: true, intro: { content: "本轮〖礼让〗目标:$" }, }, given: { audio: "splirang", trigger: { global: "phaseDiscardEnd" }, filter: function (event, player) { return event.player.hasHistory("lose", evt => { return evt.type == "discard" && evt.getParent("phaseDiscard") == event && evt.cards2.filterInD("d").length > 0; }); }, charlotte: true, prompt2: function (event, player) { var cards = []; event.player.getHistory("lose", evt => { if (evt.type == "discard" && evt.getParent("phaseDiscard") == event) cards.addArray(evt.cards2.filterInD("d")); }); return "获得" + get.translation(cards); }, content: function () { var cards = []; trigger.player.getHistory("lose", evt => { if (evt.type == "discard" && evt.getParent("phaseDiscard") == trigger) cards.addArray(evt.cards2.filterInD("d")); }); player.gain(cards, "gain2"); }, }, }, }, jsrgzhengyi: { audio: 2, trigger: { player: "damageBegin4" }, filter: function (event, player) { var list = player.getStorage("jsrglirang_used"); if (!list.length) return false; return !player.getHistory("damage").length && list[0].isIn(); }, direct: true, content: function () { "step 0"; var target = player.getStorage("jsrglirang_used")[0]; event.target = target; target .chooseBool("是否对" + get.translation(player) + "发动【争义】?", "将此" + (trigger.source ? "来源为" + get.translation(trigger.source) : "无来源") + "的" + trigger.num + "点伤害转移给你") .set("ai", () => { return _status.event.bool; }) .set("bool", get.damageEffect(player, trigger.source, target) > get.damageEffect(target, trigger.source, target)); ("step 1"); if (result.bool) { target.logSkill("jsrgzhengyi", player); trigger.cancel(); target.damage(trigger.source, trigger.nature, trigger.num).set("card", trigger.card).set("cards", trigger.cards); } }, ai: { combo: "jsrglirang", }, }, //朱儁 jsrgfendi: { audio: 2, trigger: { player: "useCardToPlayered" }, filter: function (event, player) { return event.targets.length == 1 && event.card.name == "sha" && event.targets[0].countCards("h") > 0; }, usable: 1, logTarget: "target", content: function () { "step 0"; var target = trigger.target; event.target = target; player .choosePlayerCard(target, "h", true, [1, Infinity], "分敌:展示" + get.translation(target) + "的任意张手牌") .set("ai", button => { if (_status.event.all) return 1; if (ui.selected.buttons.length) return 0; return Math.random(); }) .set( "all", !target.mayHaveShan( player, "use", target.getCards("h", i => { return i.hasGaintag("sha_notshan"); }) ) && Math.random() < 0.75 ) .set("forceAuto", true); ("step 1"); if (result.bool) { var cards = result.cards; target.showCards(cards, get.translation(player) + "对" + get.translation(target) + "发动了【分敌】"); target.addGaintag(cards, "jsrgfendi_tag"); target.addTempSkill("jsrgfendi_blocker"); player.addTempSkill("jsrgfendi_gain"); if (!trigger.card.storage) trigger.card.storage = {}; trigger.card.storage.jsrgfendi = cards.slice(); player.storage.jsrgfendi_gain = target; } else player.storage.counttrigger.jsrgfendi--; }, subSkill: { blocker: { trigger: { player: ["damageBefore", "damageCancelled", "damageZero"], target: ["shaMiss", "useCardToExcluded", "useCardToEnd"], global: ["useCardEnd"], }, forced: true, popup: false, charlotte: true, content: function () { player.removeSkill("jsrgfendi_blocker"); }, mod: { cardEnabled: function (card, player) { if (card.cards) { for (var i of card.cards) { if (!i.hasGaintag("jsrgfendi_tag")) return false; } } else if (get.itemtype(card) == "card") { if (!card.hasGaintag("jsrgfendi_tag")) return false; } }, cardRespondable: function (card, player) { return lib.skill.jsrgfendi.cardEnabled.apply(this, arguments); }, cardSavable: function (card, player) { return lib.skill.jsrgfendi.cardEnabled.apply(this, arguments); }, }, }, gain: { trigger: { global: "damageSource" }, charlotte: true, forced: true, direct: true, onremove: true, filter: function (event, player) { if (!event.card || !event.card.storage) return false; var cards = event.card.storage.jsrgfendi; var target = player.storage.jsrgfendi_gain; if (!cards || !target || !target.isIn()) return false; var cardsx = target.getCards("h"); cardsx.addArray(Array.from(ui.discardPile)); return cards.some(i => cardsx.includes(i)); //target.hasCard(card=>{ // return card.hasGaintag('jsrgfendi_tag'); //},'h'); }, content: function () { var target = player.storage.jsrgfendi_gain; player.logSkill("jsrgfendi_gain", target); var cardsx = target.getCards("h"); cardsx.addArray(Array.from(ui.discardPile)); var cards = trigger.card.storage.jsrgfendi.filter(i => cardsx.includes(i)); player.gain(cards, "give"); }, }, }, }, jsrgjuxiang: { audio: 2, trigger: { player: "gainAfter", global: "loseAsyncAfter", }, filter: function (event, player) { var evt = event.getParent("phaseDraw"); if (evt && evt.name == "phaseDraw") return false; var hs = player.getCards("h"); var cards = event.getg(player).filter(i => hs.includes(i)); if (!cards.length) return false; for (var card of cards) { if (!lib.filter.cardDiscardable(card, player, "jsrgjuxiang")) return false; } return true; }, check: function (event, player) { var target = _status.currentPhase; if (!target || get.attitude(player, target) <= 0) return false; var evt = event.getParent("phaseDiscard"), evt2 = event.getParent("phaseJieshu"); if ((evt && evt.name == "phaseDiscard") || (evt2 && evt.name == "phaseJieshu")) return false; if (target.getCardUsable({ name: "sha" }) >= target.countCards("hs", "sha")) return false; if (!target.hasValueTarget({ name: "sha" })) return false; var hs = player.getCards("h"); var cards = event.getg(player).filter(i => hs.includes(i)); var val = 0; for (var i of cards) val += get.value(i); if (val < 10) return true; return false; }, prompt2: function (event, player) { var hs = player.getCards("h"); var cards = event.getg(player).filter(i => hs.includes(i)); var target = _status.currentPhase; var str = "弃置" + get.translation(cards); if (target && target.isIn()) { var list = []; for (var card of cards) { list.add(get.suit(card, player)); } var num = list.length; str += ",然后令" + get.translation(target) + "于此回合额定的出牌阶段内使用【杀】的次数上限+" + num; } return str; }, content: function () { "step 0"; var hs = player.getCards("h"); var cards = trigger.getg(player).filter(i => hs.includes(i)); var list = []; for (var card of cards) { list.add(get.suit(card, player)); } event.num = list.length; player.discard(cards); ("step 1"); var target = _status.currentPhase; if (target && target.isIn()) { target.addTempSkill("jsrgjuxiang_sha"); target.addMark("jsrgjuxiang_sha", num, false); var evt = trigger.getParent("phaseUse"); if (evt && evt.name == "phaseUse" && !evt.skill) { evt.player.addTempSkill("jsrgjuxiang_buff", "phaseUseAfter"); evt.player.addMark("jsrgjuxiang_buff", num, false); } } }, subSkill: { sha: { trigger: { global: "phaseUseBegin" }, filter: function (event, player) { return !event.skill; }, silent: true, charlotte: true, forced: true, onremove: true, content: function () { trigger.player.addTempSkill("jsrgjuxiang_buff", "phaseUseAfter"); trigger.player.addMark("jsrgjuxiang_buff", player.countMark("jsrgjuxiang_sha"), false); }, }, buff: { charlotte: true, intro: { content: "使用【杀】的次数上限+#" }, onremove: true, mod: { cardUsable: function (card, player, num) { if (card.name == "sha") return num + player.countMark("jsrgjuxiang_buff"); }, }, }, }, }, //刘备 jsrgjishan: { audio: 2, trigger: { global: "damageBegin4" }, usable: 1, filter: function (event, player) { return player.hp > 0; }, logTarget: "player", onremove: true, prompt2: "失去1点体力并防止此伤害,然后你与其各摸一张牌", check: function (event, player) { return get.damageEffect(event.player, event.source, _status.event.player, event.nature) * event.num < get.effect(player, { name: "losehp" }, player, _status.event.player) + get.effect(player, { name: "draw" }, player, _status.event.player) + get.effect(event.player, { name: "draw" }, player, _status.event.player) / 2; }, group: "jsrgjishan_recover", content: function () { "step 0"; trigger.cancel(); player.loseHp(); player.markAuto("jsrgjishan", [trigger.player]); ("step 1"); if (player.isIn() && trigger.player.isIn()) { var targets = [player, trigger.player]; targets.sortBySeat(_status.currentPhase); targets[0].draw("nodelay"); targets[1].draw(); } }, intro: { content: "已帮助$抵挡过伤害" }, ai: { expose: 0.2 }, subSkill: { recover: { audio: "jsrgjishan", trigger: { source: "damageSource" }, filter: function (event, player) { return game.hasPlayer(current => { return current.isMinHp() && player.getStorage("jsrgjishan").includes(current); }); }, usable: 1, direct: true, content: function () { "step 0"; player .chooseTarget(get.prompt("jsrgjishan_recover"), "令一名体力值最小且你对其发动过〖积善①〗的角色回复1点体力", (card, player, target) => { return target.isMinHp() && player.getStorage("jsrgjishan").includes(target); }) .set("ai", target => { return get.recoverEffect(target, _status.event.player, _status.event.player); }); ("step 1"); if (result.bool) { var target = result.targets[0]; player.logSkill("jsrgjishan_recover", target); target.recover(); } else player.storage.counttrigger.jsrgjishan_recover--; }, }, }, }, jsrgzhenqiao: { audio: 2, trigger: { player: "useCardToTargeted" }, forced: true, shaRelated: true, filter: function (event, player) { return event.isFirstTarget && event.card.name == "sha" && player.hasEmptySlot(1); }, content: function () { // trigger.getParent().targets=trigger.getParent().targets.concat(trigger.targets); // trigger.getParent().triggeredTargets4=trigger.getParent().triggeredTargets4.concat(trigger.targets); trigger.getParent().effectCount++; }, mod: { attackRange: function (player, num) { return num + 1; }, aiOrder: (player, card, num) => { if (num > 0 && get.itemtype(card) === "card" && get.subtype(card) === "equip1" && !player.getEquip(1)) { if ( card.name !== "zhuge" || player.getCardUsable("sha") || !player.needsToDiscard() || player.countCards("hs", i => { return get.name(i) === "sha" && lib.filter.cardEnabled(i, player); }) < 2 ) return 0; } }, aiValue: (player, card, num) => { if (num > 0 && get.itemtype(card) === "card" && card.name !== "zhuge" && get.subtype(card) === "equip1" && !player.getEquip(1)) return 0.01 * num; }, aiUseful: () => { return lib.skill.jsrgzhenqiao.mod.aiValue.apply(this, arguments); }, }, }, //王允 jsrgshelun: { audio: 2, enable: "phaseUse", usable: 1, filter: function (event, player) { return game.hasPlayer(current => player.inRange(current)); }, filterTarget: function (card, player, target) { return player.inRange(target); }, content: function () { var num = player.countCards("h"); var targets = game.filterPlayer(current => { return current.countCards("h") <= num && current != target; }); player .chooseToDebate(targets) .set("callback", function () { var result = event.debateResult; if (result.bool && result.opinion) { var opinion = result.opinion; var target = event.getParent(2).target; if (opinion == "red") player.discardPlayerCard(target, "he", true); else target.damage(); } }) .set("ai", card => { var player = _status.event.player; var color = player == _status.event.source || get.damageEffect(_status.event.getParent(2).target, player, player) > 0 ? "black" : "red"; var val = 5 - get.value(card); if (get.color(card) == color) val += 10; return val; }) .set("aiCard", target => { var color = target == _status.event.source || get.damageEffect(_status.event.getParent(2).target, target, target) > 0 ? "black" : "red"; var hs = target.getCards("h", { color: color }); if (!hs.length) hs = target.getCards("h"); return { bool: true, cards: [hs.randomGet()] }; }) .set("target", target); }, ai: { order: 8, expose: 0.2, result: { target: -1 }, }, }, jsrgfayi: { audio: 2, trigger: { global: "chooseToDebateAfter" }, filter: function (event, player) { if (!event.targets.includes(player)) return false; if (event.red.map(i => i[0]).includes(player)) return event.black.length; if (event.black.map(i => i[0]).includes(player)) return event.red.length; return false; }, direct: true, content: function () { "step 0"; var targets = []; if (trigger.red.map(i => i[0]).includes(player)) targets = trigger.black; if (trigger.black.map(i => i[0]).includes(player)) targets = trigger.red; player .chooseTarget(get.prompt("jsrgfayi"), "对一名与你意见不同的角色造成1点伤害", (card, player, target) => { return _status.event.targets.includes(target); }) .set( "targets", targets.map(i => i[0]) ) .set("ai", target => { var player = _status.event.player; return get.damageEffect(target, player, player); }); ("step 1"); if (result.bool) { var target = result.targets[0]; player.logSkill("jsrgfayi", target); target.damage(); } }, }, jsrgtushe: { audio: "xinfu_tushe", mod: { aiOrder(player, card, num) { if (get.tag(card, "multitarget")) { if (player.countCards("h", { type: "basic" })) return num / 10; return num * 10; } if (get.type(card) === "basic") return num + 10; }, aiValue(player, card, num) { if (card.name === "zhangba") { let fact = n => { if (n > 1) return n * fact(n - 1); return 1; }, basic = 0; return fact( Math.min( player.countCards("hs", i => { if (get.tag(i, "multitarget")) return 2; if (!["shan", "tao", "jiu"].includes(card.name)) return 1; basic++; }) / (1 + basic), player.getCardUsable("sha") ) ); } if (["shan", "tao", "jiu"].includes(card.name)) { if (player.getEquip("zhangba") && player.countCards("hs") > 1) return 0.01; return num / 2; } if (get.tag(card, "multitarget")) return num + game.players.length; }, aiUseful(player, card, num) { if (get.name(card, player) === "shan") { if ( player.countCards("hs", i => { if (card === i || (card.cards && card.cards.includes(i))) return false; return get.name(i, player) === "shan"; }) ) return -1; return num / Math.pow(Math.max(1, player.hp), 2); } }, }, trigger: { player: "useCardToPlayered", }, filter: function (event, player) { if (get.type(event.card) == "equip") return false; if (event.getParent().triggeredTargets3.length > 1) return false; return event.targets.length > 0; }, check: function (event, player) { return !player.countCards("h", { type: "basic" }); }, locked: false, content: function () { "step 0"; player.showHandcards(); ("step 1"); if (player.countCards("h", { type: "basic" })) event.finish(); else player.chooseBool("图射:是否摸" + get.cnNumber(trigger.targets.length) + "张牌?").set("ai", () => 1); ("step 2"); if (result.bool) { player.draw(trigger.targets.length); } }, ai: { presha: true, pretao: true, threaten: 1.8, effect: { player_use(card, player, target) { if ( typeof card === "object" && card.name !== "shan" && get.type(card) !== "equip" && !player.countCards("h", i => { if (card === i || (card.cards && card.cards.includes(i))) return false; return get.type(i) === "basic"; }) ) { let targets = [], evt = _status.event.getParent("useCard"); targets.addArray(ui.selected.targets); if (evt && evt.card == card) targets.addArray(evt.targets); if (targets.length) return [1, targets.length]; if (get.tag(card, "multitarget")) return [1, game.players.length - 1]; return [1, 1]; } }, }, }, }, jsrgtongjue: { audio: 2, enable: "phaseUse", usable: 1, zhuSkill: true, filter: function (event, player) { return player.hasZhuSkill("jsrgtongjue") && game.hasPlayer(current => current != player && current.group == "qun"); }, filterCard: true, selectCard: [1, Infinity], filterTarget: function (card, player, target) { return target != player && target.group == "qun"; }, selectTarget: [1, Infinity], filterOk: function () { return ui.selected.cards.length == ui.selected.targets.length; }, check: function (card) { var player = _status.event.player; if ( player.hasCard(card => { return player.hasValueTarget(card); }, "hs") ) { return 3 - player.getUseValue(card); } return 3 - get.value(card); }, multiline: true, multitarget: true, delay: false, discard: false, lose: false, content: function () { "step 0"; var list = []; for (var i = 0; i < targets.length; i++) { var target = targets[i]; var card = cards[i]; list.push([target, card]); } game.loseAsync({ gain_list: list, player: player, cards: cards, giver: player, animate: "giveAuto", }).setContent("gaincardMultiple"); ("step 1"); player.addTempSkill("jsrgtongjue_blocker"); player.markAuto("jsrgtongjue_blocker", targets); }, ai: { order: 5, result: { target: 1, }, }, subSkill: { blocker: { charlotte: true, onremove: true, mod: { playerEnabled: function (card, player, target) { if (player.getStorage("jsrgtongjue_blocker").includes(target)) return false; }, }, mark: true, intro: { content: "$已经立牧自居,不可接近" }, }, }, }, //404曹操 jsrgzhenglve: { audio: 2, trigger: { global: "phaseEnd" }, filter: function (event, player) { var zhu = get.zhu(player) || game.findPlayer(current => current.getSeatNum() == 1); return event.player == zhu; }, locked: false, group: "jsrgzhenglve_damage", prompt2: function (event, player) { var num = Math.min( event.player.getHistory("sourceDamage").length > 0 ? 1 : 2, game.countPlayer(current => { return !current.hasMark("jsrgzhenglve_mark"); }) ); if (num == 0) return "你可以摸一张牌"; return "你可以摸一张牌并令" + get.cnNumber(num) + "名角色获得“猎”标记"; }, content: function () { "step 0"; player.draw(); ("step 1"); var damaged = trigger.player.getHistory("sourceDamage").length > 0; var num = damaged ? 1 : 2; var targets = game.filterPlayer(current => { return !current.hasMark("jsrgzhenglve_mark"); }); if (!targets.length) event.finish(); else if (targets.length <= num) event._result = { bool: true, targets: targets }; else player .chooseTarget("令" + (num > 1 ? "至多" : "") + get.cnNumber(num) + "名角色获得“猎”标记", true, [1, num], (card, player, target) => { return !target.hasMark("jsrgzhenglve_mark"); }) .set("ai", target => { var att = get.attitude(_status.event.player, target); return 100 - att; }); ("step 2"); if (result.bool) { var targets = result.targets; player.line(targets); targets.forEach(i => i.addMark("jsrgzhenglve_mark", 1)); } }, mod: { cardUsableTarget: function (card, player, target) { if (target.hasMark("jsrgzhenglve_mark")) return true; }, targetInRange: function (card, player, target) { if (target.hasMark("jsrgzhenglve_mark")) return true; }, }, subSkill: { damage: { audio: "jsrgzhenglve", trigger: { source: "damageSource" }, usable: 1, filter: function (event, player) { return event.player.hasMark("jsrgzhenglve_mark"); }, prompt2: function (event, player) { var cards = event.cards || []; return "摸一张牌" + (cards.filterInD().length ? "并获得" + get.translation(event.cards.filterInD()) : ""); }, content: function () { "step 0"; player.draw(); var cards = trigger.cards; if (cards && cards.filterInD().length) { player.gain(cards.filterInD(), "gain2"); } }, }, mark: { marktext: "猎", intro: { name: "猎(政略)", name2: "猎", markcount: () => 0, content: "已拥有“猎”标记", }, }, }, }, jsrghuilie: { audio: 2, trigger: { player: "phaseZhunbeiBegin" }, juexingji: true, forced: true, skillAnimation: true, animationColor: "thunder", derivation: ["jsrgpingrong", "feiying"], filter: function (event, player) { return game.countPlayer(current => current.hasMark("jsrgzhenglve_mark")) > 2; }, content: function () { "step 0"; player.awakenSkill("jsrghuilie"); player.loseMaxHp(); ("step 1"); player.addSkills(["jsrgpingrong", "feiying"]); }, ai: { combo: "jsrgzhenglve", }, }, jsrgpingrong: { audio: 2, trigger: { global: "phaseEnd" }, filter: function (event, player) { return !player.hasSkill("jsrgpingrong_used") && game.hasPlayer(current => current.hasMark("jsrgzhenglve_mark")); }, direct: true, content: function () { "step 0"; player .chooseTarget(get.prompt("jsrghuilie"), "移去一名角色的“猎”,然后你执行一个额外回合。若你在此额外回合内未造成伤害,则你失去1点体力。", (card, player, target) => { return target.hasMark("jsrgzhenglve_mark"); }) .set("ai", target => { return get.attitude(_status.event.player, target); }); ("step 1"); if (result.bool) { var target = result.targets[0]; player.logSkill("jsrgpingrong", target); player.addTempSkill("jsrgpingrong_used", "roundStart"); target.removeMark("jsrgzhenglve_mark", target.countMark("jsrgzhenglve_mark")); player.insertPhase(); player.addSkill("jsrgpingrong_check"); } }, subSkill: { used: { charlotte: true }, check: { audio: "jsrgpingrong", trigger: { player: "phaseAfter" }, charlotte: true, forced: true, filter: function (event, player) { return event.skill == "jsrgpingrong" && !player.getHistory("sourceDamage").length; }, content: function () { player.loseHp(); }, }, }, ai: { combo: "jsrgzhenglve", }, }, //南华老仙 jsrgshoushu: { audio: 2, forced: true, trigger: { //player:'enterGame', //global:'phaseBefore', global: "roundStart", }, filter: function (event, player) { if ( game.hasPlayer(function (current) { return current.countCards("hej", "taipingyaoshu"); }) ) return false; return true; //return event.name!='phase'||game.phaseNumber==0; }, direct: true, group: "jsrgshoushu_destroy", content: function () { "step 0"; player .chooseTarget(get.prompt("jsrgshoushu"), "将【太平要术】置入一名角色的装备区", (card, player, target) => { var card = { name: "taipingyaoshu" }; return target.canEquip(card, true); }) .set("ai", target => { return target.getUseValue({ name: "taipingyaoshu" }) * get.attitude(_status.event.player, target); }); ("step 1"); if (result.bool) { var target = result.targets[0]; event.target = target; player.logSkill("jsrgshoushu", target); if (!lib.inpile.includes("taipingyaoshu")) { lib.inpile.push("taipingyaoshu"); } event.card = game.createCard2("taipingyaoshu", "heart", 3); } else event.finish(); ("step 2"); if (card) target.equip(card); }, subSkill: { destroy: { audio: "jsrgshoushu", trigger: { global: ["loseEnd", "equipEnd", "addJudgeEnd", "gainEnd", "loseAsyncEnd", "addToExpansionEnd"], }, forced: true, filter: function (event, player) { return game.hasPlayer(current => { var evt = event.getl(current); if (evt && evt.es) return evt.es.some(i => i.name == "taipingyaoshu"); return false; }); }, content: function () { var cards = []; game.countPlayer(current => { var evt = trigger.getl(current); if (evt && evt.es) return cards.addArray(evt.es.filter(i => i.name == "taipingyaoshu")); }); game.cardsGotoSpecial(cards); game.log(cards, "被销毁了"); }, }, }, }, jsrgxundao: { audio: 2, trigger: { player: "judge" }, filter: function (event, player) { return game.hasPlayer(current => current.countCards("he")); }, direct: true, content: function () { "step 0"; var prompt2 = get.translation(player) + "(你)的" + (trigger.judgestr || "") + "判定为" + get.translation(player.judging[0]) + "," + "是否令至多两名角色依次弃置一张牌,然后选择其中一张作为新判定牌?"; player .chooseTarget(get.prompt("jsrgxundao"), prompt2, [1, 2], (card, player, target) => { return target.countCards("he"); }) .set("ai", target => { var player = _status.event.player; if (!_status.event.todiscard) return 0; if (_status.event.todiscard != "all") { if (target == _status.event.todiscard) return 100; } return get.effect(target, { name: "guohe_copy2" }, player, player) / 2; }) .set( "todiscard", (function () { if (trigger.judgestr == "闪电" && get.damageEffect(player, null, player, "thunder") >= 0) return "all"; var friends = game.filterPlayer(i => get.attitude(i, player) > 0); for (var friend of friends) { var cardsx = friend.getCards("he", card => trigger.judge(card) > 0); cardsx.sort((a, b) => { return get.value(a) - get.value(b); }); if (cardsx.length) { var card = cardsx[0]; if (trigger.judge(player.judging[0]) >= 0) { if (get.value(card) > 4) return false; } return get.owner(card); } } return "all"; })() ); ("step 1"); if (result.bool) { var targets = result.targets; targets.sortBySeat(_status.currentPhase); event.targets = targets; player.logSkill("jsrgxundao", targets); event.cards = []; } else event.finish(); ("step 2"); var target = targets.shift(); target.chooseToDiscard("寻道:请弃置一张牌" + (target == player ? "" : ",可能被作为新判定牌"), "he", true).set("ai", card => { var trigger = _status.event.getTrigger(); var player = _status.event.player; var judging = _status.event.judging; var result = trigger.judge(card) - trigger.judge(judging); var attitude = get.attitude(player, trigger.player); if (attitude == 0 || result == 0) return 0.1; if (attitude > 0) { return result + 0.01; } else { return 0.01 - result; } }); ("step 3"); if (result.bool) { event.cards.addArray(result.cards); } if (targets.length) event.goto(2); ("step 4"); var cards = event.cards.filterInD("d"); if (cards.length) { player.chooseButton(["寻道:选择一张作为新判定牌", cards], true).set("ai", button => { return trigger.judge(button.link); }); } else event.finish(); ("step 5"); if (result.bool) { var card = result.links[0]; event.card = card; game.cardsGotoOrdering(card).relatedEvent = trigger; } else event.finish(); ("step 6"); if (player.judging[0].clone) { game.broadcastAll( function (card, card2, player) { if (card.clone) { card.clone.classList.remove("thrownhighlight"); } var node = player.$throwordered(card2.copy(), true); node.classList.add("thrownhighlight"); ui.arena.classList.add("thrownhighlight"); }, player.judging[0], card, player ); game.addVideo("deletenode", player, get.cardsInfo([player.judging[0].clone])); } game.cardsDiscard(player.judging[0]); player.judging[0] = card; trigger.orderingCards.add(card); game.log(player, "的判定牌改为", card); game.delay(2); }, ai: { rejudge: true, tag: { rejudge: 1, }, }, }, jsrglinghua: { audio: 2, trigger: { player: ["phaseZhunbeiBegin", "phaseJieshuBegin"], }, prompt2: function (event, player) { var zhunbei = event.name == "phaseZhunbei"; return "进行目标为你" + (zhunbei ? "" : "且效果反转") + "的【闪电】判定。若你未因此受到伤害,你可以" + (zhunbei ? "令一名角色回复1点体力" : "对一名角色造成1点雷电伤害"); }, check: function (event, player) { var e2 = player.getEquip(2); if (e2 && e2.name == "taipingyaoshu") return true; if ( event.name == "phaseZhunbei" && game.hasPlayer(current => { return get.recoverEffect(current, player, player) >= 0; }) ) return true; if ( event.name == "phaseJieshu" && game.hasPlayer(current => { return get.damageEffect(current, player, player, "thunder") >= 0; }) && player.hasSkillTag("rejudge") && player.hasCard(card => { return lib.card.shandian.judge(card) < 0; }, "he") ) return true; return false; }, content: function () { "step 0"; var next = (event.executeDelayCardEffect = player.executeDelayCardEffect("shandian")); if (event.triggername != "phaseJieshuBegin") return; next.judge = card => -lib.card.shandian.judge(card) - 4; next.judge2 = result => !lib.card.shandian.judge2(result); ("step 1"); var executeDelayCardEffect = event.executeDelayCardEffect; if (!player.hasHistory("damage", evt => evt.getParent(2) == executeDelayCardEffect)) { if (trigger.name == "phaseZhunbei") { player.chooseTarget("灵化:是否令一名角色回复1点体力?").set("ai", target => { var player = _status.event.player; return get.recoverEffect(target, player, player); }); } else { player.chooseTarget("灵化:是否对一名角色造成1点雷电伤害?").set("ai", target => { var player = _status.event.player; return get.damageEffect(target, player, player, "thunder"); }); } } else event.finish(); ("step 2"); if (result.bool) { var target = result.targets[0]; player.line(target); if (trigger.name == "phaseZhunbei") target.recover(); else target.damage("thunder"); } }, ai: { threaten: 2.8, }, }, }; export default skills;