diff --git a/character/tw/character.js b/character/tw/character.js index 5d6e9cd83..37012324f 100644 --- a/character/tw/character.js +++ b/character/tw/character.js @@ -1,4 +1,5 @@ const characters = { + tw_zhugejun: ["male", "qun", 3, ["twshouzhu", "twdaigui", "twcairu"]], 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..f2186ab47 100644 --- a/character/tw/skill.js +++ b/character/tw/skill.js @@ -2,6 +2,294 @@ 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 }, + }, + }, //颜良文丑,但是颜良+文丑 twduwang: { audio: 3, diff --git a/character/tw/sort.js b/character/tw/sort.js index d09ed771b..60c4de8cb 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: ["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..9a27c12c4 100644 --- a/character/tw/translate.js +++ b/character/tw/translate.js @@ -686,6 +686,13 @@ 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: "每回合每种牌名限一次。你可以将两张颜色不同的牌当【火攻】、【铁索连环】或【无中生有】使用。", }; export default translates; 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