diff --git a/character/jsrg/character.js b/character/jsrg/character.js index f585dc619..013135e25 100644 --- a/character/jsrg/character.js +++ b/character/jsrg/character.js @@ -56,6 +56,14 @@ const characters = { jsrg_zhangxuan: ["female", "wu", 4, ["jsrgtongli", "jsrgshezang"]], jsrg_gaoxiang: ["male", "shu", 4, ["jsrgchiying"]], jsrg_guozhao: ["female", "wei", 3, ["jsrgpianchong", "jsrgzunwei"]], + //衰 + jsrg_yuanshao: { + sex: "male", + group: "qun", + hp: 4, + skills: ["jsrgzhimeng", "jsrgtianyu", "jsrgzhuni", "jsrghezhi"], + isZhugong: true, + }, }; export default characters; diff --git a/character/jsrg/skill.js b/character/jsrg/skill.js index 80f1272f4..ae5d08bc2 100644 --- a/character/jsrg/skill.js +++ b/character/jsrg/skill.js @@ -2,6 +2,248 @@ import { lib, game, ui, get, ai, _status } from "../../noname.js"; /** @type { importCharacterConfig['skill'] } */ const skills = { + //江山如故·衰 + jsrgzhimeng: { + trigger: { player: "phaseZhunbeiBegin" }, + logTarget() { + return game.filterPlayer(current => current.countCards("h") > 0).sortBySeat(); + }, + prompt: "是否发动【执盟】?", + async content(event, trigger, player) { + const { cards } = await game.cardsGotoOrdering(get.cards(game.countPlayer())); + await player.showCards(cards, `${get.translation(player)}发动了【执盟】`); + const targets = game.filterPlayer(current => current.countCards("h") > 0).sortBySeat(); + //选牌 + const showCardEvent = player.chooseCardOL(targets, `${get.translation(player)}发动了【执盟】,请展示一张手牌`, true); + showCardEvent.set("ai", card => { + if (get.event("_suits").includes(get.suit(card))) return 1 + Math.random(); + return (1 - get.value(card)) * Math.random(); + }); + showCardEvent.set( + "_suits", + cards.map(card => get.suit(card, false)) + ); + showCardEvent.set("source", player); + showCardEvent.set("aiCard", target => { + const hs = target.getCards("h"); + return { bool: true, cards: [hs.randomGet()] }; + }); + showCardEvent._args.remove("glow_result"); + const result = await showCardEvent.forResult(); + //选完了 展示牌 + const videoId = lib.status.videoId++; + const cardsToShown = []; + for (let i = 0; i < targets.length; i++) { + cardsToShown.push(result[i].cards[0]); + game.log(targets[i], "展示了", result[i].cards[0]); + } + game.broadcastAll( + (targets, cards, id, player) => { + const dialog = ui.create.dialog(get.translation(player) + "发动了【执盟】", cards); + dialog.videoId = id; + const getName = function (target) { + if (target._tempTranslate) return target._tempTranslate; + var name = target.name; + if (lib.translate[name + "_ab"]) return lib.translate[name + "_ab"]; + return get.translation(name); + }; + for (let i = 0; i < targets.length; i++) { + dialog.buttons[i].querySelector(".info").innerHTML = getName(targets[i]) + get.translation(get.suit(cards[i], targets[i])); + } + }, + targets, + cardsToShown, + videoId, + player + ); + await game.asyncDelay(4); + game.broadcastAll("closeDialog", videoId); + //展示完了 开始拿牌 + const suitsMap = {}; + for (let i = 0; i < targets.length; i++) { + const target = targets[i], + card = cardsToShown[i], + suit = get.suit(card, target); + if (!(suit in suitsMap)) suitsMap[suit] = target; + else suitsMap[suit] = null; + } + const gain_list = []; + for (const data of Object.entries(suitsMap)) { + const [suit, target] = data; + if (target) { + const cardsToGain = cards.filter(card => get.suit(card, false) === suit); + if (cardsToGain.length) gain_list.push([target, cardsToGain]); + } + } + if (gain_list.length) { + await game + .loseAsync({ + gain_list, + animate: "gain2", + }) + .setContent("gaincardMultiple"); + } + }, + }, + jsrgtianyu: { + trigger: { global: ["loseAsyncAfter", "cardsDiscardAfter"] }, + frequent: true, + filter(event) { + return lib.skill.jsrgtianyu.getCards(event).length > 0; + }, + getCards(event) { + const cards = event.getd().filter(card => { + return get.type(card, null, false) === "equip" || get.tag(card, "damage", null, false) > 0; + }); + if (!cards.length) return []; + game.checkGlobalHistory("cardMove", evt => { + if (evt.name === "lose") cards.removeArray(evt.cards); + }); + return cards; + }, + async content(event, trigger, player) { + const cards = lib.skill.jsrgtianyu.getCards(trigger); + let cardsToGain; + if (cards.length === 1) { + cardsToGain = cards; + } else { + cardsToGain = await player.chooseButton(["天予:选择获得任意张牌", cards], true, [1, cards.length]).forResult("links"); + } + await player.gain(cards, "gain2"); + }, + }, + jsrgzhuni: { + enable: "phaseUse", + usable: 1, + filterTarget: true, + selectTarget: -1, + multitarget: true, + multiline: true, + async content(event, trigger, player) { + let targets = event.targets.slice(0), + results = [], + forceTargets = []; + //XXX自选选择目标 + if (player.hasSkill("jsrghezhi")) { + forceTargets = targets.filter(current => current !== player && current.group === "qun"); + targets.removeArray(forceTargets); + } + //让读条不消失 + event._global_waiting = true; + const send = (player, source) => { + lib.skill.jsrgzhuni.chooseTarget(player, source); + game.resume(); + }; + const solve = (result, chooser) => { + let target; + if (!result || !result.targets || result === "ai") { + target = game.filterPlayer(current => current !== player).randomGet(); + } else target = result.targets[0]; + results.push([chooser, target]); + if (chooser === player) { + forceTargets.forEach(current => results.push([current, target])); + } + }; + let time = 10000; + if (lib.configOL && lib.configOL.choose_timeout) time = parseInt(lib.configOL.choose_timeout) * 1000; + //Promise,爽!清瑶你有种抄过去 + await Promise.all( + targets.map((current, index) => { + return new Promise(async (resolve, reject) => { + current.showTimer(time); + if (current.isOnline()) { + current.send(send, current, player); + current.wait((result, player) => { + solve(result, player); + resolve(); + }); + } else if (current == game.me) { + const next = lib.skill.jsrgzhuni.chooseTarget(current, player); + const solver = (result, player) => { + solve(result, player); + resolve(); + }; + if (_status.connectMode) game.me.wait(solver); + const result = await next.forResult(); + if (_status.connectMode) game.me.unwait(result, current); + else solver(result, current); + } else { + const next = lib.skill.jsrgzhuni.chooseTarget(current, player); + const result = await next.forResult(); + setTimeout(async () => { + solve(result, current); + resolve(); + }, 500 + 100 * index); + } + }); + }) + ); + //清除读条 + delete event._global_waiting; + for (var i of targets) i.hideTimer(); + //统计票数 + const ticketsMap = new Map(); + results.forEach(data => { + const [source, current] = data; + source.line(current); + game.log(source, forceTargets.includes(source) ? "自愿选择" : "选择了", current, "作为讨伐目标"); + ticketsMap.set(current, (ticketsMap.get(current) || 0) + 1); + }); + console.log(ticketsMap); + let maxTicket = 0; + const target = ticketsMap.entries().reduce((target, data) => { + console.log(data); + const [current, ticket] = data; + if (ticket > maxTicket) { + maxTicket = ticket; + return current; + } else if (ticket === maxTicket) return false; + else return target; + }, false); + //上Buff + if (target) { + game.log(target, "成为了", "#g【执盟】", "的讨伐目标"); + player.addTempSkill("jsrgzhuni_effect"); + player.markAuto("jsrgzhuni_effect", [target]); + } + }, + ai: { + order: 10, + result: { player: 1 }, + threaten: 1.8, + }, + chooseTarget(player, source) { + const next = player.chooseTarget(`${get.translation(player)}发动了【执盟】,请选择一名讨伐目标`, (card, player, target) => target !== source, true); + next.set("ai", target => -get.attitude(get.player(), target)); + next.set("animate", false); + return next; + }, + subSkill: { + effect: { + onremove: true, + mod: { + targetInRange(card, player, target) { + if (player.getStorage("jsrgzhuni_effect").includes(target)) { + return true; + } + }, + cardUsableTarget(card, player, target) { + if (player.getStorage("jsrgzhuni_effect").includes(target)) { + return true; + } + }, + }, + charlotte: true, + intro: { + content: "对$使用牌无距离和次数限制", + }, + }, + }, + }, + jsrghezhi: { + zhuSkill: true, + locked: true, + }, //江山如故·合 //蓄谋临时禁用 xumou_jsrg_temp: { diff --git a/character/jsrg/sort.js b/character/jsrg/sort.js index eea451785..ba64bc75e 100644 --- a/character/jsrg/sort.js +++ b/character/jsrg/sort.js @@ -3,6 +3,7 @@ const characterSort = { jiangshanrugu_cheng: ["jsrg_sunce", "jsrg_xuyou", "jsrg_lvbu", "jsrg_zhanghe", "jsrg_zoushi", "jsrg_guanyu", "jsrg_chendeng", "jsrg_zhenji", "jsrg_zhangliao", "jsrg_xugong", "jsrg_chunyuqiong"], jiangshanrugu_zhuan: ["jsrg_guojia", "jsrg_zhangfei", "jsrg_machao", "jsrg_lougui", "jsrg_zhangren", "jsrg_huangzhong", "jsrg_xiahourong", "jsrg_sunshangxiang", "jsrg_pangtong", "jsrg_hansui", "jsrg_zhangchu", "jsrg_xiahouen", "jsrg_fanjiangzhangda"], jiangshanrugu_he: ["jsrg_zhugeliang", "jsrg_jiangwei", "jsrg_luxun", "jsrg_zhaoyun", "jsrg_simayi", "jsrg_guoxun", "jsrg_sunlubansunluyu", "jsrg_caofang", "jsrg_sunjun", "jsrg_liuyong", "jsrg_weiwenzhugezhi", "jsrg_zhangxuan", "jsrg_gaoxiang", "jsrg_guozhao"], + jiangshanrugu_shuai: ["jsrg_yuanshao"], }; const characterSortTranslate = { @@ -10,6 +11,7 @@ const characterSortTranslate = { jiangshanrugu_cheng: "江山如故·承", jiangshanrugu_zhuan: "江山如故·转", jiangshanrugu_he: "江山如故·合", + jiangshanrugu_shuai: "江山如故·衰", }; export { characterSort, characterSortTranslate }; diff --git a/character/jsrg/translate.js b/character/jsrg/translate.js index e136441b6..a6bfc7ab9 100644 --- a/character/jsrg/translate.js +++ b/character/jsrg/translate.js @@ -356,6 +356,17 @@ const translates = { xumou_jsrg: "蓄谋", xumou_jsrg_info: "“蓄谋”牌可在判定区内重复存在。判定阶段开始时,你选择一项:⒈使用此牌对应的实体牌,然后本阶段不能再使用此牌名的牌;⒉将所有的“蓄谋”牌置入弃牌堆。", + + jsrg_yuanshao: "梦袁绍", + jsrg_yuanshao_prefix: "梦", + jsrgzhimeng: "执盟", + jsrgzhimeng_info: "准备阶段,你可以亮出牌堆顶的X张牌(X为存活角色数),然后令所有角色同时展示一张手牌。若有角色展示的手牌花色与其他角色均不同,则这些角色从亮出牌中获得该花色的所有牌。", + jsrgtianyu: "天予", + jsrgtianyu_info: "当一张具有“伤害”标签的牌或装备牌被置入弃牌堆时,若此牌本回合内未处于过任何角色的手牌区或装备区,则你可以获得之。", + jsrgzhuni: "诛逆", + jsrgzhuni_info: "出牌阶段限一次,你可以令所有角色同时选择一名除你之外的其他角色。若有角色本回合内被指定过的次数唯一最多,则你本回合内对该角色使用牌没有次数和距离限制。", + jsrghezhi: "合志", + jsrghezhi_info: "主公技,锁定技。其他群势力角色需要因〖诛逆〗而选择角色时,改为选择你本次选择的角色。", }; export default translates; diff --git a/character/rank.js b/character/rank.js index 1864bdc62..03d2e4bae 100644 --- a/character/rank.js +++ b/character/rank.js @@ -1102,6 +1102,7 @@ window.noname_character_rank = { "ol_wangyi", "chengji", "mb_sp_guanqiujian", + "jsrg_yuanshao", ], b: [ "junk_guanyu", @@ -1929,6 +1930,7 @@ window.noname_character_rank = { "wu_guanyu", "guanyue", "key_mia", + "jsrg_yuanshao", ], epic: [ "xukun",