diff --git a/audio/die/dc_sb_zhugejin.mp3 b/audio/die/dc_sb_zhugejin.mp3 new file mode 100644 index 000000000..3ebfa8e10 Binary files /dev/null and b/audio/die/dc_sb_zhugejin.mp3 differ diff --git a/audio/die/star_zhangchunhua.mp3 b/audio/die/star_zhangchunhua.mp3 new file mode 100644 index 000000000..3c4abc393 Binary files /dev/null and b/audio/die/star_zhangchunhua.mp3 differ diff --git a/audio/skill/dcsbhoude1.mp3 b/audio/skill/dcsbhoude1.mp3 new file mode 100644 index 000000000..a4d26bf61 Binary files /dev/null and b/audio/skill/dcsbhoude1.mp3 differ diff --git a/audio/skill/dcsbhoude2.mp3 b/audio/skill/dcsbhoude2.mp3 new file mode 100644 index 000000000..f9277c3e8 Binary files /dev/null and b/audio/skill/dcsbhoude2.mp3 differ diff --git a/audio/skill/dcsbtaozhou1.mp3 b/audio/skill/dcsbtaozhou1.mp3 new file mode 100644 index 000000000..a55027d76 Binary files /dev/null and b/audio/skill/dcsbtaozhou1.mp3 differ diff --git a/audio/skill/dcsbtaozhou2.mp3 b/audio/skill/dcsbtaozhou2.mp3 new file mode 100644 index 000000000..85d25a4a1 Binary files /dev/null and b/audio/skill/dcsbtaozhou2.mp3 differ diff --git a/audio/skill/starliangyan1.mp3 b/audio/skill/starliangyan1.mp3 new file mode 100644 index 000000000..d11dc6b2e Binary files /dev/null and b/audio/skill/starliangyan1.mp3 differ diff --git a/audio/skill/starliangyan2.mp3 b/audio/skill/starliangyan2.mp3 new file mode 100644 index 000000000..57b6712e4 Binary files /dev/null and b/audio/skill/starliangyan2.mp3 differ diff --git a/audio/skill/starminghui1.mp3 b/audio/skill/starminghui1.mp3 new file mode 100644 index 000000000..d5ff9dda7 Binary files /dev/null and b/audio/skill/starminghui1.mp3 differ diff --git a/audio/skill/starminghui2.mp3 b/audio/skill/starminghui2.mp3 new file mode 100644 index 000000000..3acb235d5 Binary files /dev/null and b/audio/skill/starminghui2.mp3 differ diff --git a/character/huicui/skill.js b/character/huicui/skill.js index c1e249da4..bbe5a0e0b 100644 --- a/character/huicui/skill.js +++ b/character/huicui/skill.js @@ -33,6 +33,9 @@ const skills = { cardDiscardable(card, player) { if (get.position(card) == "h") return false; }, + canBeDiscarded(card, player) { + if (get.position(card) == "h") return false; + }, }, group: "dctunchu_limit", subSkill: { diff --git a/character/huicui/translate.js b/character/huicui/translate.js index 8bf97bdf0..13b0030af 100644 --- a/character/huicui/translate.js +++ b/character/huicui/translate.js @@ -532,9 +532,9 @@ const translates = { dc_lifeng: "李丰", dctunchu: "囤储", //dctunchu_info: "锁定技。①你的起始手牌数为游戏人数的四倍。②你的手牌不能被弃置。③准备阶段,若你的手牌数大于你的体力上限,则你本回合至多使用三张牌。", - dctunchu_info: "锁定技。①游戏开始时,你将手牌数摸至游戏人数的四倍。②你的手牌不能被弃置。③准备阶段,若你的手牌数大于你的体力上限,则你本回合至多使用三张牌。", + dctunchu_info: "锁定技。①游戏开始时,你将手牌数摸至游戏人数的四倍。②你的手牌不能被弃置。③准备阶段,若你的手牌数大于你的体力值,则你本回合至多使用三张牌。", dcshuliang: "输粮", - dcshuliang_info: "一名角色的回合结束时,你可以将任意张手牌交给任意名没有手牌的角色各一张,然后本次获得可以指定自己为目标的牌的角色可以依次选择是否选择本次获得的牌。", + dcshuliang_info: "一名角色的回合结束时,你可以将任意张手牌交给任意名没有手牌的角色各一张,然后本次获得可以指定自己为目标的牌的角色可以依次选择是否使用本次获得的牌。", }; export default translates; diff --git a/character/mobile/character.js b/character/mobile/character.js index 30230b694..ef86716c0 100644 --- a/character/mobile/character.js +++ b/character/mobile/character.js @@ -1,4 +1,5 @@ const characters = { + mb_simafu: ["male", "wei", 3, ["mbpanxiang", "mbchenjie"]], mb_sp_guanqiujian: ["male", "wei", 4, ["mbcuizhen", "mbkuili"]], mb_caomao: ["male", "wei", 3, ["mbqianlong", "mbweitong"], ["zhu"]], chengji: ["male", "wei", 4, ["mbkuangli", "mbxiongsi"]], @@ -57,7 +58,6 @@ const characters = { sunhanhua: ["female", "wu", 3, ["chongxu", "miaojian", "shhlianhua"]], yanpu: ["male", "qun", 3, ["huantu", "bihuo"]], mayuanyi: ["male", "qun", 4, ["jibing", "wangjing", "moucuan"]], - simafu: ["male", "wei", 3, ["xunde", "chenjie"]], fuqian: ["male", "shu", 4, ["jueyong", "poxiang"]], xin_caozhen: ["male", "wei", 4, ["discretesidi"]], xin_sunluban: ["female", "wu", 3, ["xinzenhui", "xinjiaojin"]], diff --git a/character/mobile/characterReplace.js b/character/mobile/characterReplace.js index 3b0e878c4..45a2cf5ad 100644 --- a/character/mobile/characterReplace.js +++ b/character/mobile/characterReplace.js @@ -17,6 +17,8 @@ const characterReplaces = { qiaozhou: ["yj_qiaozhou", "qiaozhou"], sunhanhua: ["dc_sunhanhua", "sunhanhua"], zhoubuyi: ["zhoubuyi", "yj_zhoubuyi"], + xianglang: ["xianglang", "mb_xianglang"], + miheng: ["re_miheng", "miheng"], }; export default characterReplaces; diff --git a/character/mobile/dynamicTranslate.js b/character/mobile/dynamicTranslate.js index 19e072036..8a346ac76 100644 --- a/character/mobile/dynamicTranslate.js +++ b/character/mobile/dynamicTranslate.js @@ -30,8 +30,8 @@ const dynamicTranslates = { const xuetu = player.storage.mbxuetu, status = player.countMark("mbxuetu_status"); if (status === 0) { - if (!xuetu) return '转换技。出牌阶段限一次,阴:你可以弃置一张牌,然后令一名角色回复1点体力;阳:你可以失去1点体力,然后令一名角色摸两张牌。'; - return '转换技。出牌阶段限一次,阴:你可以弃置一张牌,然后令一名角色回复1点体力;阳:你可以失去1点体力,然后令一名角色摸两张牌。'; + if (!xuetu) return '转换技。出牌阶段限一次,阴:你可以令一名角色回复1点体力;阳:你可以令一名角色摸两张牌。'; + return '转换技。出牌阶段限一次,阴:你可以令一名角色回复1点体力;阳:你可以令一名角色摸两张牌。'; } else if (status === 1) { return lib.translate.mbxuetu_achieve_info; } else { diff --git a/character/mobile/skill.js b/character/mobile/skill.js index 15e492007..235f6558a 100644 --- a/character/mobile/skill.js +++ b/character/mobile/skill.js @@ -2,6 +2,124 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { + //新司马孚 + mbpanxiang: { + audio: 2, + trigger: { + global: "damageBegin3", + }, + async cost(event, trigger, player) { + const { player: target, source, card } = trigger; + const [SUB, ADD] = ["减伤", "加伤"]; + const list = ["减伤", "加伤"].filter(text => text !== (player.storage.mbpanxiang || {})[target.playerid]); + list.push("cancel2"); + let prompt = `${get.translation(target)}即将受到${source ? "来自" + get.translation(source) : "无来源"}的${trigger.num}点伤害,你可以选择一项:`; + const choiceTexts = [`⒈令此伤害-1${source && source.isIn() ? "," + get.translation(source) + "摸两张牌" : ""};`, `⒉令此伤害+1,${get.translation(target)}摸三张牌。`]; + if (!list.includes(SUB)) choiceTexts[0] = `${choiceTexts[0]}(上次选过)`; + if (!list.includes(ADD)) choiceTexts[1] = `${choiceTexts[1]}(上次选过)`; + choiceTexts.forEach(text => prompt += text); + const result = await player + .chooseControl(list) + .set("prompt", get.prompt("mbpanxiang", target)) + .set("prompt2", prompt) + .set("ai", () => { + return get.event("choice"); + }) + .set( + "choice", + (() => { + const damageEff = get.damageEffect(target, source, player); + const att = get.attitude(player, target), + attSource = get.attitude(player, source); + const canFilterDamage = target.hasSkillTag("filterDamage", null, { + player: source, + card, + }); + if (list.includes(ADD)) { + if (damageEff > 0) { + if (!canFilterDamage && target.getHp() <= trigger.num + 1) return ADD; + } else { + if (att > 0 && (damageEff === 0 || canFilterDamage)) return ADD; + if ( + target.getHp() + + target.countCards("hs", card => { + return target.canSaveCard(card, target); + }) > + trigger.num + 1 && + !list.includes(SUB) + ) + return ADD; + } + } + if (list.includes(SUB)) { + if (att > 0 && attSource > 0) return SUB; + if (canFilterDamage && att > 0) return "cancel2"; + if (damageEff > 0) { + if (target.getHp() > trigger.num && attSource > 0 && source.countCards("h") + source.getHp() <= 4) return SUB; + } else { + if (att > 0) { + if (trigger.num >= target.getHp()) return SUB; + if ( + !source.countCards("hs", card => { + return source.canUse(card, target, true) && get.effect(target, card, source, player) > 0; + }) + ) + return Math.random() < 0.7 ? ADD : "cancel2"; + } else { + if (attSource > 0) return SUB; + if (target.hasSkillTag("maixie") && trigger.num === 1 && damageEff < -20) return SUB; + } + } + } + return "cancel2"; + })() + ) + .forResult(); + if (result.control !== "cancel2") { + event.result = { + bool: true, + cost_data: { + control: result.control, + }, + }; + } + }, + logTarget: "player", + onremove: true, + async content(event, trigger, player) { + const { control } = event.cost_data; + const { player: target, source } = trigger; + if (!player.storage.mbpanxiang) player.storage.mbpanxiang = {}; + player.storage.mbpanxiang[target.playerid] = control; + if (control === "减伤") { + trigger.num--; + game.log(player, "令此伤害", "#y-1"); + if (source && source.isIn()) await source.draw(2); + } else { + trigger.num++; + game.log(player, "令此伤害", "#y+1"); + await target.draw(3); + } + }, + }, + mbchenjie: { + audio: 2, + trigger: { global: "dieAfter" }, + filter(event, player) { + return ( + player.hasSkill("mbpanxiang", null, false, false) && + player.hasHistory("useSkill", evt => { + return evt.skill === "mbpanxiang" && evt.targets.includes(event.player); + }) + ); + }, + forced: true, + async content(event, trigger, player) { + const cards = player.getCards("hej", card => lib.filter.cardDiscardable(card, player, "mbchenjie")); + if (cards.length) await player.discard(cards); + await player.draw(4); + }, + }, //李昭焦伯 mbzuoyou: { audio: 2, @@ -812,86 +930,117 @@ const skills = { usable: 2, filter(event, player) { if (player.countMark("mbxuetu_status") !== 1 && player.getStat("skill").mbxuetu) return false; - if (!player.storage.mbxuetu) return player.countCards("he"); return true; }, zhuanhuanji2(skill, player) { return player.countMark("mbxuetu_status") !== 1; }, - filterCard(card, player) { - if (player.countMark("mbxuetu_status") > 1) return false; - if (player.countMark("mbxuetu_status") === 1) { - if (player.getStorage("mbxuetu_used").includes(false)) return false; - return true; - } - return !player.storage.mbxuetu; - }, - selectCard() { - const player = get.player(); - if (player.countMark("mbxuetu_status") > 1) return -1; - if (player.countMark("mbxuetu_status") === 1) { - if (player.getStorage("mbxuetu_used").includes(false)) return -1; - if (player.getStorage("mbxuetu_used").includes(true)) return 1; - return [0, 1]; - } - return !player.storage.mbxuetu ? 1 : -1; - }, - check(card) { - return 6 - get.value(card); - }, - prompt() { - const player = get.player(), - storage = player.storage.mbxuetu, - status = player.countMark("mbxuetu_status"); - if (status === 0) { - if (storage) return "转换技。出牌阶段限一次,你可以失去1点体力,然后令一名角色摸两张牌。"; - return "转换技。出牌阶段限一次,你可以弃置一张牌,然后令一名角色回复1点体力。"; - } else if (status === 1) { - return "出牌阶段各限一次。⒈你可以弃置一张牌,然后令一名角色回复1点体力;⒉你可以失去1点体力,然后令一名角色摸两张牌。"; - } else { - if (storage) return "转换技。出牌阶段限一次,你可以摸一张牌,然后对一名角色造成1点伤害。"; - return "转换技。出牌阶段限一次,你可以回复1点体力,然后令一名角色弃置两张牌。"; - } - }, position: "he", - filterTarget: true, onremove: ["mbxuetu", "mbxuetu_status"], derivation: ["mbxuetu_achieve", "mbxuetu_fail"], - async content(event, trigger, player) { - const target = event.targets[0], - storage = Boolean(player.storage.mbxuetu); - const status = player.countMark("mbxuetu_status"); - player.changeZhuanhuanji("mbxuetu"); - if (status < 2) { - if (!player.storage.mbxuetu_used) { - player.when(["phaseUseAfter", "mbweiming_achieveAfter"]).then(() => { - delete player.storage.mbxuetu_used; + + chooseButton: { + dialog() { + const dialog = ui.create.dialog("###血途###请选择要执行的项"); + dialog.direct = true; + return dialog; + }, + chooseControl(event, player) { + let list = ["令一名角色回复1点体力", "令一名角色摸两张牌"]; + if (player.countMark("mbxuetu_status") !== 1) { + list[player.storage.mbxuetu ? "shift" : "pop"](); + } else { + list = list.filter((choice, index) => { + return !player.getStorage("mbxuetu_used").includes(index); }); } - player.markAuto("mbxuetu_used", [status === 0 ? storage : !event.cards.length]); - if ((status === 0 && !storage) || (status === 1 && event.cards.length)) { - await target.recover(); + list.push("cancel2"); + return list; + }, + check() { + return get.event("controls")[0]; + }, + backup(result, player) { + return { + audio: "mbxuetu", + choice: result.control.includes("回复") ? 0 : 1, + filterCard: () => false, + selectCard: -1, + filterTarget: true, + async content(event, trigger, player) { + const { choice } = get.info("mbxuetu_backup"); + const target = event.targets[0]; + const status = player.countMark("mbxuetu_status"); + player.changeZhuanhuanji("mbxuetu"); + if (status < 2) { + if (!player.storage.mbxuetu_used) { + player.when(["phaseUseAfter", "mbweiming_achieveAfter"]).then(() => { + delete player.storage.mbxuetu_used; + }); + } + player.markAuto("mbxuetu_used", [choice]); + if (!choice) { + await target.recover(); + } else { + await target.draw(2); + } + } else { + if (!choice) { + await player.recover(); + await target.chooseToDiscard(2, true, "he"); + } else { + await player.draw(); + await target.damage(); + } + } + }, + ai: { + result: { + target(player, target) { + const { choice } = get.info("mbxuetu_backup"); + const status = player.countMark("mbxuetu_status"); + if (status > 1) { + if (player.storage.mbxuetu) return -get.damageEffect(target, player, player) / 10; + return -2; + } + if (choice === 1) return 2; + const eff = get.recoverEffect(target, player, player); + return eff > 0 ? 2 : eff < 0 ? -get.sgnAttitude(player, target) : 0; + }, + player(player, target) { + const status = player.countMark("mbxuetu_status"); + if (status > 1) { + if (player.storage.mbxuetu) return 1; + return get.recoverEffect(player, player) / 6; + } + return 0; + }, + }, + }, + }; + }, + prompt(result, player) { + const { choice } = get.info("mbxuetu_backup"); + const status = player.countMark("mbxuetu_status"); + let str = ""; + if (status < 2) { + str += "令一名角色" + (choice ? "摸两张牌" : "回复1点体力"); } else { - await player.loseHp(); - await target.draw(2); + str += choice ? "摸一张牌,然后对一名角色造成1点伤害" : "回复1点体力,然后令一名角色弃置两张牌"; } - } else { - if (!storage) { - await player.recover(); - await target.chooseToDiscard(2, true, "he"); - } else { - await player.draw(); - await target.damage(); - } - } + return `###血途###
${str}
`; + }, + }, + subSkill: { + backup: {}, }, mark: true, marktext: "☯", intro: { content: (storage, player) => { if (!player.countMark("mbxuetu_status")) { - if (storage) return "转换技。出牌阶段限一次,你可以失去1点体力,然后令一名角色摸两张牌。"; - return "转换技。出牌阶段限一次,你可以弃置一张牌,然后令一名角色回复1点体力。"; + if (storage) return "转换技。出牌阶段限一次,你可以令一名角色摸两张牌。"; + return "转换技。出牌阶段限一次,你可以令一名角色回复1点体力。"; } else { if (storage) return "转换技。出牌阶段限一次,你可以摸一张牌,然后对一名角色造成1点伤害。"; return "转换技。出牌阶段限一次,你可以回复1点体力,然后令一名角色弃置两张牌。"; @@ -906,32 +1055,7 @@ const skills = { return 2; }, result: { - target(player, target) { - const status = player.countMark("mbxuetu_status"); - if (status > 1) { - if (player.storage.mbxuetu) return -get.damageEffect(target, player, player) / 10; - return -2; - } - if ((status === 0 && player.storage.mbxuetu) || (status === 1 && !ui.selected.cards.length)) return 2; - const eff = get.recoverEffect(target, player, player); - return eff > 0 ? 2 : eff < 0 ? -get.sgnAttitude(player, target) : 0; - }, - player(player, target) { - const status = player.countMark("mbxuetu_status"); - if (status > 1) { - if (player.storage.mbxuetu) return 1; - return get.recoverEffect(player, player) / 6; - } - if (status === 1 || !player.storage.mbxuetu) return -0.5; - const eff = get.effect(player, { name: "losehp" }, player, player); - if (eff >= 0) return Math.min(1, eff / 2); - const hp = - player.getHp() + - player.countCards("hes", card => { - return player.canSaveCard(card, player); - }); - return -1.5 * Math.max(0, 3 - hp); - }, + player: 1, }, }, }, @@ -7901,110 +8025,6 @@ const skills = { }, ai: { combo: "jibing", expose: 0.2 }, }, - //司马孚 - xunde: { - audio: 2, - trigger: { global: "damageEnd" }, - filter: function (event, player) { - return event.player.isIn() && get.distance(player, event.player) <= 1; - }, - logTarget: "player", - check: function (event, player) { - return get.attitude(player, event.player) > 0 && (!event.source || get.attitude(player, event.source) < 0); - }, - content: function () { - "step 0"; - player.judge().set("callback", function () { - if (event.judgeResult.number > 5) { - var player = event.getParent(2)._trigger.player; - if (get.position(card, true) == "o") player.gain(card, "gain2"); - } - }); - "step 1"; - if (result.number < 7) { - var source = trigger.source; - if (source && source.isIn() && source.countCards("h") > 0) { - player.line(source); - source.chooseToDiscard("h", true); - } - } - }, - }, - chenjie: { - audio: 2, - trigger: { global: "judge" }, - filter: function (event, player) { - var suit = get.suit(event.player.judging[0], event.player); - return ( - player.countCards("hes", function (card) { - if (_status.connectMode && get.position(card) != "e") return true; - return get.suit(card) == suit; - }) > 0 - ); - }, - direct: true, - preHidden: true, - content: function () { - "step 0"; - var suit = get.suit(trigger.player.judging[0], trigger.player); - player - .chooseCard(get.translation(trigger.player) + "的" + (trigger.judgestr || "") + "判定为" + get.translation(trigger.player.judging[0]) + "," + get.prompt("chenjie"), "hes", function (card) { - if (get.suit(card) != _status.event.suit) return false; - var player = _status.event.player; - var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); - if (mod2 != "unchanged") return mod2; - var mod = game.checkMod(card, player, "unchanged", "cardRespondable", player); - if (mod != "unchanged") return mod; - return true; - }) - .set("ai", function (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; - } - }) - .set("judging", trigger.player.judging[0]) - .set("suit", suit) - .setHiddenSkill(event.name); - "step 1"; - if (result.bool) { - event.card = result.cards[0]; - player.respond(result.cards, "highlight", "chenjie", "noOrdering"); - } else { - event.finish(); - } - "step 2"; - if (result.bool) { - if (trigger.player.judging[0].clone) { - trigger.player.judging[0].clone.classList.remove("thrownhighlight"); - game.broadcast(function (card) { - if (card.clone) { - card.clone.classList.remove("thrownhighlight"); - } - }, trigger.player.judging[0]); - game.addVideo("deletenode", player, get.cardsInfo([trigger.player.judging[0].clone])); - } - game.cardsDiscard(trigger.player.judging[0]); - trigger.player.judging[0] = card; - trigger.orderingCards.add(card); - game.log(trigger.player, "的判定牌改为", card); - player.draw(2); - } - }, - ai: { - rejudge: true, - tag: { - rejudge: 0.1, - }, - }, - }, //傅佥 jueyong: { audio: 2, diff --git a/character/mobile/sort.js b/character/mobile/sort.js index 984f8ac2b..4b68e8945 100644 --- a/character/mobile/sort.js +++ b/character/mobile/sort.js @@ -1,5 +1,5 @@ const characterSort = { - mobile_default: ["mb_sp_guanqiujian", "mb_caomao", "chengji", "lizhaojiaobo", "xin_huojun", "muludawang", "mb_chengui", "mb_huban", "mb_xianglang", "yanxiang", "xin_wuban", "laimin", "baoxin", "jiangji", "liwei", "xin_guozhao", "miheng", "taoqian", "lingcao", "sunru", "lifeng", "zhuling", "liuye", "zhaotongzhaoguang", "majun", "simazhao", "wangyuanji", "pangdegong", "shenpei", "hujinding", "zhangyì", "jiakui", "yangbiao", "chendeng", "dongcheng", "yangyi", "dengzhi", "zhengxuan", "sp_sufei", "furong", "dingyuan", "simashi", "yanghuiyu", "hucheer", "gongsunkang", "nanhualaoxian", "zhouqun", "qiaozhou", "fuqian", "simafu", "mayuanyi", "yanpu", "sunhanhua", "sp_maojie", "peixiu", "sp_jianggan", "ruanhui", "xin_mamidi", "sp_caosong", "yangfu", "wangjun", "sp_pengyang", "qianzhao", "shichangshi", "yangfeng"], + mobile_default: ["mb_simafu", "mb_sp_guanqiujian", "mb_caomao", "chengji", "lizhaojiaobo", "xin_huojun", "muludawang", "mb_chengui", "mb_huban", "mb_xianglang", "yanxiang", "xin_wuban", "laimin", "baoxin", "jiangji", "liwei", "xin_guozhao", "miheng", "taoqian", "lingcao", "sunru", "lifeng", "zhuling", "liuye", "zhaotongzhaoguang", "majun", "simazhao", "wangyuanji", "pangdegong", "shenpei", "hujinding", "zhangyì", "jiakui", "yangbiao", "chendeng", "dongcheng", "yangyi", "dengzhi", "zhengxuan", "sp_sufei", "furong", "dingyuan", "simashi", "yanghuiyu", "hucheer", "gongsunkang", "nanhualaoxian", "zhouqun", "qiaozhou", "fuqian", "mayuanyi", "yanpu", "sunhanhua", "sp_maojie", "peixiu", "sp_jianggan", "ruanhui", "xin_mamidi", "sp_caosong", "yangfu", "wangjun", "sp_pengyang", "qianzhao", "shichangshi", "yangfeng"], mobile_yijiang: ["yj_zhanghe", "yj_zhangliao", "yj_xuhuang", "yj_ganning", "yj_huangzhong", "yj_weiyan", "yj_zhoubuyi"], mobile_standard: ["xin_xiahoudun", "xin_zhangfei"], mobile_shenhua_feng: ["re_xiaoqiao", "xin_zhoutai"], diff --git a/character/mobile/translate.js b/character/mobile/translate.js index 6d1e530fe..d6e54587e 100644 --- a/character/mobile/translate.js +++ b/character/mobile/translate.js @@ -495,12 +495,6 @@ const translates = { jueyong_info: "锁定技。①当你不因〖绝勇〗成为唯一牌的目标时,若此牌不为转化牌且对应的实体牌牌数为1且不为【桃】或【酒】且你的“绝”数小于你的体力值,则你将此牌置于你的武将牌上,称为“绝”,且取消此牌的目标。②结束阶段开始时,若你有“绝”,则你令所有“绝”的原使用者依次对你使用所有“绝”,将无法使用的“绝”置入弃牌堆。", poxiang: "破降", poxiang_info: "出牌阶段限一次。你可以将一张牌交给一名其他角色。你摸三张牌(不计入本回合的手牌上限),移去所有“绝”并失去1点体力。", - simafu: "手杀司马孚", - simafu_prefix: "手杀", - xunde: "勋德", - xunde_info: "一名角色受到伤害后,若你至其的距离不大于1,则你可判定。若判定结果:大于5,你令该角色获得判定牌;小于7,你令伤害来源弃置一张手牌。", - chenjie: "臣节", - chenjie_info: "一名角色的判定牌生效前,你可打出一张花色相同的牌。系统将你打出的牌作为新判定牌,将原判定牌置入弃牌堆。然后你摸两张牌。", mayuanyi: "马元义", jibing: "集兵", jibing_info: "①摸牌阶段开始时,若你的“兵”数小于势力数,则你可以改为将牌堆顶的两张牌置于你的武将牌上,称为“兵”。②你可以将一张“兵”当做【杀】或【闪】使用或打出。", @@ -856,9 +850,9 @@ const translates = { jieyu_info_identity: "结束阶段,你可以从弃牌堆中获得共X张不同牌名的基本牌(X为3-你上次发动〖竭御〗至今你成为其他角色使用伤害类卡牌目标的次数,且X至少为1)。", yangfeng: "杨奉", mbxuetu: "血途", - mbxuetu_info: "转换技。出牌阶段限一次,阴:你可以弃置一张牌,然后令一名角色回复1点体力;阳:你可以失去1点体力,然后令一名角色摸两张牌。", + mbxuetu_info: "转换技。出牌阶段限一次,阴:你可以令一名角色回复1点体力;阳:你可以令一名角色摸两张牌。", mbxuetu_achieve: "血途·成功", - mbxuetu_achieve_info: "出牌阶段各限一次。⒈你可以弃置一张牌,然后令一名角色回复1点体力;⒉你可以失去1点体力,然后令一名角色摸两张牌。", + mbxuetu_achieve_info: "出牌阶段各限一次。⒈你可以令一名角色回复1点体力;⒉你可以令一名角色摸两张牌。", mbxuetu_fail: "血途·失败", mbxuetu_fail_info: "转换技。出牌阶段限一次,阴:你可以回复1点体力,然后令一名角色弃置两张牌;阳:你可以摸一张牌,然后对一名角色造成1点伤害。", mbweiming: "威命", @@ -894,6 +888,12 @@ const translates = { mbjuejin_info: "限定技。出牌阶段,你可以令所有角色依次将体力回复或失去至1并获得X点护甲(X为一名角色以此法变化的体力值)。然后你增加如下“向死存魏”的全局技能:当有牌进入弃牌堆后,系统将这些牌中的【闪】、【桃】和【酒】移出游戏。", mbweitong: "卫统", mbweitong_info: "主公技。游戏开始时,若你有〖潜龙〗,你获得20X枚“道心”(X为其他魏势力角色数)。", + mb_simafu: "手杀司马孚", + mb_simafu_prefix: "手杀", + mbpanxiang: "蹒襄", + mbpanxiang_info: "当一名角色受到伤害时,你可以选择一项(不能与上次你因其发动此技能时选择的选项相同):⒈令此伤害-1,伤害来源摸两张牌;⒉令此伤害+1,其摸三张牌。", + mbchenjie: "臣节", + mbchenjie_info: "锁定技。当一名角色死亡后,若你有〖蹒襄〗且其成为过你〖蹒襄〗的目标,你弃置区域里的所有牌,摸四张牌。", }; export default translates; diff --git a/character/mobile/voices.js b/character/mobile/voices.js index efa606617..49757a0e1 100644 --- a/character/mobile/voices.js +++ b/character/mobile/voices.js @@ -241,11 +241,6 @@ export default { "#moucuan1": "汉失民心,天赐良机!", "#moucuan2": "天下正主,正是大贤良师!", "#mayuanyi:die": "唐周……无耻!", - "#xunde1": "陛下所托,臣必尽心尽力!", - "#xunde2": "纵吾荏弱难持,亦不推诿君命!", - "#chenjie1": "臣心怀二心,不可事君也。", - "#chenjie2": "竭力致身,以尽臣节。", - "#simafu:die": "身辅六公,亦难报此恩……", "#jueyong1": "敌围何惧,有死而已!", "#jueyong2": "身陷敌阵,战而弥勇!", "#poxiang1": "王瓘既然假降,吾等可将计就计。", diff --git a/character/onlyOL/character.js b/character/onlyOL/character.js index aede05c36..de37a6c34 100644 --- a/character/onlyOL/character.js +++ b/character/onlyOL/character.js @@ -10,6 +10,7 @@ const characters = { ol_yufan: ["male", "wu", 3, ["olzongxuan", "olzhiyan"], ["tempname:re_yufan", "die_audio:re_yufan"]], ol_chengpu: ["male", "wu", 4, ["dclihuo", "olchunlao"], ["tempname:xin_chengpu", "die_audio:xin_chengpu"]], ol_wangyi: ["female", "wei", 3, ["olzhenlie", "olmiji"]], + ol_sb_pangtong: ["male", "shu", 3, ["olsbhongtu", "olsbqiwu"]], ol_fazheng: ["male", "shu", 3, ["olxuanhuo", "olenyuan"]], }; diff --git a/character/onlyOL/skill.js b/character/onlyOL/skill.js index 38136f8d2..70f0c801a 100644 --- a/character/onlyOL/skill.js +++ b/character/onlyOL/skill.js @@ -2,6 +2,246 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { + //谋庞统 + olsbhongtu: { + audio: 2, + trigger: { + global: ["phaseZhunbeiEnd", "phaseJudgeEnd", "phaseDrawEnd", "phaseUseEnd", "phaseDiscardEnd", "phaseJieshuEnd"], + }, + filter(event, player) { + let count = 0; + player.checkHistory("gain", evt => { + if (evt.getParent(event.name) !== event) return; + count += evt.cards.length; + }); + return count >= 2; + }, + derivation: ["nzry_feijun", "qianxi"], + prompt2: "你可以摸三张牌,展示三张手牌,令一名其他角色选择是否使用其中一张牌并令你随机弃置其中另一张牌。若使用牌的点数于三张牌中满足以下条件,其获得如下技能或效果直到其下一个回合的回合结束:唯一最大:〖飞军〗;不为最大且不为最小:〖潜袭〗;唯一最小:手牌上限+2。若其未以此法使用牌,你对其与你各造成1点火焰伤害。", + check(event, player) { + if ( + game.hasPlayer(current => { + return current !== player && get.attitude(player, current) > 0; + }) + ) + return true; + const eff = get.damageEffect(player, player, player, "fire"); + if ( + game.hasPlayer(current => { + return ( + get.damageEffect(current, player, player, "fire") > eff && + player.countCards("h", card => { + return !current.hasUseTarget(card); + }) >= + 2 + (player.getHp() > 1) + ); + }) + ) + return true; + return false; + }, + async content(event, trigger, player) { + await player.draw(3); + if (player.countCards("h") < 3) return; + const [cards, targets] = await player + .chooseCardTarget({ + prompt: "鸿图:请展示三张手牌并选择一名角色", + prompt2: "你选择的角色须选择是否使用其中的一张牌,并令你随机弃置其中的另一张牌。", + position: "h", + filterCard: true, + selectCard: 3, + filterTarget: lib.filter.notMe, + forced: true, + hasFriend: game.hasPlayer(current => { + return current !== player && get.attitude(player, current) > 0; + }), + ai1(card) { + const player = get.player(), + val = player.getUseValue(card); + if (get.event("hasFriend")) { + if ( + ui.selected.cards.some(cardx => { + return player.getUseValue(cardx) > 5; + }) + ) + return -val - get.value(card); + return val - 5; + } + if ( + game.hasPlayer(current => { + return get.attitude(get.player(), current) < 0 && !current.hasUseTarget(card); + }) + ) + return 100 - val; + return -val; + }, + ai2(target) { + const att = get.attitude(get.player(), target); + if (!ui.selected.cards.length) return 0; + if (ui.selected.cards.every(card => !target.hasUseTarget(card))) { + return 10 * (get.damageEffect(target, player, player, "fire") - get.damageEffect(player, player, player, "fire")); + } + return Math.max(...ui.selected.cards.map(card => target.getUseValue(card) * att)); + }, + }) + .forResult("cards", "targets"); + if (!cards || !cards.length || !targets || !targets.length) return; + const [target] = targets; + player.line(target, "green"); + await player.showCards(cards, `${get.translation(player)}对${get.translation(target)}发动了【鸿图】`); + const links = await target + .chooseButton([`鸿图:是否使用${get.translation(player)}展示的其中一张牌?`, cards]) + .set("filterButton", button => { + const player = get.player(), + card = button.link; + const cardx = get.autoViewAs( + { + name: get.name(card), + nature: get.nature(card), + }, + [card] + ); + return player.hasUseTarget(cardx, null, false); + }) + .set("ai", button => { + return get.player().getUseValue(button.link); + }) + .forResultLinks(); + if (!links || !links.length) { + for (const current of [target, player]) { + if (!current.isIn()) continue; + player.line(current, "fire"); + await current.damage("fire"); + } + } else { + const [card] = links; + cards.remove(card); + const cardx = get.autoViewAs( + { + name: get.name(card), + nature: get.nature(card), + }, + [card] + ); + const owner = get.owner(card); + const next = target + .chooseUseTarget(cardx, [card], true, false) + .set("throw", false) + .set("owner", owner) + .set("oncard", card => { + const owner = get.event().getParent().owner; + if (owner) owner.$throw(card.cards); + }); + if (card.name === cardx.name && get.is.sameNature(card, cardx, true)) next.set("viewAs", false); + await next; + const restCards = cards.filter(card => { + return get.owner(card) === player && get.position(card) === "h" && lib.filter.cardDiscardable(card, player, "olsbhongtu"); + }); + if (restCards.length) { + player.discard(restCards.randomGet()); + } + const num = get.number(card, player); + let skill = null; + if ( + cards.every(cardx => { + if (cardx === card) return true; + return get.number(cardx) < num; + }) + ) { + skill = "nzry_feijun"; + } else if ( + cards.every(cardx => { + if (cardx === card) return true; + return get.number(cardx) > num; + }) + ) { + target.addSkill("olsbhongtu_limit"); + target.addMark("olsbhongtu_limit", 2, false); + } else { + skill = "qianxi"; + } + let skillName = null; + if (skill) { + skillName = `olsbhongtu_${player.playerid}`; + target.addAdditionalSkills(skillName, [skill]); + } + target.when({ player: "phaseBegin" }).then(() => { + player.storage.olsbhongtu_phased = true; + }); + target + .when({ player: "phaseEnd" }) + .filter(() => { + return target.storage.olsbhongtu_phased; + }) + .assign({ + firstDo: true, + priority: Infinity, + }) + .vars({ + skillName, + }) + .then(() => { + delete player.storage.olsbhongtu_phased; + if (skillName) { + player.removeAdditionalSkills(skillName); + } else { + player.removeSkill("olsbhongtu_limit"); + } + }); + } + }, + subSkill: { + limit: { + markimage: "image/card/handcard.png", + intro: { + content(storage, player) { + return "手牌上限+" + storage; + }, + }, + charlotte: true, + mod: { + maxHandcard(player, num) { + return num + player.countMark("olsbhongtu_limit"); + }, + }, + } + }, + }, + olsbqiwu: { + audio: 2, + trigger: { + player: "damageBegin4", + }, + filter(event, player) { + if (!event.source) return false; + if (event.source !== player && !event.source.inRangeOf(player)) return false; + return ( + game + .getGlobalHistory( + "everything", + evt => { + return evt.name == "damage" && evt.player == player; + }, + event + ) + .indexOf(event) === 0 + ); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseToDiscard(get.prompt("olsbqiwu"), `你可以弃置一张红色牌,防止${get.translation(trigger.source)}对你造成的${trigger.num}点伤害。`, "chooseonly", { color: "red" }, "he") + .set("ai", card => { + if (get.event("goon")) return 6 - get.value(card); + return 0; + }) + .set("goon", get.damageEffect(player, trigger.source, player) < 0) + .forResult(); + }, + async content(event, trigger, player) { + await player.discard(event.cards); + trigger.cancel(); + }, + }, //法正 olxuanhuo: { audio: 2, diff --git a/character/onlyOL/sort.js b/character/onlyOL/sort.js index 5605b582e..56e191ac2 100644 --- a/character/onlyOL/sort.js +++ b/character/onlyOL/sort.js @@ -2,7 +2,7 @@ const characterSort = { onlyOL_yijiang1: ["ol_jianyong", "ol_lingtong", "ol_gaoshun", "ol_fazheng"], onlyOL_yijiang2: ["ol_caozhang", "ol_chengpu", "ol_wangyi"], onlyOL_yijiang3: ["ol_yufan"], - onlyOL_sb: ["ol_sb_jiangwei", "ol_sb_guanyu", "ol_sb_taishici", "ol_sb_yuanshao"], + onlyOL_sb: ["ol_sb_jiangwei", "ol_sb_guanyu", "ol_sb_taishici", "ol_sb_yuanshao", "ol_sb_pangtong"], }; const characterSortTranslate = { diff --git a/character/onlyOL/translate.js b/character/onlyOL/translate.js index 906d8896d..e5894e43a 100644 --- a/character/onlyOL/translate.js +++ b/character/onlyOL/translate.js @@ -72,6 +72,12 @@ const translates = { olzhenlie_info: "当你成为其他角色使用【杀】或普通锦囊牌的目标后,你可以失去1点体力并令此牌对你无效,然后你选择一项:①获得使用者的一张牌;②发动一次〖秘计〗。", olmiji: "秘计", olmiji_info: "结束阶段,若你已受伤,则你可以摸X张牌,然后你可以将至多X张牌任意分配给其他角色(X为你已损失的体力值)。", + ol_sb_pangtong: "OL谋庞统", + ol_sb_pangtong_prefix: "OL谋", + olsbhongtu: "鸿图", + olsbhongtu_info: "一名角色的阶段结束时,若你于此阶段得到过至少两张牌,你可以摸三张牌,展示三张手牌,令一名其他角色选择是否使用其中一张牌并令你随机弃置其中另一张牌。若使用牌的点数于三张牌中满足以下条件,其获得如下技能或效果直到其下一个回合的回合结束:唯一最大,其获得〖飞军〗;不为唯一最大且不为唯一最小,其获得〖潜袭〗;唯一最小,其手牌上限+2。若其未以此法使用牌,你对其与你各造成1点火焰伤害。", + olsbqiwu: "栖梧", + olsbqiwu_info: "当你每回合首次受到伤害时,若伤害来源为你或在你的攻击范围内,你可以弃置一张红色牌,防止此伤害。", ol_fazheng:'OL界法正', ol_fazheng_prefix:'OL界', olxuanhuo:'眩惑', diff --git a/character/rank.js b/character/rank.js index c91679c5f..074f6e129 100644 --- a/character/rank.js +++ b/character/rank.js @@ -389,6 +389,8 @@ window.noname_character_rank = { "drag_lvchang", "star_sunjian", "yj_xuangongzhu", + "ol_sb_pangtong", + "dc_sb_zhugejin", ], am: [ "tw_yanliang", @@ -706,6 +708,8 @@ window.noname_character_rank = { "lizhaojiaobo", "linghuyu", "key_mia", + "sb_handang", + "sb_gongsunzan", ], bp: [ "xin_huojun", @@ -1115,6 +1119,8 @@ window.noname_character_rank = { "std_chengyu", "std_fanyufeng", "std_feiyi", + "tw_zhugejun", + "mb_simafu", ], b: [ "std_dc_yanghu", @@ -1640,6 +1646,7 @@ window.noname_character_rank = { "old_xiaoqiao", "old_guanyu", "dc_kongrong", + "yadan", ], c: [ "xiahoudun", @@ -2238,6 +2245,8 @@ window.noname_character_rank = { "drag_caoren", "wupu", "star_sunjian", + "ol_sb_pangtong", + "dc_sb_zhugejin", ], rare: [ "std_sunhao", @@ -2747,6 +2756,11 @@ window.noname_character_rank = { "chengji", "mb_sp_guanqiujian", "lizhaojiaobo", + "tw_zhugejun", + "yadan", + "mb_simafu", + "sb_handang", + "sb_gongsunzan", ], junk: [ "ol_sb_guanyu", diff --git a/character/sb/character.js b/character/sb/character.js index f8b46f27a..f1d45cc43 100644 --- a/character/sb/character.js +++ b/character/sb/character.js @@ -1,4 +1,6 @@ const characters = { + sb_handang: ["male", "wu", 4, ["sbgongqi", "sbjiefan"]], + sb_gongsunzan: ["male", "qun", 4, ["sbyicong", "sbqiaomeng"]], sb_gaoshun: ["male", "qun", 4, ["sbxianzhen", "sbjinjiu"]], sb_xiahoudun: ["male", "wei", 4, ["sbganglie", "sbqingjian"]], sb_xunyu: ["male", "wei", 3, ["sbquhu", "sbjieming"]], diff --git a/character/sb/skill.js b/character/sb/skill.js index eab2da1ea..a163c568f 100644 --- a/character/sb/skill.js +++ b/character/sb/skill.js @@ -2,12 +2,446 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { + //韩当 + sbgongqi: { + audio: 2, + trigger: { + player: "phaseUseBegin", + }, + async cost(event, trigger, player) { + event.result = await player + .chooseToDiscard(get.prompt("sbgongqi"), "你可以弃置一张牌,令你本阶段使用牌时,其他角色不能使用或打出与你弃置的牌颜色不同的手牌进行响应。", "he", "chooseonly") + .set("ai", card => { + const ind = get.event("colors").indexOf(get.color(card)) + 1; + if (ind <= 0) return 0; + return 1.5 + 2 * ind - get.value(card); + }) + .set( + "colors", + (() => { + if (!player.countCards("hs", card => player.hasValueTarget(card))) return []; + const colors = Object.keys(lib.color); + const infos = colors.map(color => { + return [ + color, + game.filterPlayer().map(current => { + const att = get.attitude(player, current); + return current + .getCards("hes", card => { + if (get.color(card) !== color) return false; + if (current.hasUseTarget(card, false, false)) return false; + if (!lib.filter.cardEnabled(card, current, "forceEnable")) return false; + return true; + }) + .map(card => { + return get.value(card) * (att > 0 ? -0.2 : 1); + }) + .reduce((p, c) => p + c, 0); + }), + ]; + }); + infos.sort((a, b) => { + return a[1] - b[1]; + }); + return infos.map(info => info[0]); + })() + ) + .forResult(); + }, + locked: false, + async content(event, trigger, player) { + const { cards } = event; + await player.discard(cards); + await game.asyncDelayx(); + player.addTempSkill("sbgongqi_effect", "phaseChange"); + player.markAuto("sbgongqi_effect", [get.color(cards[0], player)]); + player.line(game.filterPlayer()); + await game.asyncDelayx(); + }, + updateBlocker(player) { + const list = [], + storage = player.storage.sbgongqi_block; + if (storage && storage.length) { + list.addArray(...storage.map(i => i[1])); + } + player.storage.sbgongqi_blocker = list; + }, + mod: { + attackRange(player, num) { + return num + 4; + }, + }, + subSkill: { + effect: { + trigger: { + player: "useCard", + }, + onremove: true, + charlotte: true, + forced: true, + async content(event, trigger, player) { + game.countPlayer(current => { + if (current === player) return; + current.addTempSkill("sbgongqi_block", "phaseChange"); + if (!current.storage.sbgongqi_block) current.storage.sbgongqi_block = []; + current.storage.sbgongqi_block.push([trigger.card, player.getStorage("sbgongqi_effect")]); + lib.skill.sbgongqi.updateBlocker(current); + }); + }, + }, + block: { + trigger: { + player: ["damageBefore", "damageCancelled", "damageZero"], + target: ["shaMiss", "useCardToExcluded", "useCardToEnd"], + global: ["useCardEnd"], + }, + forced: true, + firstDo: true, + popup: false, + charlotte: true, + onremove: ["sbgongqi_block", "sbgongqi_blocker"], + filter(event, player) { + if (!event.card || !player.storage.sbgongqi_block) return false; + return player.getStorage("sbgongqi_block").some(info => { + return info[0] === event.card; + }); + }, + async content(event, trigger, player) { + const storage = player.storage.sbgongqi_block; + for (let i = 0; i < storage.length; i++) { + if (storage[i][0] === trigger.card) { + storage.splice(i--, 1); + } + } + if (!storage.length) player.removeSkill("sbgongqi_block"); + else lib.skill.sbgongqi.updateBlocker(trigger.target); + }, + mod: { + cardEnabled(card, player) { + if (!player.storage.sbgongqi_blocker) return; + const color = get.color(card); + if (color == "none") return; + const hs = player.getCards("h"), + cards = [card]; + if (Array.isArray(card.cards)) cards.addArray(card.cards); + if (cards.containsSome(...hs) && player.storage.sbgongqi_blocker.includes(color)) return false; + }, + }, + }, + }, + }, + sbjiefan: { + audio: 2, + enable: "phaseUse", + usable: 1, + filterTarget: true, + async content(event, trigger, player) { + const { target } = event; + const targets = game.filterPlayer(current => { + return current.inRange(target); + }); + const count = Math.min(2, targets.length); + if (!count) { + target.chat("没人打得到我喔!"); + return; + } + const controls = ["选项一", "选项二", "背水!"]; + const control = await target + .chooseControl(controls) + .set("choiceList", [`令所有攻击范围内含有你的角色依次弃置一张牌(${get.translation(targets)})`, `你摸等同于攻击范围内含有你的角色数的牌(${get.cnNumber(count)}张牌)`, `背水!令${get.translation(player)}的〖解烦〗失效直到其杀死一名角色,然后你依次执行上述所有选项`]) + .set("ai", () => { + return get.event("choice"); + }) + .set( + "choice", + (() => { + const eff1 = targets + .map(current => { + let position = "h"; + if (!current.countCards("h")) position += "e"; + return get.effect(current, { name: "guohe", position }, target, target); + }) + .reduce((p, c) => p + c, 0); + const eff2 = (get.effect(target, { name: "wuzhong" }, target) * count) / 2; + if ( + game.hasPlayer(current => { + const att1 = get.attitude(player, current), + att2 = get.attitude(target, current); + if (att1 < 0 && att2 < 0) { + return current.getHp() <= 1; + } + return false; + }) && + eff1 > 15 && + eff2 > 0 + ) + return "背水!"; + if (eff1 > 3 * eff2) return "选项一"; + return "选项二"; + })() + ) + .forResultControl(); + game.log(target, "选择了", "#g" + control); + if (control === "背水!") { + player.tempBanSkill("sbjiefan", { source: "die" }); + } + if (control !== "选项二") { + for (const current of targets) { + target.line(current, "thunder"); + await current.chooseToDiscard("解烦:请弃置一张牌", "he", true); + } + } + if (control !== "选项一") { + target.draw(count); + } + }, + ai: { + order: 8, + result: { + target(player, target) { + const targets = game.filterPlayer(current => { + return current.inRange(target); + }); + return Math.min(2, targets.length) / 2; + }, + } + } + }, + //公孙瓒 + sbyicong: { + audio: 2, + trigger: { + global: "roundStart", + }, + filter(event, player) { + return player.hasMark("charge"); + }, + chargeSkill: true, + group: "sbyicong_init", + async cost(event, trigger, player) { + const len = player.countMark("charge"); + const numbers = Array.from({ length: len }, (_, i) => get.cnNumber(i + 1, true)); + if (_status.connectMode) { + game.broadcastAll(() => { + _status.noclearcountdown = true; + }); + } + let result, result2; + while (true) { + result = await player + .chooseControl(numbers, "cancel2") + .set("prompt", get.prompt("sbyicong")) + .set("prompt2", "你可以消耗任意点蓄力值并选择一项:⒈你于本轮内至其他角色的距离-X,令系统选择牌堆中的一张【杀】;⒉其他角色于本轮内至你的距离+X,令系统选择牌堆中的一张【闪】(X为你消耗的蓄力值)。然后若你的“扈”数小于4,你将系统选择的牌置于武将牌上,称为“扈”。") + .set("ai", () => { + return get.event("choice"); + }) + .set( + "choice", + (() => { + if ( + !game.hasPlayer(current => { + return ( + get.distance(player, current) >= 2 && + player.countCards("hs", card => { + const list = ["shunshou", "bingliang", "zhujinqiyuan"]; + if (!player.inRange(current)) list.add("sha"); + return list.includes(get.name(card)) && get.effect(current, card, player, player) > 0; + }) > 0 + ); + }) + ) + return 0; + return Math.ceil(len / 2) - 1; + })() + ) + .forResult(); + if (result.control === "cancel2") return; + const num = result.index + 1; + result2 = await player + .chooseControl(["选项一", "选项二", "返回"]) + .set("prompt", "义从:请选择一项") + .set("choiceList", [ + `你于本轮内至其他角色的距离-${num}${ + player.countCards("s", card => { + return card.hasGaintag("sbyicong"); + }) >= 4 + ? "" + : ",将牌堆中的一张【杀】置于你的武将牌上,称为“扈”" + }`, + `其他角色于本轮内至你的距离+${num}${ + player.countCards("s", card => { + return card.hasGaintag("sbyicong"); + }) >= 4 + ? "" + : ",将牌堆中的一张【闪】置于你的武将牌上,称为“扈”" + }`, + ]) + .set("ai", () => { + const player = get.player(); + if (player.getHp() > 2 || player.countCards("hsx", ["shan", "caochuan"]) >= 3) return 0; + return 1; + }) + .forResult(); + if (result2.control !== "返回") break; + } + if (_status.connectMode) { + game.broadcastAll(() => { + delete _status.noclearcountdown; + game.stopCountChoose(); + }); + } + event.result = { + bool: true, + cost_data: { + num: result.index + 1, + choice: result2.index, + }, + }; + }, + async content(event, trigger, player) { + const { num, choice } = event.cost_data; + const skill = choice === 0 ? "sbyicong_to" : "sbyicong_from"; + player.removeMark("charge", num); + player.addTempSkill(skill, "roundStart"); + player.addMark(skill, num, false); + if (player.countCards("s", card => card.hasGaintag("sbyicong")) < 4) { + const name = choice === 0 ? "sha" : "shan"; + const card = get.cardPile2(name); + if (card) { + game.log(player, "将", card, "置于了武将牌上"); + await player.loseToSpecial([card], "sbyicong"); + player.markSkill("sbyicong"); + } + } + }, + marktext: "扈", + intro: { + name: "扈(义从)", + mark(dialog, storage, player) { + const cards = player.getCards("s", card => { + return card.hasGaintag("sbyicong"); + }); + if (cards.length) dialog.addAuto(cards); + else dialog.addText("暂无卡牌"); + }, + markcount(storage, player) { + return player.countCards("s", card => { + return card.hasGaintag("sbyicong"); + }); + }, + onunmark(storage, player) { + const cards = player.getCards("s", card => { + return card.hasGaintag("sbyicong"); + }); + if (cards.length) { + player.loseToDiscardpile(cards); + } + }, + }, + subSkill: { + init: { + audio: "sbyicong", + trigger: { + player: "enterGame", + global: "phaseBefore", + }, + filter(event, player) { + return event.name != "phase" || game.phaseNumber == 0; + }, + forced: true, + locked: false, + async content(event, trigger, player) { + player.addMark("charge", 2); + }, + }, + to: { + charlotte: true, + mod: { + globalFrom(from, to, distance) { + return distance - from.countMark("sbyicong_to"); + }, + }, + marktext: "从", + intro: { + content: "本轮你至其他角色的距离-#", + }, + }, + from: { + charlotte: true, + mod: { + globalTo(from, to, distance) { + return distance - to.countMark("sbyicong_to"); + }, + }, + marktext: "从", + intro: { + content: "本轮其他角色至你的距离-#", + }, + }, + }, + }, + sbqiaomeng: { + audio: 2, + trigger: { + source: "damageSource", + }, + filter(event, player) { + if (!event.card || event.card.name !== "sha") return false; + return player.hasSkill("sbyicong", null, false, false); + }, + async cost(event, trigger, player) { + const list = ["蓄力", "cancel2"]; + const choiceList = [`弃置${get.translation(trigger.player)}区域里的一张牌,你摸一张牌`, `获得2点蓄力值`]; + if (trigger.player.isIn() && trigger.player.countDiscardableCards(player, "hej")) { + list.unshift("弃牌"); + } else { + choiceList[0] = `${choiceList[0]}`; + } + const result = await player + .chooseControl(list) + .set("prompt", get.prompt("sbqiaomeng")) + .set("choiceList", choiceList) + .set("ai", () => { + return get.event("choice"); + }) + .set( + "choice", + (() => { + if (!list.includes("弃牌")) return "蓄力"; + const eff = get.effect(trigger.player, { name: "guohe" }, player, player); + if (player.countMark("charge") >= 2 && eff >= 0) return "弃牌"; + return "蓄力"; + })() + ) + .forResult(); + if (result.control !== "cancel2") { + event.result = { + bool: true, + cost_data: { + control: result.control, + }, + }; + } + }, + async content(event, trigger, player) { + const { control } = event.cost_data; + if (control === "弃牌") { + player.line(trigger.player); + await player.discardPlayerCard(trigger.player, "hej", true); + await player.draw(); + } else { + const num = Math.min(2, 4 - player.countMark("charge")); + if (num > 0) player.addMark("charge", num); + } + }, + }, //高顺 sbxianzhen: { audio: 2, enable: "phaseUse", usable: 1, filterTarget(card, player, target) { + if (get.mode() === "identity" && target.getHp() >= player.getHp()) return false; return target !== player; }, async content(event, trigger, player) { @@ -71,10 +505,12 @@ const skills = { } game.log(card, "无视防具且不计入次数限制"); if (!player.storage.sbxianzhen_damaged) { - player.storage.sbxianzhen_damaged = true; + player.storage.sbxianzhen_damaged = (player.storage.sbxianzhen_damaged || 0) + 1; player.when("phaseAfter").then(() => { delete player.storage.sbxianzhen_damaged; }); + } + if (player.storage.sbxianzhen_damaged <= 2) { await target.damage(); await game.asyncDelayx(); } @@ -211,6 +647,7 @@ const skills = { sbganglie: { audio: 2, enable: "phaseUse", + usable: 1, filter(event, player) { if (!event.sbganglie_enabledTargets) return false; return game.hasPlayer(current => { @@ -224,12 +661,12 @@ const skills = { .getAllHistory("useSkill", evt => evt.skill === "sbganglie") .map(evt => { return evt.targets; - }) - .flat(); - const targets = player + }); + let targets = player .getAllHistory("damage", evt => evt.source && evt.source.isIn()) .map(evt => evt.source) .unique(); + targets = [...targets, ...targets]; targets.removeArray(chosen); event.set("sbganglie_enabledTargets", targets); }, @@ -6101,7 +6538,7 @@ const skills = { return [1, 1]; } }, - } + }, }, }, }, diff --git a/character/sb/sort.js b/character/sb/sort.js index 54facd70b..4566fbf89 100644 --- a/character/sb/sort.js +++ b/character/sb/sort.js @@ -1,9 +1,9 @@ const characterSort = { sb_zhi: ["sb_sunquan", "sb_zhouyu", "sb_zhangjiao", "sb_caocao", "sb_zhenji", "sb_liubei", "sb_daqiao", "sb_liubiao", "sb_sp_zhugeliang", "sb_xunyu"], - sb_shi: ["sb_xuhuang", "sb_machao", "sb_fazheng", "sb_chengong", "sb_diaochan", "sb_pangtong", "sb_zhanghe", "sb_caopi", "sb_ganning"], + sb_shi: ["sb_xuhuang", "sb_machao", "sb_fazheng", "sb_chengong", "sb_diaochan", "sb_pangtong", "sb_zhanghe", "sb_caopi", "sb_ganning", "sb_handang"], sb_tong: ["liucheng", "sp_yangwan", "sb_xiahoushi", "sb_zhangfei", "sb_zhaoyun", "sb_sunce", "sb_zhurong", "sb_xiaoqiao", "sb_xiahoudun"], sb_yu: ["sb_yujin", "sb_lvmeng", "sb_huangzhong", "sb_huanggai", "sb_zhouyu", "sb_caoren", "sb_yl_luzhi", "sb_huangyueying"], - sb_neng: ["sb_huaxiong", "sb_sunshangxiang", "sb_jiangwei", "sb_yuanshao", "sb_menghuo", "sb_guanyu", "sb_gaoshun"], + sb_neng: ["sb_huaxiong", "sb_sunshangxiang", "sb_jiangwei", "sb_yuanshao", "sb_menghuo", "sb_guanyu", "sb_gaoshun", "sb_gongsunzan"], // sb_waitforsort:[], }; diff --git a/character/sb/translate.js b/character/sb/translate.js index 5bcc097fe..ec2d6d9cf 100644 --- a/character/sb/translate.js +++ b/character/sb/translate.js @@ -260,15 +260,28 @@ const translates = { sb_xiahoudun: "谋夏侯惇", sb_xiahoudun_prefix: "谋", sbganglie: "刚烈", - sbganglie_info: "出牌阶段,你可以选择一名本局游戏对你造成过伤害且未以此法选择过的角色,你对其造成2点伤害。", + sbganglie_info: "出牌阶段限一次。你可以选择一名本局游戏对你造成过伤害且你以此法选择过其的次数小于2的角色,你对其造成1点伤害。", sbqingjian: "清俭", sbqingjian_info: "①当有一张牌不因使用而进入弃牌堆后,若你的“清俭”数小于X,你将此牌置于你的武将牌上,称为“清俭”(X为你的体力值-1,且至少为1)。②出牌阶段结束时,你将所有“清俭”分配给任意角色。", sb_gaoshun: "谋高顺", sb_gaoshun_prefix: "谋", sbxianzhen: "陷阵", - sbxianzhen_info: "出牌阶段限一次。你可以选择一名其他角色,你于本阶段获得如下效果:⒈你对其使用牌无距离限制;⒉当你使用【杀】指定其为目标后,你可以与其拼点:若你赢,此【杀】无视防具且不计入次数,且若你本回合未以此法造成过伤害,你对其造成1点伤害;若其拼点牌为【杀】,则你获得之;若其拼点牌为其最后的手牌,则此【杀】对其造成伤害时,此伤害+1。", + sbxianzhen_info_identity: "出牌阶段限一次。你可以选择一名体力值小于你的角色,你于本阶段获得如下效果:⒈你对其使用牌无距离限制;⒉当你使用【杀】指定其为目标后,你可以与其拼点:若你赢,此【杀】无视防具且不计入次数,且若你本回合以此法对其造成的伤害小于2,你对其造成1点伤害;若其拼点牌为【杀】,则你获得之;若其拼点牌为其最后的手牌,则此【杀】对其造成伤害时,此伤害+1。", + sbxianzhen_info: "出牌阶段限一次。你可以选择一名其他角色,你于本阶段获得如下效果:⒈你对其使用牌无距离限制;⒉当你使用【杀】指定其为目标后,你可以与其拼点:若你赢,此【杀】无视防具且不计入次数,且若你本回合以此法对其造成的伤害小于2,你对其造成1点伤害;若其拼点牌为【杀】,则你获得之;若其拼点牌为其最后的手牌,则此【杀】对其造成伤害时,此伤害+1。", sbjinjiu: "禁酒", sbjinjiu_info: "锁定技。①你的【酒】均视为【杀】。②当你受到酒【杀】的伤害时,你令此伤害减至1。③其他角色不能于你的回合内使用【酒】。④当一名其他角色的拼点牌亮出后,若你为发起者或参与者且此牌为【酒】,则此牌的点数视为A。", + sb_handang: "谋韩当", + sb_handang_prefix: "谋", + sbgongqi: "弓骑", + sbgongqi_info: "①出牌阶段开始时,你可以弃置一张牌,然后本阶段你获得如下效果:当你使用牌时,你令所有其他角色不能使用或打出与你弃置牌颜色不同的手牌响应此牌。②你的攻击范围+4。", + sbjiefan: "解烦", + sbjiefan_info: "出牌阶段限一次。你可以令一名角色选择一项:⒈令所有攻击范围内含有其的角色依次弃置一张牌;⒉其摸等同于攻击范围内含有其的角色数的牌(至多两张);⒊背水:此技能失效直到你杀死一名角色,然后依次执行上述所有选项。", + sb_gongsunzan: "谋公孙瓒", + sb_gongsunzan_prefix: "谋", + sbyicong: "义从", + sbyicong_info: "蓄力技(2/4)。①一轮游戏开始时,你可以消耗任意点蓄力值并选择一项:⒈你于本轮内至其他角色的距离-X,令系统选择牌堆中的一张【杀】;⒉其他角色于本轮内至你的距离+X,令系统选择牌堆中的一张【闪】(X为你消耗的蓄力值)。然后若你的“扈”数小于4,你将系统选择的牌置于武将牌上,称为“扈”。②你可以将“扈”如手牌般使用或打出。", + sbqiaomeng: "趫猛", + sbqiaomeng_info: "当你使用【杀】造成伤害后,若你有〖义从〗,你可以选择一项:⒈弃置受伤角色区域里的一张牌并摸一张牌;⒉获得2点蓄力值。", }; export default translates; diff --git a/character/shenhua/characterReplace.js b/character/shenhua/characterReplace.js index 742f008f9..2ff5f0180 100644 --- a/character/shenhua/characterReplace.js +++ b/character/shenhua/characterReplace.js @@ -11,7 +11,7 @@ const characterReplaces = { dianwei: ["dianwei", "ol_dianwei", "re_dianwei"], xunyu: ["xunyu", "ol_xunyu", "re_xunyu", "sb_xunyu"], sp_zhugeliang: ["sp_zhugeliang", "ol_sp_zhugeliang", "re_sp_zhugeliang", "sb_sp_zhugeliang"], - pangtong: ["pangtong", "ol_pangtong", "re_pangtong", "sb_pangtong"], + pangtong: ["pangtong", "ol_pangtong", "re_pangtong", "ol_sb_pangtong", "sb_pangtong"], re_jsp_pangtong: ["re_jsp_pangtong", "jsrg_pangtong", "sp_pangtong"], taishici: ["taishici", "re_taishici", "ol_sb_taishici"], re_yuanshao: ["re_yuanshao", "ol_yuanshao", "xin_yuanshao", "ol_sb_yuanshao", "star_yuanshao", "sb_yuanshao"], diff --git a/character/sp/character.js b/character/sp/character.js index ca04ccc55..c59422cd4 100644 --- a/character/sp/character.js +++ b/character/sp/character.js @@ -1,4 +1,5 @@ const characters = { + yadan: ["male", "qun", 4, ["olqingya", "oltielun"]], sp_sunce: ["male", "qun", 4, ["olliantao"]], ol_liupi: ["male", "qun", 4, ["olyicheng"]], ol_lukai: ["male", "wu", 3, ["olxuanzhu", "oljiane"]], diff --git a/character/sp/intro.js b/character/sp/intro.js index 5b3c3ddad..5aac7efd8 100644 --- a/character/sp/intro.js +++ b/character/sp/intro.js @@ -1,4 +1,5 @@ const characterIntro = { + yadan: "雅丹,《三国演义》虚构人物,西羌丞相。诸葛亮伐魏时,魏大都督曹真驰书赴羌,西羌国王彻里吉任命雅丹与元帅越吉起兵15万前去增援,中了诸葛亮之计,被伏兵所困。", liupan: "刘磐(生卒年不详),山阳高平人,荆州牧刘表从子。与南阳人黄忠共守长沙攸县。为人骁勇,数次为寇于艾、西安诸县。江东孙策于是分海昏、建昌为左右六县,以东莱太史慈为建昌都尉,治海昏,并督诸将共拒刘磐。于是刘磐绝迹不复为寇。", guotu: "郭图(?-205年),字公则,颍川(治今河南省禹州市)人。东汉末年袁绍帐下谋士。韩馥统冀州时,郭图与荀谌等人奉袁绍之命,说服韩馥让位。袁绍统一河北后,郭图与审配等人力劝袁绍统率大军攻打曹操。袁绍死后,袁尚继位。郭图与辛评为袁谭效力,挑唆袁谭攻击袁尚。建安十年(205年),郭图和袁谭一同被曹操所杀。", tianchou: "田畴(169年或170年-214年或216年),字子泰,东汉右北平郡无终人,东汉末年隐士。田畴好文习武。汉初平年间,其受刘虞派遣去长安,呈送指控公孙赞奏章,献帝大悦,封为骑都尉,田畴不受。携诏返回时,刘虞已被公孙所杀,田畴到刘墓祭拜,被公孙所提,不久释放。田畴回故乡后率家族及随从数百人隐居徐无山,致力农桑,数年间增至5000家。制定法条,兴建学校,一时民风良好,乌桓、鲜卑纷纷与其结交。汉建安二十年(207年),曹操北征乌桓,田畴请为向导。上徐无山、出卢龙、过平冈、登白狼堆、至柳城,曹军大胜,封田畴为亭侯,坚辞不受。曹念田功,四次封赏,终不受,乃拜为议郎。建安二十一年(216年),田畴去世。", diff --git a/character/sp/skill.js b/character/sp/skill.js index 1e6905e08..a26ae8e2e 100644 --- a/character/sp/skill.js +++ b/character/sp/skill.js @@ -2,6 +2,186 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { + //鸭蛋 + olqingya: { + audio: 2, + trigger: { + player: "useCardToPlayered", + }, + filter(event, player) { + if (event.targets.length != 1 || event.target == player || event.target.hasSkill("nodis")) return false; + if (event.card.name != "sha") return false; + const target = event.target; + let left = [], + right = [], + left2 = player, + right2 = player; + while (left2 != target && right2 != target) { + left2 = left2.getPrevious(); + right2 = right2.getNext(); + if (left2 != target) left.push(left2); + if (right2 != target) right.push(right2); + } + if (target == left2) { + for (const i of left) { + if (i.countDiscardableCards(player)) return true; + } + } + if (target == right2) { + for (const i of right) { + if (i.countDiscardableCards(player)) return true; + } + } + return false; + }, + aiJudge(player, target, bool) { + let left = [], + right = [], + left2 = player, + right2 = player, + left3 = false, + right3 = false; + let eff_left = 0, + eff_right = 0; + while (left2 != target && right2 != target) { + left2 = left2.getPrevious(); + right2 = right2.getNext(); + if (left2 != target) left.push(left2); + if (right2 != target) right.push(right2); + } + const card = { name: "guohe", position: "h" }; + if (target == left2) { + for (const i of left) { + if (i.countDiscardableCards(player)) { + left3 = true; + eff_left += get.effect(i, card, player, player); + } + } + } + if (target == right2) { + for (const i of right) { + if (i.countDiscardableCards(player)) { + right3 = true; + eff_right += get.effect(i, card, player, player); + } + } + } + if (left3 && right3) { + if (!bool) return Math.max(eff_left, eff_right); + if (eff_left > Math.max(0, eff_right)) return "↖顺时针"; + if (eff_right > Math.max(0, eff_left)) return "逆时针↗"; + return "cancel2"; + } else if (left3) { + if (bool) return eff_left > 0 ? "↖顺时针" : "cancel2"; + return eff_left; + } else if (right3) { + if (bool) return eff_right > 0 ? "逆时针↗" : "cancel2"; + return eff_right; + } else return bool ? "cancel2" : 0; + }, + async cost(event, trigger, player) { + const choices = []; + const target = trigger.target; + let left = [], + right = [], + left2 = player, + right2 = player; + while (left2 != target && right2 != target) { + left2 = left2.getPrevious(); + right2 = right2.getNext(); + if (left2 != target) left.push(left2); + if (right2 != target) right.push(right2); + } + if (target == left2) { + for (const i of left) { + if (lib.filter.targetEnabled2(trigger.card, player, i)) { + choices.push("↖顺时针"); + break; + } + } + } + if (target == right2) { + for (const i of right) { + if (lib.filter.targetEnabled2(trigger.card, player, i)) { + choices.push("逆时针↗"); + break; + } + } + } + choices.push("cancel2"); + const result = await player + .chooseControl(choices) + .set("prompt", get.prompt("olqingya")) + .set("prompt2", `弃置自己和${get.translation(trigger.target)}某个方向之间的所有角色(不包括你与其)各一张手牌`) + .set("choices", choices) + .set("ai", () => { + var evt = _status.event.getTrigger(); + return lib.skill.olqingya.aiJudge(evt.player, evt.target, true); + }) + .forResult(); + if (result.control !== "cancel2") { + event.result = { + bool: true, + cost_data: { + control: result.control, + }, + }; + } + }, + async content(event, trigger, player) { + const result = event.cost_data; + const targets = []; + game.log(player, "选择了", "#g" + result.control); + if (result.control == "↖顺时针") { + let current = player.getPrevious(); + while (current != trigger.target) { + if (current.countDiscardableCards(player)) targets.push(current); + current = current.getPrevious(); + } + } else { + let current = player.getNext(); + while (current != trigger.target) { + if (current.countDiscardableCards(player)) targets.push(current); + current = current.getNext(); + } + } + for (const current of targets) { + if (!current.countDiscardableCards(player)) continue; + player.line(current); + await player.discardPlayerCard(current, true); + } + await game.asyncDelayx(); + }, + ai: { + effect: { + player_use(card, player, target) { + if (!target || player._olqingya_judging || ui.selected.targets.length || player == target || target.hasSkill("nodis")) return; + if (typeof card != "object" || card.name != "sha") return false; + player._olqingya_judging = true; + var effect = lib.skill.olqingya.aiJudge(player, target); + delete player._olqingya_judging; + if (effect > 0) return [1, effect / Math.max(0.01, get.attitude(player, player))]; + }, + }, + }, + }, + oltielun: { + audio: 2, + mod: { + globalFrom(from, to, distance) { + let usedCount = 0; + const stats = from.stat.slice(); + stats.reverse(); + for (const stat of stats) { + Object.values(stat.card).forEach(cnt => { + usedCount += cnt; + }); + if (stat.isRound) break; + } + return distance - usedCount; + }, + }, + }, //SP孙策 olliantao: { audio: 2, diff --git a/character/sp/sort.js b/character/sp/sort.js index 2986fc3b2..896b3d875 100644 --- a/character/sp/sort.js +++ b/character/sp/sort.js @@ -1,7 +1,7 @@ const characterSort = { sp_tianji: ["sunhao", "liuxie", "caoang", "hetaihou", "sunluyu", "ol_wangrong", "zuofen", "ol_bianfuren", "qinghegongzhu", "tengfanglan", "ruiji", "caoxiancaohua", "caoyu"], sp_sibi: ["ol_lukai", "yangxiu", "guotu", "chenlin", "chengyu", "shixie", "fuwan", "wangyun", "zhugejin", "simalang", "maliang", "buzhi", "dongyun", "kanze", "sunqian", "xizhicai", "sunshao", "duxi", "jianggan", "ol_dengzhi", "ol_yangyi", "ol_dongzhao", "ol_chendeng", "jin_yanghu", "wangyan", "xiahouxuan", "quhuang", "zhanghua", "wangguan", "sunhong", "caoxi", "tianchou"], - sp_tianzhu: ["liyi", "zhangyan", "niujin", "hejin", "hansui", "wutugu", "yanbaihu", "shamoke", "zhugedan", "huangzu", "gaogan", "tadun", "fanjiangzhangda", "ahuinan", "dongtuna", "ol_wenqin"], + sp_tianzhu: ["yadan", "liyi", "zhangyan", "niujin", "hejin", "hansui", "wutugu", "yanbaihu", "shamoke", "zhugedan", "huangzu", "gaogan", "tadun", "fanjiangzhangda", "ahuinan", "dongtuna", "ol_wenqin"], sp_nvshi: ["ol_dingshangwan", "lingju", "guanyinping", "zhangxingcai", "mayunlu", "dongbai", "zhaoxiang", "ol_zhangchangpu", "daxiaoqiao", "jin_guohuai", "ol_hujinding"], sp_shaowei: ["simahui", "zhangbao", "zhanglu", "zhugeguo", "xujing", "zhangling", "huangchengyan", "zhangzhi", "lushi"], sp_huben: ["duanjiong", "ol_mengda", "caohong", "xiahouba", "zhugeke", "zumao", "wenpin", "litong", "mazhong", "heqi", "quyi", "luzhi", "yuejin", "dingfeng", "wuyan", "ol_zhuling", "tianyu", "huojun", "zhaoyǎn", "dengzhong", "ol_furong", "macheng", "ol_zhangyì", "ol_zhujun", "maxiumatie", "luoxian", "ol_huban", "haopu", "ol_qianzhao"], diff --git a/character/sp/translate.js b/character/sp/translate.js index bd5d55335..e34f4c99a 100644 --- a/character/sp/translate.js +++ b/character/sp/translate.js @@ -1239,6 +1239,11 @@ const translates = { sp_sunce_prefix: "SP", olliantao: "连讨", olliantao_info: "出牌阶段开始时,你可以令一名其他角色选择一个颜色,然后你依次将此颜色的所有手牌当作【决斗】对其使用直到有一方进入濒死状态,然后你摸X张牌(X为你本次以此法造成的伤害数)。若没有角色因本次技能结算受到伤害,你摸三张牌,本回合手牌上限+3且本回合你不能使用【杀】。", + yadan: "雅丹", + olqingya: "倾轧", + olqingya_info: "当你使用【杀】指定唯一目标后,你可从逆时针方向和顺时针方向中选择一个你与其之间角色最少的方向。你弃置该方向下你与其之间的角色各一张手牌,然后你可以于本回合下个阶段结束时使用其中一张牌。", + oltielun: "铁轮", + oltielun_info: "锁定技。你计算与其他角色的距离-X(X为你本轮使用的牌数)。", }; export default translates; diff --git a/character/sp2/voices.js b/character/sp2/voices.js index 23911b59d..7ff2f4a48 100644 --- a/character/sp2/voices.js +++ b/character/sp2/voices.js @@ -1,4 +1,9 @@ export default { + "#starliangyan1": "佳燕并头语,不恋雕梁而归于万里。", + "#starliangyan2": "灵禽非醴泉不饮,非积善之家不栖。", + "#starminghui1": "大智若愚,女子之锦绣常隐于华服。", + "#starminghui2": "知者不惑,心有明镜以照人。", + "#star_zhangchunhua:die": "我何为也,竟称可憎之老物?", "#xiongsuan1": "朝中无一是男儿,谁敢拦我二人!", "#xiongsuan2": "挟持天子,执掌重兵,天下可图!", "#liqueguosi:die": "文和之言,诚不欺我……", diff --git a/character/standard/characterReplace.js b/character/standard/characterReplace.js index e77df2bb3..abf7368cb 100644 --- a/character/standard/characterReplace.js +++ b/character/standard/characterReplace.js @@ -31,7 +31,7 @@ const characterReplaces = { huatuo: ["huatuo", "re_huatuo", "old_huatuo"], huaxiong: ["huaxiong", "re_huaxiong", "old_huaxiong", "sb_huaxiong", "ol_huaxiong"], yuanshu: ["yuanshu", "re_yuanshu", "yl_yuanshu", "old_yuanshu", "ol_yuanshu", "star_yuanshu"], - gongsunzan: ["gongsunzan", "re_gongsunzan", "dc_gongsunzan", "xin_gongsunzan"], + gongsunzan: ["gongsunzan", "re_gongsunzan", "dc_gongsunzan", "xin_gongsunzan", "sb_gongsunzan"], re_lidian: ["re_lidian", "old_re_lidian", "junk_lidian"], sunhao: ["sunhao", "std_sunhao"], lvlingqi: ["lvlingqi", "std_lvlingqi"], diff --git a/character/tw/character.js b/character/tw/character.js index 5d6e9cd83..a24acb5c4 100644 --- a/character/tw/character.js +++ b/character/tw/character.js @@ -1,4 +1,6 @@ const characters = { + tw_zhugejun: ["male", "qun", 3, ["twshouzhu", "twdaigui", "twcairu"]], + simafu: ["male", "wei", 3, ["xunde", "chenjie"]], tw_yanliang: ["male", "qun", 4, ["twduwang", "twylyanshi"]], tw_wenchou: ["male", "qun", 4, ["twjuexing", "twxiayong"]], tw_yuantan: ["male", "qun", 4, ["twqiaosi", "twbaizu"]], diff --git a/character/tw/intro.js b/character/tw/intro.js index 06c739de8..0b8d9f9e0 100644 --- a/character/tw/intro.js +++ b/character/tw/intro.js @@ -1,4 +1,5 @@ const characterIntro = { + zhugejun: "诸葛均(生卒年不详),琅邪阳都(今山东省沂南县)人,诸葛珪之子。三国时吴大将军诸葛瑾、蜀汉丞相诸葛亮之弟。在蜀汉官至长水校尉。", yanliang: "颜良(?~200年),字公骥,安平郡堂阳县(今河北省新河县)人。东汉末年河北将领。颜良性格促狭,虽骁勇不可独任,为一夫之勇。官渡之战,袁绍令颜良进攻白马(今河南滑县)。曹操采用军师荀攸“声东击西、轻兵掩袭”之计,大败袁军,颜良本人也被关羽亲自斩杀死,白马之围遂解。据说颜之推是其后人。", wenchou: "文丑(?~200年),东汉末年河北将领。文丑为一夫之勇。建安五年(200年),带领左将军刘备进驻延津,误中曹操军师荀攸的“饵敌”之计,其麾下“五六千骑”惨败于“不满六百”的曹军骑兵。文丑本人也死于乱军之中,葬于河南省禹州市。", yuantan: "袁谭(?-205年),字显思,汝南郡汝阳县,袁绍长子,曾任青州刺史。建安元年(196年),击败田楷、孔融,完全占据青州。袁绍去世后,审配等伪立遗令,拥立袁尚为继承人,袁谭不能继位,心怀愤恨。后袁谭、袁尚二人的矛盾彻底爆发,袁谭联合曹操共同攻打袁尚。建安十年,曹操兴兵进攻南皮,袁谭奋力抵抗,终于在曹操急攻之下战败,为曹纯麾下虎豹骑所杀。", diff --git a/character/tw/skill.js b/character/tw/skill.js index 943707783..537777c90 100644 --- a/character/tw/skill.js +++ b/character/tw/skill.js @@ -2,6 +2,395 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { + //诸葛均 + twshouzhu: { + audio: 2, + global: "beOfOneHeart", + oneHeart: true, + trigger: { + player: "phaseUseBegin", + }, + filter(event, player) { + return player.getStorage("beOfOneHeartWith").some(target => { + return target.isIn(); + }); + }, + logTarget(event, player) { + return player.getStorage("beOfOneHeartWith").filter(target => { + return target.isIn(); + }); + }, + forced: true, + locked: false, + async content(event, trigger, player) { + const targets = player.getStorage("beOfOneHeartWith").filter(target => { + return target.isIn(); + }); + let count = 0; + for (const current of targets) { + if (!current.isIn()) continue; + const cards = await current + .chooseToGive(`${get.translation(player)}对你发动了【受嘱】`, "作为其的同心角色,是否交给其至多三张牌?", player, "he", [1, 3]) + .set("ai", card => { + if (!get.event("goon")) return -get.value(card); + if (ui.selected.cards.length < 2) return 4.5 + ui.selected.cards.length - get.value(card) + get.player().getUseValue(card) / 5; + return 0; + }) + .set("goon", get.attitude(current, player) > 0) + .forResultCards(); + if (cards && cards.length) count += cards.length; + } + if (count < 2) return; + await game.asyncDraw(targets); + await game.asyncDelay(); + targets.unshift(player); + for (const current of targets) { + const cards = get.cards(count); + await game.cardsGotoOrdering(cards); + const next = current.chooseToMove(); + next.set("list", [["牌堆底", cards], ["弃牌堆"]]); + next.set("prompt", "受嘱:点击排列牌置于牌堆底的顺序,或置入弃牌堆"); + next.set("processAI", list => { + const cards = list[0][1], + player = get.player(); + let bottom = [], + discard = []; + cards.sort((a, b) => get.value(b, player) - get.value(a, player)); + while (cards.length) { + if (get.value(cards[0], player) <= 5) break; + bottom.unshift(cards.shift()); + } + discard = cards; + return [bottom, discard]; + }); + const { moved } = await next.forResult(); + const bottom = moved[0]; + const discard = moved[1]; + if (bottom.length) { + await game.cardsGotoPile(bottom); + } + current.popup(get.cnNumber(bottom.length) + "下"); + game.log(current, "将" + get.cnNumber(bottom.length) + "张牌置于牌堆底"); + if (discard.length) { + await game.cardsDiscard(discard); + game.log(current, "将", discard, "置入了弃牌堆"); + } + await game.asyncDelayx(); + } + }, + }, + beOfOneHeart: { + trigger: { player: "phaseBegin" }, + filter(event, player) { + if (!game.hasPlayer(current => current !== player)) return false; + return player.getSkills().some(skill => { + const info = get.info(skill); + if (!info || !info.oneHeart) return false; + return true; + }); + }, + forced: true, + ruleSkill: true, + async content(event, trigger, player) { + const targets = await player.chooseTarget("请选择你的“同心”角色", lib.filter.notMe).forResultTargets(); + if (!targets || !targets.length) return; + player.line(targets, "green"); + game.log(player, "选择了", targets, "作为自己的同心角色"); + player.markSkill("beOfOneHeart"); + player.storage.beOfOneHeartWith = targets; + player + .when({ player: "phaseBegin" }, false) + .assign({ firstDo: true }) + .then(() => { + delete player.storage.beOfOneHeartWith; + player.unmarkSkill("beOfOneHeart"); + }) + .finish(); + await game.asyncDelayx(); + }, + marktext: "❤", + intro: { + name: "同心", + content(_, player) { + return `当前同心角色:${get.translation(player.getStorage("beOfOneHeartWith"))}`; + }, + } + }, + twdaigui: { + audio: 2, + trigger: { + player: "phaseUseEnd", + }, + filter(event, player) { + if (!player.countCards("h")) return false; + const color = get.color(player.getCards("h")[0]); + return player.getCards("h").every(card => { + return get.color(card) === color; + }); + }, + async cost(event, trigger, player) { + const maxLimit = player.countCards("h"); + event.result = await player + .chooseTarget(get.prompt("twdaigui"), `选择至多${get.cnNumber(maxLimit)}名角色并亮出牌堆底等量的牌,令这些角色依次选择并获得其中一张。`, [1, maxLimit]) + .set("ai", target => { + const player = get.player(); + return get.attitude(player, target) * (player === target && player.needsToDiscard(1) ? 0.4: 1); + }) + .forResult(); + }, + async content(event, trigger, player) { + const { targets } = event; + const cards = get.bottomCards(targets.length); + await game.cardsGotoOrdering(cards); + const videoId = lib.status.videoId++; + game.addVideo("cardDialog", null, ["待归", get.cardsInfo(cards), videoId]); + game.broadcastAll( + function (cards, videoId) { + const dialog = ui.create.dialog("待归", cards, true); + _status.dieClose.push(dialog); + dialog.videoId = videoId; + }, + cards, + videoId + ); + await game.asyncDelay(); + const chooseableCards = cards.slice(); + for (const current of targets) { + if (!current.isIn() || !chooseableCards.length) continue; + const links = await current + .chooseButton(true) + .set("dialog", videoId) + .set("closeDialog", false) + .set("dialogdisplay", true) + .set("cardFilter", chooseableCards.slice()) + .set("filterButton", button => { + return get.event("cardFilter").includes(button.link); + }) + .set("ai", button => { + return get.value(button.link, _status.event.player); + }) + .forResultLinks(); + + const [card] = links; + if (card) { + current.gain(card, "gain2"); + chooseableCards.remove(card); + } + const capt = `${get.translation(current)}选择了${get.translation(card)}`; + game.broadcastAll( + function (card, id, name, capt) { + const dialog = get.idDialog(id); + if (dialog) { + dialog.content.firstChild.innerHTML = capt; + for (let i = 0; i < dialog.buttons.length; i++) { + if (dialog.buttons[i].link == card) { + dialog.buttons[i].querySelector(".info").innerHTML = name; + break; + } + } + game.addVideo("dialogCapt", null, [dialog.videoId, dialog.content.firstChild.innerHTML]); + } + }, + card, + videoId, + (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); + })(current), + capt + ); + } + if (chooseableCards.length) await game.cardsDiscard(chooseableCards); + game.broadcastAll(function (id) { + const dialog = get.idDialog(id); + if (dialog) { + dialog.close(); + _status.dieClose.remove(dialog); + } + }, videoId); + game.addVideo("cardDialog", null, videoId); + }, + }, + twcairu: { + audio: 2, + enable: ["chooseToUse", "chooseToRespond"], + filter(event, player) { + return ["huogong", "tiesuo", "wuzhong"].some(name => { + if (player.getStorage("twcairu_used").includes(name)) return false; + return event.filterCard({ name }, player, event); + }); + }, + chooseButton: { + dialog(event, player) { + const list = ["huogong", "tiesuo", "wuzhong"] + .filter(name => { + if (player.getStorage("twcairu_used").includes(name)) return false; + return event.filterCard({ name }, player, event); + }) + .map(name => [get.translation(get.type(name)), "", name]); + return ui.create.dialog("才濡", [list, "vcard"]); + }, + check(button) { + return get.player().getUseValue({ name: button.link[2] }); + }, + backup(links, player) { + return { + audio: "twcairu", + filterCard(card, player) { + const color = get.color(card, player); + return !ui.selected.cards.length || get.color(ui.selected.cards[0]) != color; + }, + selectCard: 2, + complexCard: true, + popname: true, + check(card) { + return 5 - get.value(card); + }, + position: "hes", + viewAs: { name: links[0][2] }, + precontent() { + delete event.result.skill; + player.logSkill("twcairu"); + if (!player.storage.twcairu_used) { + player.storage.twcairu_used = []; + player.when({ global: "phaseAfter" }).then(() => { + delete player.storage.twcairu_used; + }); + } + player.storage.twcairu_used.add(event.result.card.name); + }, + }; + }, + prompt(links, player) { + return "将两张颜色不同的牌当【" + get.translation(links[0][2]) + "】使用"; + }, + }, + subSkill: { backup: {} }, + ai: { + order(item, player) { + if (!player || _status.event.type != "phase") return 0.001; + let max = 0, + names = ["huogong", "tiesuo", "wuzhong"].filter(name => { + if (player.getStorage("twcairu_used").includes(name)) return false; + return event.filterCard({ name }, player, event); + }); + if (!names.length) return 0; + names = names.map(namex => ({ name: namex })); + names.forEach(card => { + if (player.getUseValue(card) > 0) { + let temp = get.order(card); + if (temp > max) max = temp; + } + }); + if (max > 0) max += 0.3; + return max; + }, + result: { player: 1 }, + }, + }, + //司马孚 + xunde: { + audio: 2, + trigger: { global: "damageEnd" }, + filter(event, player) { + return event.player.isIn() && get.distance(player, event.player) <= 1; + }, + logTarget: "player", + check(event, player) { + return get.attitude(player, event.player) > 0 && (!event.source || get.attitude(player, event.source) < 0); + }, + content() { + "step 0"; + player.judge().set("callback", function () { + if (event.judgeResult.number > 5) { + var player = event.getParent(2)._trigger.player; + if (get.position(card, true) == "o") player.gain(card, "gain2"); + } + }); + "step 1"; + if (result.number < 7) { + var source = trigger.source; + if (source && source.isIn() && source.countCards("h") > 0) { + player.line(source); + source.chooseToDiscard("h", true); + } + } + }, + }, + chenjie: { + audio: 2, + trigger: { global: "judge" }, + filter(event, player) { + var suit = get.suit(event.player.judging[0], event.player); + return ( + player.countCards("hes", function (card) { + if (_status.connectMode && get.position(card) != "e") return true; + return get.suit(card) == suit; + }) > 0 + ); + }, + popup: false, + preHidden: true, + async cost(event, trigger, player) { + var suit = get.suit(trigger.player.judging[0], trigger.player); + const { + result: { bool, cards }, + } = await player + .chooseCard(get.translation(trigger.player) + "的" + (trigger.judgestr || "") + "判定为" + get.translation(trigger.player.judging[0]) + "," + get.prompt("chenjie"), "hes", function (card) { + if (get.suit(card) != _status.event.suit) return false; + var player = _status.event.player; + var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); + if (mod2 != "unchanged") return mod2; + var mod = game.checkMod(card, player, "unchanged", "cardRespondable", player); + if (mod != "unchanged") return mod; + return true; + }) + .set("ai", function (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; + } + }) + .set("judging", trigger.player.judging[0]) + .set("suit", suit) + .setHiddenSkill("chenjie"); + if (bool) event.result = { bool, cost_data: { cards } }; + }, + async content(event, trigger, player) { + const result = event.cost_data; + const card = result.cards[0]; + await player.respond(result.cards, "highlight", "chenjie", "noOrdering"); + if (trigger.player.judging[0].clone) { + trigger.player.judging[0].clone.classList.remove("thrownhighlight"); + game.broadcast(function (card) { + if (card.clone) { + card.clone.classList.remove("thrownhighlight"); + } + }, trigger.player.judging[0]); + game.addVideo("deletenode", player, get.cardsInfo([trigger.player.judging[0].clone])); + } + await game.cardsDiscard(trigger.player.judging[0]); + trigger.player.judging[0] = card; + trigger.orderingCards.add(card); + game.log(trigger.player, "的判定牌改为", card); + await player.draw(2); + }, + ai: { + rejudge: true, + tag: { + rejudge: 0.1, + }, + }, + }, //颜良文丑,但是颜良+文丑 twduwang: { audio: 3, diff --git a/character/tw/sort.js b/character/tw/sort.js index d09ed771b..3624e600f 100644 --- a/character/tw/sort.js +++ b/character/tw/sort.js @@ -1,5 +1,5 @@ const characterSort = { - tw_sp: ["tw_yanliang", "tw_wenchou", "tw_yuantan", "tw_zhangzhao", "tw_zhanghong", "tw_fuwan", "tw_yujin", "tw_zhaoxiang", "tw_hucheer", "tw_hejin", "tw_mayunlu", "tw_re_caohong", "tw_zangba", "tw_liuhong", "tw_tianyu", "jiachong", "duosidawang", "wuban", "yuejiu", "tw_caocao", "tw_zhangmancheng", "tw_caozhao", "tw_wangchang", "tw_puyangxing", "tw_jiangji", "tw_niujin", "tw_xiahouen", "tw_xiahoushang", "tw_zhangji", "tw_zhangnan", "tw_fengxí", "tw_furong", "tw_liwei", "tw_yangyi", "tw_daxiaoqiao", "tw_dengzhi", "tw_baoxin", "tw_bingyuan", "tw_fanchou", "tw_haomeng", "tw_huchuquan", "tw_jianshuo", "tw_jiling", "tw_liufuren", "tw_liuzhang", "tw_mateng", "tw_niufudongxie", "tw_qiaorui", "tw_weixu", "tw_yanxiang", "tw_yufuluo", "tw_zhangning", "tw_dengzhi", "tw_yangyi", "tw_yangang", "tw_gongsunfan"], + tw_sp: ["simafu", "tw_zhugejun", "tw_yanliang", "tw_wenchou", "tw_yuantan", "tw_zhangzhao", "tw_zhanghong", "tw_fuwan", "tw_yujin", "tw_zhaoxiang", "tw_hucheer", "tw_hejin", "tw_mayunlu", "tw_re_caohong", "tw_zangba", "tw_liuhong", "tw_tianyu", "jiachong", "duosidawang", "wuban", "yuejiu", "tw_caocao", "tw_zhangmancheng", "tw_caozhao", "tw_wangchang", "tw_puyangxing", "tw_jiangji", "tw_niujin", "tw_xiahouen", "tw_xiahoushang", "tw_zhangji", "tw_zhangnan", "tw_fengxí", "tw_furong", "tw_liwei", "tw_yangyi", "tw_daxiaoqiao", "tw_dengzhi", "tw_baoxin", "tw_bingyuan", "tw_fanchou", "tw_haomeng", "tw_huchuquan", "tw_jianshuo", "tw_jiling", "tw_liufuren", "tw_liuzhang", "tw_mateng", "tw_niufudongxie", "tw_qiaorui", "tw_weixu", "tw_yanxiang", "tw_yufuluo", "tw_zhangning", "tw_dengzhi", "tw_yangyi", "tw_yangang", "tw_gongsunfan"], tw_yunchouzhi: ["tw_wangcan", "tw_dongzhao", "tw_bianfuren", "tw_feiyi", "tw_chenzhen", "tw_xunchen"], tw_yunchouxin: ["tw_wangling", "tw_huojun", "tw_wujing", "tw_zhouchu"], tw_yunchouren: ["tw_xujing", "tw_qiaogong"], diff --git a/character/tw/translate.js b/character/tw/translate.js index 4cf79bb6f..fdeada1c8 100644 --- a/character/tw/translate.js +++ b/character/tw/translate.js @@ -686,6 +686,19 @@ const translates = { twqiaosi_info: "结束阶段,你可以获得由其他角色区域直接置入或经由处理区置入弃牌堆的所有牌,然后若你以此法获得的牌数小于你的体力值,则你失去1点体力。", twbaizu: "败族", twbaizu_info: "锁定技。结束阶段,若你已受伤且你有手牌,则你须选择X名有手牌的其他角色(X为你的体力值),你与这些角色同时弃置一张手牌,然后你对与你弃置牌类别相同的所有其他角色各造成1点伤害。历战:〖败族〗目标选择数+1。", + tw_zhugejun: "诸葛均", + twshouzhu: "受嘱", + twshouzhu_info: "出牌阶段开始时,你的同心角色可交给你至多三张牌。若你以此法得到的牌数X不小于2,其摸一张牌,然后执行同心:观看牌堆顶X张牌,然后将其中任意张牌以任意顺序置于牌堆底,将其余的牌置入弃牌堆。", + twdaigui: "待归", + twdaigui_info: "出牌阶段结束时,若你手牌的颜色均相同,你可以选择至多Y名角色并亮出牌堆底等量的牌,然后这些角色依次选择并获得其中一张(Y为你的手牌数)。", + twcairu: "才濡", + twcairu_info: "每回合每种牌名限一次。你可以将两张颜色不同的牌当【火攻】、【铁索连环】或【无中生有】使用。", + simafu: "TW司马孚", + simafu_prefix: "TW", + xunde: "勋德", + xunde_info: "一名角色受到伤害后,若你至其的距离不大于1,则你可判定。若判定结果:大于5,你令该角色获得判定牌;小于7,你令伤害来源弃置一张手牌。", + chenjie: "臣节", + chenjie_info: "一名角色的判定牌生效前,你可打出一张花色相同的牌。系统将你打出的牌作为新判定牌,将原判定牌置入弃牌堆。然后你摸两张牌。", }; export default translates; diff --git a/character/tw/voices.js b/character/tw/voices.js index cfefd9867..233d3d879 100644 --- a/character/tw/voices.js +++ b/character/tw/voices.js @@ -1,4 +1,9 @@ export default { + "#xunde1": "陛下所托,臣必尽心尽力!", + "#xunde2": "纵吾荏弱难持,亦不推诿君命!", + "#chenjie1": "臣心怀二心,不可事君也。", + "#chenjie2": "竭力致身,以尽臣节。", + "#simafu:die": "身辅六公,亦难报此恩……", "#twduwang1": "阿瞒聚众来犯,吾一人可挡万敌!", "#twduwang2": "勇绝河北,吾足以一柱擎天!", "#twylyanshi1": "今破曹军,明日当直取许都!", diff --git a/character/xianding/character.js b/character/xianding/character.js index 3df6be7a7..fa813f3ca 100644 --- a/character/xianding/character.js +++ b/character/xianding/character.js @@ -1,4 +1,5 @@ const characters = { + dc_sb_zhugejin: ["male", "wu", 3, ["dcsbtaozhou", "dcsbhoude"]], dc_sb_jiaxu: ["male", "qun", 3, ["dcsbsushen", "dcsbfumou"]], guanyue: ["male", "shu", 4, ["dcshouzhi", "dcfenhui"]], sp_zhenji: ["female", "qun", 3, ["dcjijie", "dchuiji"]], diff --git a/character/xianding/characterReplace.js b/character/xianding/characterReplace.js index 1253ae7f4..6b585cbe4 100644 --- a/character/xianding/characterReplace.js +++ b/character/xianding/characterReplace.js @@ -13,6 +13,7 @@ const characterReplaces = { caofang: ["caofang", "jsrg_caofang"], caomao: ["caomao", "mb_caomao"], sp_zhenji: ["sp_zhenji", "jsrg_zhenji"], + zhugejin: ["zhugejin", "dc_sb_zhugejin"], }; export default characterReplaces; diff --git a/character/xianding/skill.js b/character/xianding/skill.js index d3f5e4939..f5b9d6a71 100644 --- a/character/xianding/skill.js +++ b/character/xianding/skill.js @@ -1,7 +1,250 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; +import cards from "../sp2/card.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { + //诸葛瑾 + dcsbtaozhou: { + audio: 2, + enable: "phaseUse", + filter(event, player) { + return game.hasPlayer(current => { + if (current.hasSkill("dcsbzijin")) return false; + return current.countCards("h") > 0 && current !== player; + }); + }, + derivation: "dcsbzijin", + chooseButton: { + dialog() { + return ui.create.dialog("###讨州###请选择一个数字(对其他角色不可见)"); + }, + chooseControl(event, player) { + const list = [1, 2, 3]; + list.push("cancel2"); + return list; + }, + check() { + const event = get.event(), player = get.player(); + if ( + game.hasPlayer(current => { + return current !== player && get.attitude(player, current) > 0; + }) + ) + return [0, 1, 2].randomGet(); + if (player.hasShan()) return 2; + const rand = event.getRand(); + if (rand < 0.2) return 0; + if (rand < 0.5) return 1; + return 2; + }, + backup(result, player) { + return { + audio: "dcsbtaozhou", + chosenNumber: result.index + 1, + filterCard: () => false, + selectCard: -1, + filterTarget(card, player, target) { + if (target.hasSkill("dcsbzijin")) return false; + return target.countCards("h") > 0 && target !== player; + }, + async content(event, trigger, player) { + const [target] = event.targets; + const chosenNumber = get.info("dcsbtaozhou_backup").chosenNumber; + const cards = await target + .chooseToGive(`${get.translation(player)}对你发动了【讨州】`, "你可以交给其至多三张手牌", [1, 3]) + .set("ai", card => { + if (get.event("att") > 0) { + if (get.event("chosenNumber") < ui.selected.cards.length + (get.event("getRand")() < 0.5)) { + return 5 - get.value(card); + } + return 0; + } + return -get.value(card); + }) + .set("att", get.attitude(target, player)) + .set("chosenNumber", chosenNumber) + .forResultCards(); + const givenCount = (cards && cards.length) || 0; + const delta = Math.abs(givenCount - chosenNumber); + if (givenCount >= chosenNumber) { + await game.asyncDraw([player, target]); + } else { + target.addSkill("dcsbtaozhou_debuff"); + target.addMark("dcsbtaozhou_debuff", delta, false); + } + if (delta >= 2) { + const sha = get.autoViewAs({ name: "sha" }); + if (target.canUse(sha, player, false)) { + await target.addSkills("dcsbzijin"); + await target.useCard(sha, player, "noai"); + } + } + const roundNumberToRestore = game.roundNumber + chosenNumber; + player.tempBanSkill("dcsbtaozhou", "forever"); + player + .when({ global: "roundStart" }) + .filter(() => { + return game.roundNumber >= roundNumberToRestore; + }) + .assign({ + firstDo: true, + }) + .then(() => { + delete player.storage[`temp_ban_dcsbtaozhou`]; + }); + }, + ai: { + result: { + player: 0.5, + target() { + const chosenNumber = get.info("dcsbtaozhou_backup").chosenNumber; + if (chosenNumber > 1) return -1; + return 0; + }, + }, + }, + }; + }, + prompt: () => "请选择【讨州】的目标", + }, + subSkill: { + backup: {}, + debuff: { + trigger: { player: "damageBegin3" }, + forced: true, + charlotte: true, + async content(event, trigger, player) { + trigger.num++; + player.removeMark("dcsbtaozhou_debuff", 1, false); + if (!player.countMark("dcsbtaozhou_debuff")){ + player.removeSkill("dcsbtaozhou_debuff"); + } + }, + intro: { + content: "下&次受到伤害时,伤害+1", + }, + }, + }, + ai: { + order: 9.6, + result: { + player: 1, + }, + }, + }, + dcsbzijin: { + audio: 2, + trigger: { + player: "useCardAfter", + }, + filter(event, player) { + return !game.hasPlayer2(current => { + return current.hasHistory("damage", evt => evt.card === event.card); + }, true); + }, + forced: true, + async content(event, trigger, player) { + const bool = await player + .chooseToDiscard("自矜:弃置一张牌或失去1点体力", "he") + .set("ai", card => { + const player = get.player(); + if (get.effect(player, { name: "losehp" }, player, player) > 0) return 0; + return 5 - get.value(card); + }) + .forResultBool(); + if (!bool) await player.loseHp(); + }, + ai: { + effect: { + player_use(card, player) { + if (get.effect(player, { name: "losehp" }, player) > 0) return; + if (!get.tag(card, "damage") && get.value(card) < 5) + return [ + 0.2, + player.hasCard(card => { + return get.value(card) < 3; + }, "he") + ? -0.1 + : -2, + ]; + }, + }, + neg: true, + }, + }, + dcsbhoude: { + audio: 2, + trigger: { + target: "useCardToTargeted", + }, + filter(event, player) { + const phaseUse = event.getParent("phaseUse"); + if (!phaseUse || phaseUse.name !== "phaseUse" || phaseUse.player === player) return false; + const filter = card => { + const color = get.color(card); + return (get.name(card) === "sha" && color === "red") || (get.type(card) === "trick" && color === "black"); + }; + const evt = event.getParent(); + if ( + game + .getGlobalHistory( + "useCard", + evt => { + return filter(evt.card); + }, + evt + ) + .indexOf(evt) !== 0 + ) + return false; + return filter(event.card); + }, + async cost(event, trigger, player) { + const target = trigger.player; + let result; + if (get.name(trigger.card) === "sha") { + result = await player + .chooseToDiscard(get.prompt("dcsbhoude", target), `弃置一张牌,令${get.translation(trigger.card)}对你无效。`, "chooseonly", "he") + .set("ai", card => { + if (!get.event("goon")) return 0; + return 5.5 - get.value(card); + }) + .set("goon", get.effect(player, trigger.card, target, player) < 0) + .forResult(); + } else { + result = await player + .choosePlayerCard(`###${get.prompt("dcsbhoude", target)}###
弃置其的一张牌,令${get.translation(trigger.card)}对你无效。
`, target, "he") + .set("ai", button => { + if (!get.event("goon")) return 0; + const val = get.buttonValue(button); + if (get.attitude(get.player(), get.owner(button.link)) > 0) return -val; + return val; + }) + .set("goon", get.effect(player, trigger.card, target, player) < 0) + .forResult(); + } + if (result.bool) { + event.result = { + bool: true, + cost_data: { + cards: result.cards, + links: result.links, + }, + }; + } + }, + logTarget: "player", + async content(event, trigger, player) { + const target = trigger.player; + const result = event.cost_data; + if (result.links && result.links.length) { + await target.discard(result.links, "notBySelf").set("discarder", player); + } else { + await player.discard(result.cards); + } + trigger.excluded.add(player); + }, + }, //谋贾诩 dcsbsushen: { unique: true, @@ -14413,6 +14656,7 @@ const skills = { player.changeZhuanhuanji("bazhan"); "step 1"; var target = event.recover; + var cards = event.cards; if (result.bool && result.cards && result.cards.length) { cards = result.cards; } diff --git a/character/xianding/sort.js b/character/xianding/sort.js index f21c943ed..d835acbee 100644 --- a/character/xianding/sort.js +++ b/character/xianding/sort.js @@ -14,6 +14,7 @@ const characterSort = { sp2_gaoshan: ["wanglang", "liuhui", "zhangjian"], sp2_wumiao: ["wu_zhugeliang", "wu_luxun", "wu_guanyu"], sp2_mouding: ["dc_sb_jiaxu", "dc_sb_lusu", "dc_sb_zhouyu", "dc_sb_simayi"], + sp2_zijing: ["dc_sb_zhugejin"], }; const characterSortTranslate = { @@ -32,6 +33,7 @@ const characterSortTranslate = { sp2_gaoshan: "高山仰止", sp2_qifu: "祈福", sp2_mouding: "谋定天下", + sp2_zijing: "子敬邀刀", }; export { characterSort, characterSortTranslate }; diff --git a/character/xianding/translate.js b/character/xianding/translate.js index a4d977187..f62bcc3e4 100644 --- a/character/xianding/translate.js +++ b/character/xianding/translate.js @@ -599,6 +599,14 @@ const translates = { dcsbrushi_info: "限定技,出牌阶段,你可以将你当前〖覆谋〗的状态、你的手牌数和你的体力值调整为你发动〖肃身〗时的记录,然后重置〖覆谋〗的发动次数。", dcsbfumou: "覆谋", dcsbfumou_info: "转换技,出牌阶段限一次,你可以观看一名其他角色A的手牌并展示其一半手牌:阴,并将这些牌交给另一名其他角色B,然后你与A各摸X张牌(X为A以此法失去的手牌数);阳,令A依次使用这些牌中所有其可以使用的牌(无距离限制且不可被响应)。", + dc_sb_zhugejin: "新杀谋诸葛瑾", + dc_sb_zhugejin_prefix: "新杀谋", + dcsbtaozhou: "讨州", + dcsbtaozhou_info: "出牌阶段,你可以选择一名有手牌的其他角色并从1/2/3中选择一个数字X,其可以选择是否交给你至多三张手牌。若其交给你的牌数Y:不小于X,则你与其各摸一张牌;小于X,则其下Z次受到的伤害+1(Z为X与Y之差)。若Z不小于2,则其获得〖自矜〗并视为对你使用一张【杀】。然后此技能失效直到下X轮游戏开始时。", + dcsbhoude: "厚德", + dcsbhoude_info: "当你于其他角色的出牌阶段内首次成为红色【杀】/黑色普通锦囊牌的目标后,你可以弃置你/其的一张牌,令此牌对你无效。", + dcsbzijin: "自矜", + dcsbzijin_info: "锁定技。①你不能成为〖讨州〗的目标。②当你使用牌结算结束后,若此牌未造成过伤害,你须弃置一张牌或失去1点体力。", }; export default translates; diff --git a/character/xianding/voices.js b/character/xianding/voices.js index 0aeb7153d..99b1fb984 100644 --- a/character/xianding/voices.js +++ b/character/xianding/voices.js @@ -1,4 +1,9 @@ export default { + "#dcsbtaozhou1": "皇叔借荆州久矣,瑾特来讨要。", + "#dcsbtaozhou2": "荆州弹丸之地,诸君岂可食言而肥?", + "#dcsbhoude1": "君子有德,可以载天下之重。", + "#dcsbhoude2": "南山有松,任尔风雨雷霆。", + "#dc_sb_zhugejin:die": "吾数梦,琅琊旧园。", "#dcjijie1": "不知书,何由见之。", "#dcjijie2": "闻古贤女,未有不学前世成败者。", "#dchuiji1": "明眸善睐,瑰姿艳逸。", diff --git a/character/yijiang/characterReplace.js b/character/yijiang/characterReplace.js index 658d925e7..dba70caf7 100644 --- a/character/yijiang/characterReplace.js +++ b/character/yijiang/characterReplace.js @@ -17,7 +17,7 @@ const characterReplaces = { madai: ["old_madai", "re_madai", "tw_madai", "madai"], liaohua: ["liaohua", "re_liaohua", "xin_liaohua"], bulianshi: ["bulianshi", "dc_bulianshi", "re_bulianshi", "old_bulianshi"], - handang: ["handang", "xin_handang", "re_handang", "tw_handang", "old_handang"], + handang: ["handang", "xin_handang", "re_handang", "tw_handang", "sb_handang", "old_handang"], chengpu: ["chengpu", "ol_chengpu", "re_chengpu", "xin_chengpu", "tw_chengpu", "ns_chengpu", "std_chengpu"], liubiao: ["liubiao", "xin_liubiao", "re_liubiao", "sb_liubiao", "oldre_liubiao", "old_liubiao"], manchong: ["manchong", "re_manchong"], @@ -68,7 +68,7 @@ const characterReplaces = { zhongyao: ["zhongyao", "re_zhongyao"], liwan: ["ol_liwan", "liwan"], wuxian: ["wuxian", "clan_wuxian"], - simafu: ["simafu", "yj_simafu"], + simafu: ["mb_simafu", "simafu", "yj_simafu"], xuangongzhu: ["yj_xuangongzhu", "xuangongzhu"], }; diff --git a/image/character/dc_sb_zhugejin.jpg b/image/character/dc_sb_zhugejin.jpg new file mode 100644 index 000000000..6796e849b Binary files /dev/null and b/image/character/dc_sb_zhugejin.jpg differ diff --git a/image/character/ol_sb_pangtong.jpg b/image/character/ol_sb_pangtong.jpg new file mode 100644 index 000000000..df55f9d01 Binary files /dev/null and b/image/character/ol_sb_pangtong.jpg differ diff --git a/image/character/sb_gaoshun.jpg b/image/character/sb_gaoshun.jpg new file mode 100644 index 000000000..2611bb556 Binary files /dev/null and b/image/character/sb_gaoshun.jpg differ diff --git a/image/character/sb_xiahoudun.jpg b/image/character/sb_xiahoudun.jpg new file mode 100644 index 000000000..c6f7eeea4 Binary files /dev/null and b/image/character/sb_xiahoudun.jpg differ diff --git a/image/character/tw_zhugejun.jpg b/image/character/tw_zhugejun.jpg new file mode 100644 index 000000000..de9f051b6 Binary files /dev/null and b/image/character/tw_zhugejun.jpg differ diff --git a/image/character/yadan.jpg b/image/character/yadan.jpg new file mode 100644 index 000000000..79c05f0a6 Binary files /dev/null and b/image/character/yadan.jpg differ diff --git a/image/character/yangfeng.jpg b/image/character/yangfeng.jpg new file mode 100644 index 000000000..e9abd2a7f Binary files /dev/null and b/image/character/yangfeng.jpg differ diff --git a/noname/library/element/content.js b/noname/library/element/content.js index a367e9ed8..447d1dd65 100644 --- a/noname/library/element/content.js +++ b/noname/library/element/content.js @@ -5604,7 +5604,7 @@ export const Content = { controls.remove("cancel2"); if ((event.direct && controls.length == 1) || event.forceDirect) { event.result = { - control: event.controls[0].link, + control: event.controls[0], links: get.links([event.controls[0]]), }; return; @@ -5620,7 +5620,7 @@ export const Content = { controls.remove("cancel2"); if ((event.direct && controls.length == 1) || event.forceDirect) { event.result = { - control: event.controls[0].link, + control: event.controls[0], links: get.links([event.controls[0]]), }; return; diff --git a/noname/library/element/player.js b/noname/library/element/player.js index 01d9f7a76..7e8d3e523 100644 --- a/noname/library/element/player.js +++ b/noname/library/element/player.js @@ -8047,19 +8047,21 @@ export class Player extends HTMLDivElement { if (log !== false && this.hasSkill(skill)) game.log(this, "的技能", `#g【${get.translation(skill)}】`, "暂时失效了"); - if (!expire) expire = { global: ["phaseAfter", "phaseBeforeStart"] }; - else if (typeof expire == "string" || Array.isArray(expire)) expire = { global: expire }; - this.when(expire, false) - .assign({ - firstDo: true, - }) - .vars({ - bannedSkill: skill, - }) - .then(() => { - delete player.storage[`temp_ban_${bannedSkill}`]; - }) - .finish(); + if (expire !== "forever") { + if (!expire) expire = { global: ["phaseAfter", "phaseBeforeStart"] }; + else if (typeof expire == "string" || Array.isArray(expire)) expire = { global: expire }; + this.when(expire, false) + .assign({ + firstDo: true, + }) + .vars({ + bannedSkill: skill, + }) + .then(() => { + delete player.storage[`temp_ban_${bannedSkill}`]; + }) + .finish(); + } } return skill; }