noname/character/jsrg/skill.js

9678 lines
286 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { lib, game, ui, get, ai, _status } from "../../noname.js";
/** @type { importCharacterConfig['skill'] } */
const skills = {
//江山如故·衰
//卢植
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 && current.hp <= 2) {
const att = get.attitude(player, current);
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)));
});
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()) break;
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 += "<li>至" + 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 += "<li>至" + 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 = `<span style="text-decoration: line-through;">${item}</span>`;
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([
`<div class="text center">${get.translation(target)}</div>`,
[
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")}###将一张牌当【杀】使用,且当一名角色受到此【杀】伤害时,此伤害+XX为其本回合回复过的体力值`);
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 ? "<br>或" : ""}${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(['<div class="text center">' + get.translation(target) + "的武器牌</div>", 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) + '###<div class="text center">' + str + "</div>", [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("<li>当前可用技能:" + 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('<div class="text center">如果移去' + get.translation(drawers) + ",则你摸一张牌</div>");
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", '<span class="thundertext">' + trigger.skillwarn + "。</span>" + 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(['###评鉴:移去一名访客###<div class="text center">若移去的访客为' + get.translation(current) + ",则你摸一张牌</div>", [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;