From 310c4d15462002824b27e06ae4410e3c087da378 Mon Sep 17 00:00:00 2001 From: Rintim Date: Sat, 8 Mar 2025 15:00:54 +0800 Subject: [PATCH 01/48] =?UTF-8?q?fix:=20=E6=96=B9=E5=A4=A9=E7=94=BB?= =?UTF-8?q?=E6=88=9F=E5=9C=A8=E5=9B=BD=E6=88=98=E6=83=85=E5=86=B5=E4=B8=8B?= =?UTF-8?q?=E5=B9=B6=E6=9C=AA=E6=8C=89=E7=85=A7=E9=A2=84=E6=9C=9F=E7=9A=84?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E8=BF=9B=E8=A1=8C=E5=8A=BF=E5=8A=9B=E6=8E=92?= =?UTF-8?q?=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- card/standard.js | 80 +++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/card/standard.js b/card/standard.js index c77af881e9..1132cb56c4 100644 --- a/card/standard.js +++ b/card/standard.js @@ -3191,36 +3191,60 @@ game.import("card", function () { return true; }); }, - direct: true, - content() { - "step 0"; - player - .chooseTarget(get.prompt2("fangtian"), [1, Infinity], function (card, player, target) { - var cardx = _status.event.cardx; - if (!lib.filter.filterTarget(cardx, player, target)) return false; - var targets = _status.event.targets.slice(0).concat(ui.selected.targets); - if (targets.includes(target)) return false; - if (target.identity == "ye" || target.identity == "unknown") return true; - for (var i = 0; i < targets.length; i++) { - if (target.identity == targets[i].identity) return false; - } + log: false, + async cost(event, trigger, player) { + const next = player.chooseTarget(get.prompt2("fangtian")); + + next.set("selectTarget", [1, Infinity]); + next.set("filterTarget", filterTarget); + next.set("promptbar", "none"); + next.set("complexTarget", true); + next.set("cardx", trigger.card); + next.set("targets", trigger.targets); + next.set("ai", check); + + event.result = await next.forResult(); + + function filterTarget(card, player, target) { + const cardx = get.event("cardx"); + + if (!lib.filter.filterTarget(cardx, player, target)) { + return false; + } + + const targets = get.event("targets").concat(ui.selected.targets); + + if (targets.includes(target)) { + return false; + } + if (target.identity == "ye" || target.identity == "unknown") { return true; - }) - .set("promptbar", "none") - .set("cardx", trigger.card) - .set("targets", trigger.targets) - .set("ai", function (target) { - var player = _status.event.player; - return get.effect(target, _status.event.cardx, player, player); - }); - "step 1"; - if (result.bool) { - player.logSkill("fangtian_skill", result.targets); - if (!player.storage.fangtian_guozhan_trigger) player.storage.fangtian_guozhan_trigger = []; - player.storage.fangtian_guozhan_trigger.add(trigger.card); - trigger.targets.addArray(result.targets); - player.addTempSkill("fangtian_guozhan_trigger"); + } + + for (let i = 0; i < targets.length; i++) { + if (target.identity == targets[i].identity) { + return false; + } + } + + return true; + } + + function check(target) { + var player = _status.event.player; + return get.effect(target, _status.event.cardx, player, player); + } + }, + async content(event, trigger, player) { + player.logSkill("fangtian_skill", event.targets); + + if (!player.storage.fangtian_guozhan_trigger) { + player.storage.fangtian_guozhan_trigger = []; } + + player.storage.fangtian_guozhan_trigger.add(trigger.card); + trigger.targets.addArray(event.targets); + player.addTempSkill("fangtian_guozhan_trigger"); }, }, fangtian_guozhan_trigger: { From 15ec6e5ee15adb7c460af28634cb0f567e1c553d Mon Sep 17 00:00:00 2001 From: Rintim Date: Sat, 8 Mar 2025 21:49:31 +0800 Subject: [PATCH 02/48] =?UTF-8?q?pref:=20=E4=BC=98=E5=8C=96=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E5=88=A4=E6=96=AD=EF=BC=8C=E4=BD=BF`game.import`?= =?UTF-8?q?=E8=83=BD=E7=9B=B4=E6=8E=A5=E5=AF=BC=E5=85=A5=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=EF=BC=8C=E8=80=8C=E4=B8=8D=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E5=86=8D=E5=8C=85=E8=A3=85=E4=B8=80=E5=B1=82=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- noname/game/index.js | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/noname/game/index.js b/noname/game/index.js index 4880291b99..2125561c06 100644 --- a/noname/game/index.js +++ b/noname/game/index.js @@ -1965,16 +1965,40 @@ export class Game extends GameCompatible { _status.extensionLoading.add(promise); return promise; } else { - if (!lib.imported[type]) lib.imported[type] = {}; - const promise = Promise.resolve((gnc.is.generator(content) ? gnc.of(content) : content)(lib, game, ui, get, ai, _status)).then(content2 => { + if (!lib.imported[type]) { + lib.imported[type] = {}; + } + + /** @type {Promise} */ + let promise; + if (typeof content === "function") { + if (gnc.is.generator(content)) { + promise = gnc.of(content)(lib, game, ui, get, ai, _status); + } else { + // @ts-expect-error no `Promise.try` type info + promise = Promise.try(content, lib, game, ui, get, ai, _status); + } + } else { + // 目前假定content是一个合法的对象 + promise = Promise.resolve(content); + } + + promise = promise.then(content2 => { if (content2.name) { lib.imported[type][content2.name] = content2; // delete content2.name; } }); - if (typeof _status.importing == "undefined") _status.importing = {}; - if (!_status.importing[type]) _status.importing[type] = []; + + if (typeof _status.importing == "undefined") { + _status.importing = {}; + } + if (!_status.importing[type]) { + _status.importing[type] = []; + } + _status.importing[type].add(promise); + return promise; } } From aa1381db3d23bf954c35a2815ffd726eaf88ff09 Mon Sep 17 00:00:00 2001 From: Rintim Date: Sun, 9 Mar 2025 01:43:49 +0800 Subject: [PATCH 03/48] =?UTF-8?q?pref:=20=E4=BD=BF=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E7=9A=84=E5=87=BD=E6=95=B0=E5=B0=86=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E8=BF=94=E5=9B=9E=EF=BC=8C=E4=BD=BF=E8=B0=83=E7=94=A8?= =?UTF-8?q?=E8=80=85=E5=8F=AF`await`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- noname/game/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/noname/game/index.js b/noname/game/index.js index 2125561c06..e8acc79a6f 100644 --- a/noname/game/index.js +++ b/noname/game/index.js @@ -1210,7 +1210,7 @@ export class Game extends GameCompatible { type == "hidden" ); _status.mode = lib.configOL[lib.configOL.mode + "_mode"]; - game.chooseCharacterOL(); + return game.chooseCharacterOL(); } closeMenu() { if (ui.menuContainer && !ui.menuContainer.classList.contains("hidden")) { @@ -1323,6 +1323,7 @@ export class Game extends GameCompatible { var next = game.createEvent("waitForPlayer", false); next.func = func; next.setContent("waitForPlayer"); + return next; } /** * @param { number } time @@ -6870,6 +6871,7 @@ export class Game extends GameCompatible { next.player = player; next._isStandardLoop = true; next.setContent("phaseLoop"); + return next; } /** * @param { Player } [player] From c595ef708c752bf5f6e0bcbf9a9210d3bf49f30c Mon Sep 17 00:00:00 2001 From: Rintim Date: Sun, 9 Mar 2025 01:45:37 +0800 Subject: [PATCH 04/48] =?UTF-8?q?pref:=20=E9=87=8D=E6=9E=84=E5=9B=BD?= =?UTF-8?q?=E6=88=98=E6=A8=A1=E5=BC=8F=E7=9A=84`start`=E5=87=BD=E6=95=B0?= =?UTF-8?q?=EF=BC=8C=E5=B9=B6=E6=9B=B4=E6=96=B0=E4=B8=BA`Async=20Content`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mode/guozhan/src/main.js | 267 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 mode/guozhan/src/main.js diff --git a/mode/guozhan/src/main.js b/mode/guozhan/src/main.js new file mode 100644 index 0000000000..edc2b17055 --- /dev/null +++ b/mode/guozhan/src/main.js @@ -0,0 +1,267 @@ +import { lib, game, ui, get, ai, _status } from "../../../noname.js"; + +/** + * @type {ContentFuncByAll} + */ +export async function start(event, trigger, player) { + // 首先检查是否在播放录像 + const playback = localStorage.getItem(lib.configprefix + "playback"); + + // 如果有录像信息,则尝试播放录像 + if (playback) { + ui.create.me(); + ui.arena.style.display = "none"; + ui.system.style.display = "none"; + + _status.playback = playback; + localStorage.removeItem(lib.configprefix + "playback"); + + // 读取录像信息 + // @ts-expect-error type error + const store = lib.db.transaction(["video"], "readwrite").objectStore("video"); + store.get(parseInt(playback)).onsuccess = function (e) { + if (e.target.result) { + game.playVideoContent(e.target.result.video); + } else { + alert("播放失败:找不到录像"); + game.reload(); + } + }; + + // 录像或许需要对乱斗模式进行特殊的处理 + _status.mode = get.config("guozhan_mode"); + if (_status.brawl && _status.brawl.submode) { + _status.mode = _status.brawl.submode; + } + if (get.config("separatism")) { + // @ts-expect-error 祖宗之法就是这么写的 + _status.separatism = true; + } + + return; + } + + // 如果没有录像信息,则根据是否在联机模式进行不同的处理 + if (_status.connectMode) { + // 等待玩家加入 + // @ts-expect-error 祖宗之法就是这么写的 + await game.waitForPlayer(); + + // 获取当前模式的配置 + let mode = lib.configOL.guozhan_mode; + _status.mode = mode; + + // 如果当前模式不在可选列表中,则默认为normal + if (!["normal", "yingbian", "old"].includes(mode)) { + _status.mode = mode = "normal"; + } + + if (lib.configOL.separatism) { + // @ts-expect-error 祖宗之法就是这么写的 + _status.separatism = true; + } + + // 决定当前模式下的牌堆 + switch (_status.mode) { + case "old": + // @ts-expect-error 祖宗之法就是这么写的 + lib.card.list = lib.guozhanPile_old.slice(0); + break; + case "yingbian": + // @ts-expect-error 祖宗之法就是这么写的 + lib.card.list = lib.guozhanPile_yingbian.slice(0); + delete lib.translate.shuiyanqijunx_info_guozhan; + break; + default: + // @ts-expect-error 祖宗之法就是这么写的 + lib.card.list = lib.guozhanPile.slice(0); + break; + } + + // @ts-expect-error 祖宗之法就是这么写的 + game.fixedPile = true; + + // 向其他玩家广播当前模式 + game.broadcastAll( + // @ts-expect-error 祖宗之法就是这么写的 + (mode, separatism) => { + _status.mode = mode; + if (separatism) { + // @ts-expect-error 祖宗之法就是这么写的 + _status.separatism = true; + } + // @ts-expect-error 祖宗之法就是这么写的 + const pack = lib.characterPack.mode_guozhan; + if (mode == "yingbian") { + delete lib.translate.shuiyanqijunx_info_guozhan; + // @ts-expect-error 祖宗之法就是这么写的 + const pack2 = lib.yingbian_guozhan; + for (const i in pack2) { + pack[i] = pack2[i]; + } + } + for (let i = 0; i < game.players.length; ++i) { + game.players[i].node.name.hide(); + game.players[i].node.name2.hide(); + } + for (const character in pack) { + lib.character[character] = pack[character]; + if (!lib.translate["#" + character + ":die"] && !lib.character[character].dieAudios?.length) { + let list = lib.character?.[character.slice(3)]?.dieAudios; + lib.character[character].dieAudios = list?.length ? list : [character.slice(3)]; + } + if (!lib.translate[character]) { + lib.translate[character] = lib.translate[character.slice(3)]; + } + } + for (const character in lib.character) { + if (lib.character[character][1] == "shen" || lib.character[character][1] == "western") { + lib.character[character].group = lib.character[character].groupInGuozhan || "qun"; + } + } + //lib.characterReplace={}; + }, + _status.mode, + // @ts-expect-error 祖宗之法就是这么写的 + _status.separatism + ); + + await game.randomMapOL(); + } else { + // 获取当前模式的配置 + let mode = get.config("guozhan_mode"); + _status.mode = mode; + + // 如果当前模式不在可选列表中,则默认为normal + if (!["normal", "yingbian", "old", "free"].includes(mode)) { + _status.mode = mode = "normal"; + } + + // 决定当前模式下的牌堆 + switch (_status.mode) { + case "old": + // @ts-expect-error 祖宗之法就是这么写的 + lib.card.list = lib.guozhanPile_old.slice(0); + break; + case "yingbian": { + // @ts-expect-error 祖宗之法就是这么写的 + lib.card.list = lib.guozhanPile_yingbian.slice(0); + delete lib.translate.shuiyanqijunx_info_guozhan; + // @ts-expect-error 祖宗之法就是这么写的 + const pack = lib.yingbian_guozhan; + for (const i in pack) { + lib.character[i] = pack[i]; + // @ts-expect-error 祖宗之法就是这么写的 + lib.characterPack.mode_guozhan[i] = pack[i]; + if (!lib.translate["#" + i + ":die"] && !lib.character[i].dieAudios?.length) { + let list = lib.character?.[i.slice(3)]?.dieAudios; + lib.character[i].dieAudios = list?.length ? list : [i.slice(3)]; + } + if (!lib.translate[i]) lib.translate[i] = lib.translate[i.slice(3)]; + } + break; + } + case "normal": + // @ts-expect-error 祖宗之法就是这么写的 + lib.card.list = lib.guozhanPile.slice(0); + break; + } + + if (_status.mode != "free") { + // @ts-expect-error 祖宗之法就是这么写的 + game.fixedPile = true; + } else { + delete lib.translate.shuiyanqijunx_info_guozhan; + } + + game.prepareArena(); + // game.delay(); + game.showChangeLog(); + + if (_status.brawl && _status.brawl.submode) { + _status.mode = _status.brawl.submode; + } + if (get.config("separatism")) { + // @ts-expect-error 祖宗之法就是这么写的 + _status.separatism = true; + } + + for (let i = 0; i < game.players.length; ++i) { + game.players[i].node.name.hide(); + game.players[i].node.name2.hide(); + game.players[i].getId(); + } + + if (_status.brawl && _status.brawl.chooseCharacterBefore) { + await _status.brawl.chooseCharacterBefore(); + } + + // @ts-expect-error 祖宗之法就是这么写的 + await game.chooseCharacter(); + } + + // 后面暂时不加注释了,等重构吧 + if (ui.coin) { + _status.coinCoeff = get.coinCoeff([game.me.name1, game.me.name2]); + } + + let playerFirst; + // @ts-expect-error 祖宗之法就是这么写的 + if (_status.cheat_seat) { + // @ts-expect-error 祖宗之法就是这么写的 + let seat = _status.cheat_seat.link; + if (seat == 0) { + playerFirst = game.me; + } else { + playerFirst = game.players[game.players.length - seat]; + } + if (!playerFirst) playerFirst = game.me; + // @ts-expect-error 祖宗之法就是这么写的 + delete _status.cheat_seat; + } else { + playerFirst = game.players[Math.floor(Math.random() * game.players.length)]; + } + + await event.trigger("gameStart"); + + await game.gameDraw(playerFirst); + // @ts-expect-error 祖宗之法就是这么写的 + game.broadcastAll(player => { + for (let i = 0; i < game.players.length; ++i) { + var seatNum = get.distance(player, game.players[i], "absolute"); + game.players[i].name = `unknown${seatNum}`; + game.players[i].node.name_seat = ui.create.div(".name.name_seat", get.seatTranslation(seatNum), game.players[i]); + // if(game.players[i]==game.me){ + // lib.translate[game.players[i].name]+='(你)'; + // } + } + }, playerFirst); + + const players = get.players(lib.sort.position); + const info = []; + for (let i = 0; i < players.length; ++i) { + info.push({ + name: game.players[i].name, + translate: lib.translate[game.players[i].name], + name1: players[i].name1, + name2: players[i].name2, + nickname: players[i].node.nameol.innerHTML, + }); + } + + // @ts-expect-error 祖宗之法就是这么写的 + _status.videoInited = true; + game.addVideo("init", null, info); + + if (_status.mode == "mingjiang") { + // @ts-expect-error 祖宗之法就是这么写的 + game.showIdentity(true); + } else { + for (let i = 0; i < game.players.length; ++i) { + game.players[i].ai.shown = 0; + } + } + if (_status.connectMode && lib.configOL.change_card) { game.replaceHandcards(game.players.slice(0)) } + + await game.phaseLoop(playerFirst); +} From b9e4d6815234a727d9702e56aac082d50363e425 Mon Sep 17 00:00:00 2001 From: Rintim Date: Sun, 9 Mar 2025 01:46:33 +0800 Subject: [PATCH 05/48] =?UTF-8?q?chore:=20=E4=BD=BFGit=E4=B8=8D=E4=BC=9A?= =?UTF-8?q?=E6=97=A0=E8=A7=86=E4=BD=8D=E4=BA=8E=E6=A8=A1=E5=BC=8F=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=A4=B9=E4=B8=8B=E7=9A=84`main.js`=E6=96=87=E4=BB=B6?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 854fc542c8..c155d50356 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ Home jsconfig.json localStorage.json main.js +!mode/**/src/main.js node_modules noname.ico package-lock.json From 63d82c6a8812deb9057f52da6993b9cb6524e379 Mon Sep 17 00:00:00 2001 From: Rintim Date: Sun, 9 Mar 2025 01:51:34 +0800 Subject: [PATCH 06/48] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=9B=BD?= =?UTF-8?q?=E6=88=98=E6=A8=A1=E5=BC=8F=E7=9A=84=E9=85=8D=E7=BD=AE=E5=92=8C?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mode/guozhan/index.js | 15 ++++++++++++ mode/guozhan/src/main.js | 51 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 mode/guozhan/index.js diff --git a/mode/guozhan/index.js b/mode/guozhan/index.js new file mode 100644 index 0000000000..5028576cdc --- /dev/null +++ b/mode/guozhan/index.js @@ -0,0 +1,15 @@ +import { lib, game, ui, get, ai, _status } from "../../noname.js"; +import { start, startBefore, onreinit } from "./src/main.js"; + +export const type = "mode"; + +/** + * @type {importModeConfig} + */ +export default { + name: "guozhan", + + start, + startBefore, + onreinit +}; diff --git a/mode/guozhan/src/main.js b/mode/guozhan/src/main.js index edc2b17055..d48b3f4246 100644 --- a/mode/guozhan/src/main.js +++ b/mode/guozhan/src/main.js @@ -261,7 +261,56 @@ export async function start(event, trigger, player) { game.players[i].ai.shown = 0; } } - if (_status.connectMode && lib.configOL.change_card) { game.replaceHandcards(game.players.slice(0)) } + if (_status.connectMode && lib.configOL.change_card) { + game.replaceHandcards(game.players.slice(0)); + } await game.phaseLoop(playerFirst); } + +export function startBefore() { + const playback = localStorage.getItem(lib.configprefix + "playback"); + + // @ts-expect-error 祖宗之法就是这么写的 + for (let character in lib.characterPack.mode_guozhan) { + if (!get.config("onlyguozhan") && !playback) { + if (lib.character[character.slice(3)]) continue; + } + // @ts-expect-error 祖宗之法就是这么写的 + lib.character[character] = lib.characterPack.mode_guozhan[character]; + if (!lib.translate["#" + character + ":die"] && !lib.character[character].dieAudios?.length) { + let list = lib.character?.[character.slice(3)]?.dieAudios; + lib.character[character].dieAudios = list?.length ? list : [character.slice(3)]; + } + if (!lib.translate[character]) { + lib.translate[character] = lib.translate[character.slice(3)]; + } + } + for (const character in lib.character) { + if (lib.character[character].group == "shen") { + lib.character[character].group = lib.character[character].groupInGuozhan || "qun"; + } + } +} + +export function onreinit() { + // @ts-expect-error 祖宗之法就是这么写的 + const pack = lib.characterPack.mode_guozhan; + + for (const character in pack) { + lib.character[character] = pack[character]; + if (!lib.translate["#" + character + ":die"] && !lib.character[character].dieAudios?.length) { + let list = lib.character?.[character.slice(3)]?.dieAudios; + lib.character[character].dieAudios = list?.length ? list : [character.slice(3)]; + } + if (!lib.translate[character]) { + lib.translate[character] = lib.translate[character.slice(3)]; + } + } + + for (const character in lib.character) { + if (lib.character[character].group == "shen" || lib.character[character].group == "western") { + lib.character[character].group = lib.character[character].groupInGuozhan || "qun"; + } + } +} From ee313e2091ca7cfbb0b920c47397de313c5a2e50 Mon Sep 17 00:00:00 2001 From: Rintim Date: Sun, 9 Mar 2025 02:05:54 +0800 Subject: [PATCH 07/48] =?UTF-8?q?fix:=20=E4=B8=80=E4=BA=9B=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E4=B8=8A=E7=9A=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- card/standard.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/card/standard.js b/card/standard.js index 85476b94cf..25ca8ab9a8 100644 --- a/card/standard.js +++ b/card/standard.js @@ -3235,7 +3235,7 @@ game.import("card", function () { return get.effect(target, _status.event.cardx, player, player); } }, - async content(event, trigger, player) { + async content(event, trigger, player) { player.logSkill("fangtian_skill", event.targets); trigger.targets.addArray(event.targets); @@ -3252,8 +3252,11 @@ game.import("card", function () { onremove: true, charlotte: true, async content(event, trigger, player) { - if (event.triggername == "shaMiss" && player.getStorage(event.name).includes(trigger.card)) trigger.getParent().excluded.addArray(trigger.getParent().targets); - else player.unmarkAuto(event.name, [trigger.card]); + if (event.triggername == "shaMiss" && player.getStorage(event.name).includes(trigger.card)) { + trigger.getParent().excluded.addArray(trigger.getParent().targets); + } else { + player.unmarkAuto(event.name, [trigger.card]); + } }, }, }, From 56932734b79c8a9fa4e468bbc743d2aa3ee5ba29 Mon Sep 17 00:00:00 2001 From: Rintim Date: Mon, 10 Mar 2025 16:09:11 +0800 Subject: [PATCH 08/48] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96`check`=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E4=B8=AD=E7=9A=84=E5=8F=98=E9=87=8F=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- card/standard.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/card/standard.js b/card/standard.js index 25ca8ab9a8..643f310b7f 100644 --- a/card/standard.js +++ b/card/standard.js @@ -3231,8 +3231,9 @@ game.import("card", function () { } function check(target) { - var player = _status.event.player; - return get.effect(target, _status.event.cardx, player, player); + const player = get.player(); + const card = get.event("cardx"); + return get.effect(target, card, player, player); } }, async content(event, trigger, player) { From cb548c042a9828e914fad1905f10413f2c8fb55b Mon Sep 17 00:00:00 2001 From: Rintim Date: Mon, 10 Mar 2025 16:21:44 +0800 Subject: [PATCH 09/48] =?UTF-8?q?pref:=20=E9=87=8D=E6=9E=84=E5=9B=BD?= =?UTF-8?q?=E6=88=98=E6=A8=A1=E5=BC=8F=E5=AF=B9`Game`=E7=9A=84=E7=8C=B4?= =?UTF-8?q?=E5=AD=90=E8=A1=A5=E4=B8=81=20(1/3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mode/guozhan/src/main.js | 7 +- mode/guozhan/src/patch/game.js | 1272 ++++++++++++++++++++++++++++++++ 2 files changed, 1275 insertions(+), 4 deletions(-) create mode 100644 mode/guozhan/src/patch/game.js diff --git a/mode/guozhan/src/main.js b/mode/guozhan/src/main.js index d48b3f4246..4a469d619b 100644 --- a/mode/guozhan/src/main.js +++ b/mode/guozhan/src/main.js @@ -1,4 +1,5 @@ import { lib, game, ui, get, ai, _status } from "../../../noname.js"; +import { broadcastAll } from "./patch/game.js"; /** * @type {ContentFuncByAll} @@ -82,8 +83,7 @@ export async function start(event, trigger, player) { game.fixedPile = true; // 向其他玩家广播当前模式 - game.broadcastAll( - // @ts-expect-error 祖宗之法就是这么写的 + broadcastAll( (mode, separatism) => { _status.mode = mode; if (separatism) { @@ -225,8 +225,7 @@ export async function start(event, trigger, player) { await event.trigger("gameStart"); await game.gameDraw(playerFirst); - // @ts-expect-error 祖宗之法就是这么写的 - game.broadcastAll(player => { + broadcastAll(player => { for (let i = 0; i < game.players.length; ++i) { var seatNum = get.distance(player, game.players[i], "absolute"); game.players[i].name = `unknown${seatNum}`; diff --git a/mode/guozhan/src/patch/game.js b/mode/guozhan/src/patch/game.js new file mode 100644 index 0000000000..71eb8a095e --- /dev/null +++ b/mode/guozhan/src/patch/game.js @@ -0,0 +1,1272 @@ +import { lib, game, ui, get, ai, _status } from "../../../../noname.js"; +import { GameEvent, Dialog, Player } from "../../../../noname/library/element/index.js"; +import { Game } from "../../../../noname/game/index.js"; + +export class GameGuozhan extends Game { + /** + * 不确定是干啥的,反正恒返回真 + * + * @returns {boolean} + */ + canReplaceViewpoint() { + return true; + } + + /** + * 当野心家未明置主将,且场上只剩副将所属阵容时,野心家可明置主将,并进行”拉拢人心“ + * + * 详情请参阅规则集 + * + * @returns {GameEvent} + */ + showYexings() { + const next = game.createEvent("showYexings", false); + + // 如果已存在展示野心的野心家,则不做处理 + // @ts-expect-error 祖宗之法就是这么写的 + if (_status.showYexings) { + next.setContent(async () => { + return; + }); + + return next; + } + + // @ts-expect-error 祖宗之法就是这么写的 + _status.showYexings = true; + next.setContent(showYexingsContent); + + return next; + } + + /** + * 获取武将选择 + * + * @author Spmario233 + * @param {string[]} list - 所有武将的数组 + * @param {number} num - 选择武将的数量 + * @returns {string[]} - 最终武将的数组 + */ + getCharacterChoice(list, num) { + const choice = list.splice(0, num).sort(function (a, b) { + return (get.is.double(a) ? 1 : -1) - (get.is.double(b) ? 1 : -1); + }); + const map = { wei: [], shu: [], wu: [], qun: [], key: [], jin: [], ye: [] }; + for (let i = 0; i < choice.length; ++i) { + if (get.is.double(choice[i])) { + // @ts-expect-error 祖宗之法就是这么写的 + var group = get.is.double(choice[i], true); + // @ts-expect-error 祖宗之法就是这么写的 + for (var ii of group) { + if (map[ii] && map[ii].length) { + map[ii].push(choice[i]); + lib.character[choice[i]][1] = ii; + group = false; + break; + } + } + if (group) choice.splice(i--, 1); + } else { + // @ts-expect-error 祖宗之法就是这么写的 + var group = lib.character[choice[i]][1]; + if (map[group]) { + map[group].push(choice[i]); + } + } + } + if (map.ye.length) { + for (const i in map) { + if (i != "ye" && map[i].length) return choice.randomSort(); + } + choice.remove(map.ye[0]); + map.ye.remove(map.ye[0]); + for (var i = 0; i < list.length; i++) { + if (lib.character[list[i]][1] != "ye") { + choice.push(list[i]); + list.splice(i--, 1); + return choice.randomSort(); + } + } + } + for (const i in map) { + if (map[i].length < 2) { + if (map[i].length == 1) { + choice.remove(map[i][0]); + list.push(map[i][0]); + } + map[i] = false; + } + } + if (choice.length == num - 1) { + for (let i = 0; i < list.length; ++i) { + if (map[lib.character[list[i]][1]]) { + choice.push(list[i]); + list.splice(i--, 1); + break; + } + } + } else if (choice.length < num - 1) { + let group = null; + for (let i = 0; i < list.length; ++i) { + if (group) { + if (lib.character[list[i]][1] == group || lib.character[list[i]][1] == "ye") { + choice.push(list[i]); + list.splice(i--, 1); + if (choice.length >= num) { + break; + } + } + } else { + if (!map[lib.character[list[i]][1]] && !get.is.double(list[i])) { + group = lib.character[list[i]][1]; + if (group == "ye") group = null; + choice.push(list[i]); + list.splice(i--, 1); + if (choice.length >= num) { + break; + } + } + } + } + } + return choice.randomSort(); + } + + /** + * 联机时获取当前玩家的信息 + * + * @returns {Record} - 玩家信息的对象 + */ + getState() { + /** @type {Record} */ + const state = {}; + for (const playerId in lib.playerOL) { + var player = lib.playerOL[playerId]; + state[playerId] = { + identity: player.identity, + //group:player.group, + shown: player.ai.shown, + }; + } + return state; + } + + /** + * 联机时更新玩家信息 + * + * @param {Record} state - 玩家信息的对象 + */ + updateState(state) { + for (const playerId in state) { + const player = lib.playerOL[playerId]; + if (player) { + player.identity = state[playerId].identity; + //player.group=state[i].group; + player.ai.shown = state[playerId].shown; + } + } + } + + /** + * 联机时获取当前房间的信息 + * + * @param {Dialog} uiintro + */ + getRoomInfo(uiintro) { + var num, last; + if (lib.configOL.initshow_draw == "off") { + num = "关闭"; + } else { + num = { mark: "标记", draw: "摸牌" }[lib.configOL.initshow_draw]; + } + uiintro.add('
群雄割据:' + (lib.configOL.separatism ? "开启" : "关闭")); + uiintro.add('
首亮奖励:' + num); + uiintro.add('
珠联璧合:' + (lib.configOL.zhulian ? "开启" : "关闭")); + uiintro.add('
出牌时限:' + lib.configOL.choose_timeout + "秒"); + uiintro.add('
国战牌堆:' + (lib.configOL.guozhanpile ? "开启" : "关闭")); + uiintro.add('
鏖战模式:' + (lib.configOL.aozhan ? "开启" : "关闭")); + last = uiintro.add('
观看下家副将:' + (lib.configOL.viewnext ? "开启" : "关闭")); + + // @ts-expect-error 祖宗之法就是这么写的 + last.style.paddingBottom = "8px"; + } + + /** + * 为当前对局增加战绩记录 + * + * @param {Boolean} bool - 当前对局是否胜利 + */ + async addRecord(bool) { + if (typeof bool !== "boolean") { + return; + } + + const data = lib.config.gameRecord.guozhan.data; + + const identity = game.me.identity; + if (!data[identity]) { + data[identity] = [0, 0]; + } + + if (bool) { + ++data[identity][0]; + } else { + ++data[identity][1]; + } + + /// 构建战绩记录字符串 + let group = [...lib.group, "ye"]; + // 过滤神和外服势力,以及没有战绩的势力 + group = group.filter(group => group !== "shen" && group !== "western" && data[group]); + // 将战绩记录转换为字符串 + const strs = group.map(group => { + const name = get.translation(`${group[i]}2`); + const [win, lose] = data[group]; + + return `${name}: ${win}胜 ${lose}负`; + }); + const str = strs.join("
"); + + lib.config.gameRecord.guozhan.str = str; + + await game.promises.saveConfig("gameRecord", lib.config.gameRecord); + } + + /** + * 获取某名玩家可能的势力列表 + * + * @param {Player} player - 玩家 + * @returns {Record} - 势力及其对应的名称 + */ + getIdentityList(player) { + // @ts-expect-error 祖宗之法就是这么写的 + if (!player.isUnseen()) return; + // @ts-expect-error 祖宗之法就是这么写的 + if (player === game.me) return; + + let list = { + wei: "魏", + shu: "蜀", + wu: "吴", + qun: "群", + ye: "野", + unknown: "猜", + }; + const num = Math.floor((game.players.length + game.dead.length) / 2); + let noye = true; + if (get.population("wei") >= num) { + // @ts-expect-error 祖宗之法就是这么写的 + delete list.wei; + noye = false; + } + if (get.population("shu") >= num) { + // @ts-expect-error 祖宗之法就是这么写的 + delete list.shu; + noye = false; + } + if (get.population("wu") >= num) { + // @ts-expect-error 祖宗之法就是这么写的 + delete list.wu; + noye = false; + } + if (get.population("qun") >= num) { + // @ts-expect-error 祖宗之法就是这么写的 + delete list.qun; + noye = false; + } + if (noye) { + // @ts-expect-error 祖宗之法就是这么写的 + delete list.ye; + } + return list; + } + + /** + * @param {string[]} list + */ + getIdentityList2(list) { + for (var i in list) { + switch (i) { + case "unknown": + list[i] = "未知"; + break; + case "ye": + list[i] = "野心家"; + break; + case "qun": + list[i] += "雄"; + break; + case "key": + list[i] = "Key"; + break; + case "jin": + list[i] += "朝"; + break; + default: + list[i] += "国"; + } + } + } + + getVideoName() { + var str = get.translation(game.me.name1) + "/" + get.translation(game.me.name2); + var str2 = _status.separatism + ? get.modetrans({ + mode: lib.config.mode, + separatism: true, + }) + : get.cnNumber(parseInt(get.config("player_number"))) + "人" + get.translation(lib.config.mode); + if (game.me.identity == "ye") { + str2 += " - 野心家"; + } + var name = [str, str2]; + return name; + } + showIdentity(started) { + if (game.phaseNumber == 0 && !started) return; + for (var i = 0; i < game.players.length; i++) { + game.players[i].showCharacter(2, false); + } + } + tryResult() { + var map = {}, + sides = [], + pmap = _status.connectMode ? lib.playerOL : game.playerMap, + hiddens = []; + for (var i of game.players) { + if (i.identity == "unknown") { + hiddens.push(i); + continue; + } + var added = false; + for (var j of sides) { + if (i.isFriendOf(pmap[j])) { + added = true; + map[j].push(i); + break; + } + } + if (!added) { + map[i.playerid] = [i]; + sides.push(i.playerid); + } + } + if (!sides.length) return; + else if (sides.length > 1) { + if (!hiddens.length && sides.length == 2) { + if ( + map[sides[0]].length == 1 && + !map[sides[1]].filter(function (i) { + return i.identity != "ye" && i.isUnseen(0); + }).length + ) + map[sides[0]][0].showGiveup(); + if ( + map[sides[1]].length == 1 && + !map[sides[0]].filter(function (i) { + return i.identity != "ye" && i.isUnseen(0); + }).length + ) + map[sides[1]][0].showGiveup(); + } + } else { + var isYe = function (player) { + return player.identity != "ye" && lib.character[player.name1][1] == "ye"; + }; + if (!hiddens.length) { + if (map[sides[0]].length > 1) { + for (var i of map[sides[0]]) { + if (isYe(i)) { + game.showYexings(); + return; + } + } + } + game.broadcastAll(function (id) { + game.winner_id = id; + }, sides[0]); + game.checkResult(); + } else { + var identity = map[sides[0]][0].identity; + if (identity == "ye") return; + for (var i of map[sides[0]]) { + if (isYe(i)) return; + } + for (var ind = 0; ind < hiddens.length; ind++) { + var current = hiddens[ind]; + if (isYe(current) || current.getGuozhanGroup(2) != identity || !current.wontYe(null, ind + 1)) return; + } + game.broadcastAll(function (id) { + game.winner_id = id; + }, sides[0]); + game.checkResult(); + } + } + } + checkResult() { + _status.overing = true; + var me = game.me._trueMe || game.me; + for (var i = 0; i < game.players.length; i++) { + game.players[i].showCharacter(2); + } + var winner = (_status.connectMode ? lib.playerOL : game.playerMap)[game.winner_id]; + game.over(winner && winner.isFriendOf(me) ? true : false); + game.showIdentity(); + } + checkOnlineResult(player) { + var winner = lib.playerOL[game.winner_id]; + return winner && winner.isFriendOf(game.me); + } + chooseCharacter() { + var next = game.createEvent("chooseCharacter"); + next.showConfig = true; + next.addPlayer = true; + next.ai = function (player, list, back) { + if (_status.brawl && _status.brawl.chooseCharacterAi) { + if (_status.brawl.chooseCharacterAi(player, list, back) !== false) { + return; + } + } + var filterChoice = function (name1, name2) { + if (_status.separatism) return true; + var group1 = lib.character[name1][1]; + var group2 = lib.character[name2][1]; + var doublex = get.is.double(name1, true); + if (doublex) { + var double = get.is.double(name2, true); + if (double) return doublex.some(group => double.includes(group)); + return doublex.includes(group2); + } else { + if (group1 == "ye") return group2 != "ye"; + var double = get.is.double(name2, true); + if (double) return double.includes(group1); + return group1 == group2; + } + }; + for (var i = 0; i < list.length - 1; i++) { + for (var j = i + 1; j < list.length; j++) { + if (filterChoice(list[i], list[j]) || filterChoice(list[j], list[i])) { + var mainx = list[i]; + var vicex = list[j]; + if (!filterChoice(mainx, vicex) || (filterChoice(vicex, mainx) && get.guozhanReverse(mainx, vicex))) { + mainx = list[j]; + vicex = list[i]; + } + player.init(mainx, vicex, false); + if (get.is.double(mainx, true)) { + if (!get.is.double(vicex, true)) player.trueIdentity = lib.character[vicex][1]; + else if (get.is.double(mainx, true).removeArray(get.is.double(vicex, true)).length == 0 || get.is.double(vicex, true).removeArray(get.is.double(mainx, true)).length == 0) + player.trueIdentity = get.is + .double(vicex, true) + .filter(group => get.is.double(mainx, true).includes(group)) + .randomGet(); + else player.trueIdentity = get.is.double(mainx, true).find(group => get.is.double(vicex, true).includes(group)); + } else if (lib.character[mainx][1] == "ye" && get.is.double(vicex, true)) player.trueIdentity = get.is.double(vicex, true).randomGet(); + if (back) { + list.remove(player.name1); + list.remove(player.name2); + for (var i = 0; i < list.length; i++) { + back.push(list[i]); + } + } + return; + } + } + } + }; + next.setContent(function () { + "step 0"; + ui.arena.classList.add("choose-character"); + var addSetting = function (dialog) { + dialog.add("选择座位").classList.add("add-setting"); + var seats = document.createElement("table"); + seats.classList.add("add-setting"); + seats.style.margin = "0"; + seats.style.width = "100%"; + seats.style.position = "relative"; + for (var i = 1; i <= game.players.length; i++) { + var td = ui.create.div(".shadowed.reduce_radius.pointerdiv.tdnode"); + td.innerHTML = "" + get.cnNumber(i, true) + ""; + td.link = i - 1; + seats.appendChild(td); + td.addEventListener(lib.config.touchscreen ? "touchend" : "click", function () { + if (_status.dragged) return; + if (_status.justdragged) return; + if (_status.cheat_seat) { + _status.cheat_seat.classList.remove("bluebg"); + if (_status.cheat_seat == this) { + delete _status.cheat_seat; + return; + } + } + this.classList.add("bluebg"); + _status.cheat_seat = this; + }); + } + dialog.content.appendChild(seats); + if (game.me == game.zhu) { + seats.previousSibling.style.display = "none"; + seats.style.display = "none"; + } + + dialog.add(ui.create.div(".placeholder.add-setting")); + dialog.add(ui.create.div(".placeholder.add-setting")); + if (get.is.phoneLayout()) dialog.add(ui.create.div(".placeholder.add-setting")); + }; + var removeSetting = function () { + var dialog = _status.event.dialog; + if (dialog) { + dialog.style.height = ""; + delete dialog._scrollset; + var list = Array.from(dialog.querySelectorAll(".add-setting")); + while (list.length) { + list.shift().remove(); + } + ui.update(); + } + }; + event.addSetting = addSetting; + event.removeSetting = removeSetting; + + var chosen = lib.config.continue_name || []; + game.saveConfig("continue_name"); + event.chosen = chosen; + + var i; + event.list = []; + for (i in lib.character) { + if (i.indexOf("gz_shibing") == 0) continue; + if (chosen.includes(i)) continue; + if (lib.filter.characterDisabled(i)) continue; + if (get.config("onlyguozhan")) { + if (!lib.characterGuozhanFilter.some(pack => lib.characterPack[pack][i])) continue; + if (get.is.jun(i)) continue; + } + if (lib.character[i].hasHiddenSkill) continue; + event.list.push(i); + } + _status.characterlist = event.list.slice(0); + _status.yeidentity = []; + if (_status.brawl && _status.brawl.chooseCharacterFilter) { + event.list = _status.brawl.chooseCharacterFilter(event.list); + } + event.list.randomSort(); + // var list=event.list.splice(0,parseInt(get.config('choice_num'))); + var list; + if (_status.brawl && _status.brawl.chooseCharacter) { + list = _status.brawl.chooseCharacter(event.list, game.me); + } else { + list = game.getCharacterChoice(event.list, parseInt(get.config("choice_num"))); + } + if (_status.auto) { + event.ai(game.me, list); + lib.init.onfree(); + } else if (chosen.length) { + game.me.init(chosen[0], chosen[1], false); + lib.init.onfree(); + } else { + var dialog = ui.create.dialog("选择角色", "hidden", [list, "character"]); + if (!_status.brawl || !_status.brawl.noAddSetting) { + if (get.config("change_identity")) { + addSetting(dialog); + } + } + var next = game.me.chooseButton(dialog, true, 2).set("onfree", true); + next.filterButton = function (button) { + if (ui.dialog.buttons.length <= 10) { + for (var i = 0; i < ui.dialog.buttons.length; i++) { + if (ui.dialog.buttons[i] != button) { + if ( + lib.element.player.perfectPair.call( + { + name1: button.link, + name2: ui.dialog.buttons[i].link, + }, + true + ) + ) { + button.classList.add("glow2"); + } + } + } + } + if (lib.character[button.link].hasHiddenSkill) return false; + var filterChoice = function (name1, name2) { + if (_status.separatism) return true; + var group1 = lib.character[name1][1]; + var group2 = lib.character[name2][1]; + var doublex = get.is.double(name1, true); + if (doublex) { + var double = get.is.double(name2, true); + if (double) return doublex.some(group => double.includes(group)); + return doublex.includes(group2); + } else { + if (group1 == "ye") return group2 != "ye"; + var double = get.is.double(name2, true); + if (double) return double.includes(group1); + return group1 == group2; + } + }; + if (!ui.selected.buttons.length) { + return ui.dialog.buttons.some(but => { + if (but == button) return false; + return filterChoice(button.link, but.link); + }); + } + return filterChoice(ui.selected.buttons[0].link, button.link); + }; + next.switchToAuto = function () { + event.ai(game.me, list); + ui.arena.classList.remove("selecting"); + }; + var createCharacterDialog = function () { + event.dialogxx = ui.create.characterDialog( + "heightset", + function (i) { + if (i.indexOf("gz_shibing") == 0) return true; + if (get.config("onlyguozhan")) { + if (!lib.characterGuozhanFilter.some(pack => lib.characterPack[pack][i])) return true; + if (get.is.jun(i)) return true; + } + }, + get.config("onlyguozhanexpand") ? "expandall" : undefined, + get.config("onlyguozhan") ? "onlypack:mode_guozhan" : undefined + ); + if (ui.cheat2) { + ui.cheat2.addTempClass("controlpressdownx", 500); + ui.cheat2.classList.remove("disabled"); + } + }; + if (lib.onfree) { + lib.onfree.push(createCharacterDialog); + } else { + createCharacterDialog(); + } + ui.create.cheat2 = function () { + ui.cheat2 = ui.create.control("自由选将", function () { + if (this.dialog == _status.event.dialog) { + if (game.changeCoin) { + game.changeCoin(10); + } + this.dialog.close(); + _status.event.dialog = this.backup; + this.backup.open(); + delete this.backup; + game.uncheck(); + game.check(); + if (ui.cheat) { + ui.cheat.addTempClass("controlpressdownx", 500); + ui.cheat.classList.remove("disabled"); + } + } else { + if (game.changeCoin) { + game.changeCoin(-10); + } + this.backup = _status.event.dialog; + _status.event.dialog.close(); + _status.event.dialog = _status.event.parent.dialogxx; + this.dialog = _status.event.dialog; + this.dialog.open(); + game.uncheck(); + game.check(); + if (ui.cheat) { + ui.cheat.classList.add("disabled"); + } + } + }); + if (lib.onfree) { + ui.cheat2.classList.add("disabled"); + } + }; + ui.create.cheat = function () { + _status.createControl = ui.cheat2; + ui.cheat = ui.create.control("更换", function () { + if (ui.cheat2 && ui.cheat2.dialog == _status.event.dialog) { + return; + } + if (game.changeCoin) { + game.changeCoin(-3); + } + event.list = event.list.concat(list); + event.list.randomSort(); + // list=event.list.splice(0,parseInt(get.config('choice_num'))); + list = game.getCharacterChoice(event.list, parseInt(get.config("choice_num"))); + var buttons = ui.create.div(".buttons"); + var node = _status.event.dialog.buttons[0].parentNode; + _status.event.dialog.buttons = ui.create.buttons(list, "character", buttons); + _status.event.dialog.content.insertBefore(buttons, node); + buttons.addTempClass("start"); + node.remove(); + game.uncheck(); + game.check(); + }); + delete _status.createControl; + }; + if (!_status.brawl || !_status.brawl.chooseCharacterFixed) { + if (!ui.cheat && get.config("change_choice")) ui.create.cheat(); + if (!ui.cheat2 && get.config("free_choose")) ui.create.cheat2(); + } + } + ("step 1"); + if (ui.cheat) { + ui.cheat.close(); + delete ui.cheat; + } + if (ui.cheat2) { + ui.cheat2.close(); + delete ui.cheat2; + } + if (result.buttons) { + var name1 = result.buttons[0].link, + name2 = result.buttons[1].link; + event.choosen = [name1, name2]; + if (get.is.double(name1, true)) { + if (!get.is.double(name2, true)) event._result = { control: lib.character[name2][1] }; + else if (get.is.double(name1, true).removeArray(get.is.double(name2, true)).length == 0 || get.is.double(name2, true).removeArray(get.is.double(name1, true)).length == 0) + game.me + .chooseControl(get.is.double(name2, true).filter(group => get.is.double(name1, true).includes(group))) + .set("prompt", "请选择你代表的势力") + .set("ai", () => _status.event.controls.randomGet()); + else + event._result = { + control: get.is.double(name1, true).find(group => get.is.double(name2, true).includes(group)), + }; + } else if (lib.character[name1][1] == "ye" && get.is.double(name2, true)) + game.me + .chooseControl(get.is.double(name2, true)) + .set("prompt", "请选择副将代表的势力") + .set("ai", () => _status.event.controls.randomGet()); + } + ("step 2"); + if (result && result.control) game.me.trueIdentity = result.control; + if (event.choosen) { + game.me.init(event.choosen[0], event.choosen[1], false); + game.addRecentCharacter(event.choosen[0], event.choosen[1]); + } + event.list.remove(game.me.name1); + event.list.remove(game.me.name2); + for (var i = 0; i < game.players.length; i++) { + if (game.players[i] != game.me) { + event.ai(game.players[i], game.getCharacterChoice(event.list, parseInt(get.config("choice_num"))), event.list); + } + } + for (var i = 0; i < game.players.length; i++) { + game.players[i].classList.add("unseen"); + game.players[i].classList.add("unseen2"); + _status.characterlist.remove(game.players[i].name); + _status.characterlist.remove(game.players[i].name2); + if (game.players[i] != game.me) { + game.players[i].node.identity.firstChild.innerHTML = "猜"; + game.players[i].node.identity.dataset.color = "unknown"; + game.players[i].node.identity.classList.add("guessing"); + } + game.players[i].hiddenSkills = lib.character[game.players[i].name1][3].slice(0); + var hiddenSkills2 = lib.character[game.players[i].name2][3]; + for (var j = 0; j < hiddenSkills2.length; j++) { + game.players[i].hiddenSkills.add(hiddenSkills2[j]); + } + for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { + if (!lib.skill[game.players[i].hiddenSkills[j]]) { + game.players[i].hiddenSkills.splice(j--, 1); + } + } + game.players[i].group = "unknown"; + game.players[i].sex = "unknown"; + game.players[i].name1 = game.players[i].name; + game.players[i].name = "unknown"; + game.players[i].identity = "unknown"; + game.players[i].node.name.show(); + game.players[i].node.name2.show(); + for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { + game.players[i].addSkillTrigger(game.players[i].hiddenSkills[j], true); + } + } + setTimeout(function () { + ui.arena.classList.remove("choose-character"); + }, 500); + }); + } + chooseCharacterOL() { + var next = game.createEvent("chooseCharacter"); + next.setContent(function () { + "step 0"; + game.broadcastAll(function () { + ui.arena.classList.add("choose-character"); + for (var i = 0; i < game.players.length; i++) { + game.players[i].classList.add("unseen"); + game.players[i].classList.add("unseen2"); + } + }); + var list = []; + for (var i in lib.characterPack.mode_guozhan) { + if (i.indexOf("gz_shibing") == 0) continue; + if (get.is.jun(i)) continue; + if (lib.config.guozhan_banned && lib.config.guozhan_banned.includes(i)) continue; + list.push(i); + } + _status.characterlist = list.slice(0); + _status.yeidentity = []; + event.list = list.slice(0); + var list2 = []; + var num; + if (lib.configOL.number * 6 > list.length) { + num = 5; + } else if (lib.configOL.number * 7 > list.length) { + num = 6; + } else { + num = 7; + } + var filterButton = function (button) { + if (ui.dialog) { + if (ui.dialog.buttons.length <= 10) { + for (var i = 0; i < ui.dialog.buttons.length; i++) { + if (ui.dialog.buttons[i] != button) { + if ( + lib.element.player.perfectPair.call( + { + name1: button.link, + name2: ui.dialog.buttons[i].link, + }, + true + ) + ) { + button.classList.add("glow2"); + } + } + } + } + } + var filterChoice = function (name1, name2) { + if (_status.separatism) return true; + var group1 = lib.character[name1][1]; + var group2 = lib.character[name2][1]; + var doublex = get.is.double(name1, true); + if (doublex) { + var double = get.is.double(name2, true); + if (double) return doublex.some(group => double.includes(group)); + return doublex.includes(group2); + } else { + if (group1 == "ye") return group2 != "ye"; + var double = get.is.double(name2, true); + if (double) return double.includes(group1); + return group1 == group2; + } + }; + if (!ui.selected.buttons.length) { + return ui.dialog.buttons.some(but => { + if (but == button) return false; + return filterChoice(button.link, but.link); + }); + } + return filterChoice(ui.selected.buttons[0].link, button.link); + }; + list.randomSort(); + for (var i = 0; i < game.players.length; i++) { + list2.push([ + game.players[i], + ["选择角色", [game.getCharacterChoice(list, num), "character"]], + 2, + true, + function () { + return Math.random(); + }, + filterButton, + ]); + } + game.me + .chooseButtonOL(list2, function (player, result) { + if (game.online || player == game.me) player.init(result.links[0], result.links[1], false); + }) + .set("switchToAuto", function () { + _status.event.result = "ai"; + }) + .set("processAI", function () { + var buttons = _status.event.dialog.buttons; + var filterChoice = function (name1, name2) { + if (_status.separatism) return true; + var group1 = lib.character[name1][1]; + var group2 = lib.character[name2][1]; + var doublex = get.is.double(name1, true); + if (doublex) { + var double = get.is.double(name2, true); + if (double) return doublex.some(group => double.includes(group)); + return doublex.includes(group2); + } else { + if (group1 == "ye") return group2 != "ye"; + var double = get.is.double(name2, true); + if (double) return double.includes(group1); + return group1 == group2; + } + }; + for (var i = 0; i < buttons.length - 1; i++) { + for (var j = i + 1; j < buttons.length; j++) { + if (filterChoice(buttons[i].link, buttons[j].link) || filterChoice(buttons[j].link, buttons[i].link)) { + var mainx = buttons[i].link; + var vicex = buttons[j].link; + if (!filterChoice(mainx, vicex) || (filterChoice(vicex, mainx) && get.guozhanReverse(mainx, vicex))) { + mainx = buttons[j].link; + vicex = buttons[i].link; + } + var list = [mainx, vicex]; + return { + bool: true, + links: list, + }; + } + } + } + }); + ("step 1"); + var sort = true, + chosen = [], + chosenCharacter = []; + for (var i in result) { + if (result[i] && result[i].links) { + for (var j = 0; j < result[i].links.length; j++) { + event.list.remove(result[i].links[j]); + } + } + } + for (var i in result) { + if (result[i] == "ai" || !result[i].links || result[i].links.length < 1) { + if (sort) { + sort = false; + event.list.randomSort(); + } + result[i] = [event.list.shift()]; + var group = lib.character[result[i][0]][1]; + for (var j = 0; j < event.list.length; j++) { + if (lib.character[event.list[j]][1] == group) { + result[i].push(event.list[j]); + event.list.splice(j--, 1); + break; + } + } + } else { + result[i] = result[i].links; + } + var name1 = result[i][0], + name2 = result[i][1]; + if (get.is.double(name1, true)) { + if (!get.is.double(name2, true)) lib.playerOL[i].trueIdentity = lib.character[name2][1]; + else if (get.is.double(name1, true).removeArray(get.is.double(name2, true)).length == 0 || get.is.double(name2, true).removeArray(get.is.double(name1, true)).length == 0) { + chosen.push(lib.playerOL[i]); + chosenCharacter.push([name1, name2]); + } else lib.playerOL[i].trueIdentity = get.is.double(name1, true).find(group => get.is.double(name2, true).includes(group)); + } else if (lib.character[name1][1] == "ye" && get.is.double(name2, true)) { + chosen.push(lib.playerOL[i]); + chosenCharacter.push([name1, name2]); + } + } + event.result2 = result; + if (chosen.length) { + for (var i = 0; i < chosen.length; i++) { + var name1 = chosenCharacter[i][0], + name2 = chosenCharacter[i][1], + str, + choice; + if (get.is.double(name1, true)) { + str = "请选择你代表的势力"; + choice = get.is.double(name2, true).filter(group => get.is.double(name1, true).includes(group)); + } + if (lib.character[name1][1] == "ye") { + str = "请选择你的副将代表的势力"; + choice = get.is.double(name2, true); + } + chosen[i] = [ + chosen[i], + [ + str, + [ + choice.map(function (i) { + return ["", "", "group_" + i]; + }), + "vcard", + ], + ], + 1, + true, + ]; + } + game.me + .chooseButtonOL(chosen, function (player, result) { + if (player == game.me) player.trueIdentity = result.links[0][2].slice(6); + }) + .set("switchToAuto", function () { + _status.event.result = "ai"; + }) + .set("processAI", function () { + return { + bool: true, + links: [_status.event.dialog.buttons.randomGet().link], + }; + }); + } else event._result = {}; + ("step 2"); + if (!result) result = {}; + var result2 = event.result2; + game.broadcastAll( + function (result, result2) { + for (var i = 0; i < game.players.length; i++) { + var current = game.players[i], + id = current.playerid; + if (result[id] && !current.name) { + current.init(result[id][0], result[id][1], false); + } + if (result2[id] && result2[id].length) { + current.trueIdentity = result2[id][0][2].slice(6); + } + if (game.players[i] != game.me) { + game.players[i].node.identity.firstChild.innerHTML = "猜"; + game.players[i].node.identity.dataset.color = "unknown"; + game.players[i].node.identity.classList.add("guessing"); + } + game.players[i].hiddenSkills = lib.character[game.players[i].name1][3].slice(0); + var hiddenSkills2 = lib.character[game.players[i].name2][3]; + for (var j = 0; j < hiddenSkills2.length; j++) { + game.players[i].hiddenSkills.add(hiddenSkills2[j]); + } + for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { + if (!lib.skill[game.players[i].hiddenSkills[j]]) { + game.players[i].hiddenSkills.splice(j--, 1); + } + } + game.players[i].group = "unknown"; + game.players[i].sex = "unknown"; + game.players[i].name1 = game.players[i].name; + game.players[i].name = "unknown"; + game.players[i].identity = "unknown"; + game.players[i].node.name.show(); + game.players[i].node.name2.show(); + for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { + game.players[i].addSkillTrigger(game.players[i].hiddenSkills[j], true); + } + } + setTimeout(function () { + ui.arena.classList.remove("choose-character"); + }, 500); + }, + result2, + result + ); + }); + } +} + +/** + * + * @param {GameEvent} event + * @param {GameEvent} _trigger + * @param {Player} player + */ +export async function showYexingsContent(event, _trigger, player) { + /** @type {Player[]} */ + // @ts-expect-error 类型就是这样的 + const yexingPlayers = game + .filterPlayer(current => lib.character[current.name1][1] == "ye") + // @ts-expect-error 祖宗之法就是这么写的 + .sortBySeat(_status.currentPhase); + + /** @type {Player[]} */ + let showYexingPlayers = []; + for (const target of yexingPlayers) { + const next = target.chooseBool("是否【暴露野心】,展示主将并继续战斗?", "若选择“否”,则视为本局游戏失败"); + + next.set("ai", showCheck); + + if (await next.forResultBool()) { + showYexingPlayers.push(target); + target.$fullscreenpop("暴露野心", "thunder"); + game.log(target, "暴露了野心"); + await target.showCharacter(0); + await game.delay(2); + } + + /** + * 是否暴露野心的AI + * + * @param {GameEvent} _event + * @param {Player} _player + */ + function showCheck(_event, _player) { + // TODO: 未来再想AI该怎么写 + return Math.random() < 0.5; + } + } + + // 如果没有人暴露野心,那么游戏结束 + if (showYexingPlayers.length === 0) { + const winner = game.findPlayer(current => lib.character[current.name1][1] != "ye"); + + if (winner) { + broadcastAll(id => { + // @ts-expect-error 祖宗之法就是这么写的 + game.winner_id = id; + }, winner.playerid); + // @ts-expect-error 祖宗之法就是这么写的 + game.checkResult(); + } + + // @ts-expect-error 祖宗之法就是这么写的 + delete _status.showYexings; + return; + } + + let yexingGroupList = ["夏", "商", "周", "秦", "汉", "隋", "唐", "宋", "辽", "金", "元", "明"]; + for (const target of showYexingPlayers) { + // 基本不可能发生 + if (yexingGroupList.length === 0) { + yexingGroupList = ["夏", "商", "周", "秦", "汉", "隋", "唐", "宋", "辽", "金", "元", "明"]; + } + + const next = target.chooseControl(yexingGroupList); + + next.set("prompt", "请选择自己所属的野心家势力的标识"); + next.set("ai", () => (yexingGroupList ? yexingGroupList.randomGet() : 0)); + + /** @type {string} */ + let text; + + const control = await next.forResultControl(); + if (control) { + text = control; + yexingGroupList.remove(control); + } else { + text = yexingGroupList.randomRemove() ?? "野"; + } + + lib.group.push(text); + lib.translate[`${text}2`] = text; + lib.groupnature[text] = "kami"; + + broadcastAll( + /** + * @param {Player} player + * @param {string} text + */ + (player, text) => { + player.identity = text; + player.setIdentity(text, "kami"); + }, + target, + text + ); + + target.changeGroup(text); + target.removeMark("yexinjia_mark", 1); + + /** @type {Player[]} */ + // @ts-expect-error 祖宗之法就是这么写的 + const maybeFriends = game.players.filter(current => current.identity != "ye" && current !== target && !get.is.jun(current) && !yexingPlayers.includes(current) && !current.getStorage("yexinjia_friend").length); + if (maybeFriends.length === 0) { + continue; + } + + /** @type {Player[]} */ + const refused = []; + for (const other of maybeFriends) { + target.line(other, "green"); + + const next = other.chooseBool(`是否响应${get.translation(target)}发起的【拉拢人心】?`, `将势力改为${text}`); + + next.set("source", target); + next.set("ai", check); + + if (await next.forResultBool()) { + other.chat("加入"); + //event.targets4.push(target); + broadcastAll( + /** + * @param {Player} player + * @param {string} text + */ + (player, text) => { + player.identity = text; + player.setIdentity(text, "kami"); + }, + other, + text + ); + other.changeGroup(text); + } else { + other.chat("拒绝"); + refused.push(other); + } + + /** + * @param {GameEvent} _event + * @param {Player} _player + * @returns {boolean} + */ + function check(_event, _player) { + const player = get.player(); + const source = get.event("source"); + const friendsCount = target.getFriends(true).length; + + if (game.players.length <= 2 * friendsCount) { + return false; + } + // @ts-expect-error 祖宗之法就是这么写的 + if (source.getFriends(true).length + friendsCount > game.players.length / 2) { + return true; + } + + if (player.isDamaged() || player.countCards("h") < 4) { + return false; + } + + return true; + } + } + + for (const other of refused) { + await other.drawTo(4, []); + await other.recover(); + } + } + + // @ts-expect-error 祖宗之法就是这么写的 + delete _status.showYexings; + if ( + !game.hasPlayer(current => { + return game.hasPlayer(target => { + return !target.isFriendOf(current); + }); + }) + ) { + broadcastAll(id => { + // @ts-expect-error 祖宗之法就是这么写的 + game.winner_id = id; + }, event.source.playerid); + // @ts-expect-error 祖宗之法就是这么写的 + game.checkResult(); + } +} + +/** + * `Game#broadcast`的类型兼容版本 + * + * 未来或许会移动到别的地方,但目前先直接放国战里 + * + * @template {(...args: any[]) => unknown} T + * @param {T} func + * @param {Parameters} args + */ +export function broadcast(func, ...args) { + // @ts-expect-error 类型就是这么写的 + return game.broadcast(func, ...args); +} + +/** + * `Game#broadcastAll`的类型兼容版本 + * + * 未来或许会移动到别的地方,但目前先直接放国战里 + * + * @template {(...args: any[]) => unknown} T + * @param {T} func + * @param {Parameters} args + */ +export function broadcastAll(func, ...args) { + // @ts-expect-error 类型就是这么写的 + return game.broadcastAll(func, ...args); +} From d2d613949596c37eadb6f07e37cb80a3de82561c Mon Sep 17 00:00:00 2001 From: Rintim Date: Mon, 10 Mar 2025 21:03:14 +0800 Subject: [PATCH 10/48] =?UTF-8?q?pref:=20=E5=AF=B9=E9=83=A8=E5=88=86?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E8=BF=9B=E8=A1=8C=E6=8B=86=E5=88=86=E5=BD=92?= =?UTF-8?q?=E7=B1=BB=EF=BC=9B=E6=8F=90=E4=BE=9B=E6=97=A0=E5=90=8D=E6=9D=80?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E7=9A=84=E8=A1=A5=E4=B8=81=E5=AF=B9=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mode/guozhan.js | 1325 +---------------------------- mode/guozhan/src/patch/content.js | 193 +++++ mode/guozhan/src/patch/game.js | 232 +---- mode/guozhan/src/patch/index.js | 28 + 4 files changed, 264 insertions(+), 1514 deletions(-) create mode 100644 mode/guozhan/src/patch/content.js create mode 100644 mode/guozhan/src/patch/index.js diff --git a/mode/guozhan.js b/mode/guozhan.js index ced99812cb..1e17220a34 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -1,4 +1,7 @@ import { lib, game, ui, get, ai, _status } from "../noname.js"; +import { start, startBefore, onreinit } from "./guozhan/src/main.js"; +import { gamePatch } from "./guozhan/src/patch/index.js"; + export const type = "mode"; /** * @type { () => importModeConfig } @@ -6,232 +9,9 @@ export const type = "mode"; export default () => { return { name: "guozhan", - startBefore() { - var playback = localStorage.getItem(lib.configprefix + "playback"); - for (var i in lib.characterPack.mode_guozhan) { - if (!get.config("onlyguozhan") && !playback) { - if (lib.character[i.slice(3)]) continue; - } - lib.character[i] = lib.characterPack.mode_guozhan[i]; - if (!lib.translate["#" + i + ":die"] && !lib.character[i].dieAudios?.length) { - let list = lib.character?.[i.slice(3)]?.dieAudios; - lib.character[i].dieAudios = list?.length ? list : [i.slice(3)]; - } - if (!lib.translate[i]) { - lib.translate[i] = lib.translate[i.slice(3)]; - } - } - for (var i in lib.character) { - if (lib.character[i].group == "shen") { - lib.character[i].group = lib.character[i].groupInGuozhan || "qun"; - } - } - }, - onreinit() { - var pack = lib.characterPack.mode_guozhan; - for (var i in pack) { - lib.character[i] = pack[i]; - if (!lib.translate["#" + i + ":die"] && !lib.character[i].dieAudios?.length) { - let list = lib.character?.[i.slice(3)]?.dieAudios; - lib.character[i].dieAudios = list?.length ? list : [i.slice(3)]; - } - if (!lib.translate[i]) { - lib.translate[i] = lib.translate[i.slice(3)]; - } - } - for (var i in lib.character) { - if (lib.character[i].group == "shen" || lib.character[i].group == "western") { - lib.character[i].group = lib.character[i].groupInGuozhan || "qun"; - } - } - }, - start() { - "step 0"; - var playback = localStorage.getItem(lib.configprefix + "playback"); - if (playback) { - ui.create.me(); - ui.arena.style.display = "none"; - ui.system.style.display = "none"; - _status.playback = playback; - localStorage.removeItem(lib.configprefix + "playback"); - var store = lib.db.transaction(["video"], "readwrite").objectStore("video"); - store.get(parseInt(playback)).onsuccess = function (e) { - if (e.target.result) { - game.playVideoContent(e.target.result.video); - } else { - alert("播放失败:找不到录像"); - game.reload(); - } - }; - event.finish(); - } else if (_status.connectMode) { - game.waitForPlayer(); - } else { - _status.mode = get.config("guozhan_mode"); - if (!["normal", "yingbian", "old", "free"].includes(_status.mode)) _status.mode = "normal"; - //决定牌堆 - switch (_status.mode) { - case "old": - lib.card.list = lib.guozhanPile_old.slice(0); - break; - case "yingbian": - lib.card.list = lib.guozhanPile_yingbian.slice(0); - delete lib.translate.shuiyanqijunx_info_guozhan; - const pack = lib.yingbian_guozhan; - for (const i in pack) { - lib.character[i] = pack[i]; - lib.characterPack.mode_guozhan[i] = pack[i]; - if (!lib.translate["#" + i + ":die"] && !lib.character[i].dieAudios?.length) { - let list = lib.character?.[i.slice(3)]?.dieAudios; - lib.character[i].dieAudios = list?.length ? list : [i.slice(3)]; - } - if (!lib.translate[i]) lib.translate[i] = lib.translate[i.slice(3)]; - } - break; - case "normal": - lib.card.list = lib.guozhanPile.slice(0); - break; - } - if (_status.mode != "free") game.fixedPile = true; - else { - delete lib.translate.shuiyanqijunx_info_guozhan; - } - game.prepareArena(); - // game.delay(); - game.showChangeLog(); - } - if (!_status.connectMode) { - _status.mode = get.config("guozhan_mode"); - if (_status.brawl && _status.brawl.submode) { - _status.mode = _status.brawl.submode; - } - if (get.config("separatism")) _status.separatism = true; - } - "step 1"; - if (_status.connectMode) { - _status.mode = lib.configOL.guozhan_mode; - if (!["normal", "yingbian", "old"].includes(_status.mode)) _status.mode = "normal"; - if (lib.configOL.separatism) _status.separatism = true; - //决定牌堆 - switch (_status.mode) { - case "old": - lib.card.list = lib.guozhanPile_old.slice(0); - break; - case "yingbian": - lib.card.list = lib.guozhanPile_yingbian.slice(0); - delete lib.translate.shuiyanqijunx_info_guozhan; - break; - default: - lib.card.list = lib.guozhanPile.slice(0); - break; - } - game.fixedPile = true; - game.broadcastAll( - (mode, separatism) => { - _status.mode = mode; - if (separatism) _status.separatism = true; - var pack = lib.characterPack.mode_guozhan; - if (mode == "yingbian") { - delete lib.translate.shuiyanqijunx_info_guozhan; - const pack2 = lib.yingbian_guozhan; - for (const i in pack2) { - pack[i] = pack2[i]; - } - } - for (var i = 0; i < game.players.length; i++) { - game.players[i].node.name.hide(); - game.players[i].node.name2.hide(); - } - for (var i in pack) { - lib.character[i] = pack[i]; - if (!lib.translate["#" + i + ":die"] && !lib.character[i].dieAudios?.length) { - let list = lib.character?.[i.slice(3)]?.dieAudios; - lib.character[i].dieAudios = list?.length ? list : [i.slice(3)]; - } - if (!lib.translate[i]) { - lib.translate[i] = lib.translate[i.slice(3)]; - } - } - for (var i in lib.character) { - if (lib.character[i][1] == "shen" || lib.character[i][1] == "western") { - lib.character[i].group = lib.character[i].groupInGuozhan || "qun"; - } - } - //lib.characterReplace={}; - }, - _status.mode, - _status.separatism - ); - game.randomMapOL(); - } else { - //lib.characterReplace={}; - for (var i = 0; i < game.players.length; i++) { - game.players[i].node.name.hide(); - game.players[i].node.name2.hide(); - game.players[i].getId(); - } - if (_status.brawl && _status.brawl.chooseCharacterBefore) { - _status.brawl.chooseCharacterBefore(); - } - game.chooseCharacter(); - } - "step 2"; - //game.broadcastAll(function(){ - // lib.inpile.removeArray(['gz_haolingtianxia','gz_kefuzhongyuan','gz_guguoanbang','gz_wenheluanwu']); - //}); - if (ui.coin) { - _status.coinCoeff = get.coinCoeff([game.me.name1, game.me.name2]); - } - var player; - if (_status.cheat_seat) { - var seat = _status.cheat_seat.link; - if (seat == 0) { - player = game.me; - } else { - player = game.players[game.players.length - seat]; - } - if (!player) player = game.me; - delete _status.cheat_seat; - } else { - player = game.players[Math.floor(Math.random() * game.players.length)]; - } - event.playerx = player; - event.trigger("gameStart"); - "step 3"; - game.gameDraw(event.playerx); - game.broadcastAll(function (player) { - for (var i = 0; i < game.players.length; i++) { - var seatNum = get.distance(player, game.players[i], "absolute"); - game.players[i].name = `unknown${seatNum}`; - game.players[i].node.name_seat = ui.create.div(".name.name_seat", get.seatTranslation(seatNum), game.players[i]); - // if(game.players[i]==game.me){ - // lib.translate[game.players[i].name]+='(你)'; - // } - } - }, event.playerx); - - var players = get.players(lib.sort.position); - var info = []; - for (var i = 0; i < players.length; i++) { - info.push({ - name: game.players[i].name, - translate: lib.translate[game.players[i].name], - name1: players[i].name1, - name2: players[i].name2, - nickname: players[i].node.nameol.innerHTML, - }); - } - (_status.videoInited = true), game.addVideo("init", null, info); - if (_status.mode == "mingjiang") { - game.showIdentity(true); - } else { - for (var i = 0; i < game.players.length; i++) { - game.players[i].ai.shown = 0; - } - } - if (_status.connectMode && lib.configOL.change_card) game.replaceHandcards(game.players.slice(0)); - game.phaseLoop(event.playerx); - }, + startBefore, + onreinit, + start, card: { junling1: { type: "junling", @@ -19475,1098 +19255,7 @@ export default () => { }, }, }, - game: { - canReplaceViewpoint: () => true, - showYexings() { - if (_status.showYexings) return; - _status.showYexings = true; - var next = game.createEvent("showYexings", false); - next.setContent(function () { - "step 0"; - event.targets = game - .filterPlayer(function (current) { - return lib.character[current.name1][1] == "ye"; - }) - .sortBySeat(_status.currentPhase); - event.targets2 = []; - "step 1"; - var target = targets.shift(); - event.target = target; - target.chooseBool("是否【暴露野心】,展示主将并继续战斗?", "若选择“否”,则视为本局游戏失败"); - "step 2"; - if (result.bool) { - event.targets2.push(target); - target.$fullscreenpop("暴露野心", "thunder"); - game.log(target, "暴露了野心"); - target.showCharacter(0); - game.delay(2); - if (targets.length) event.goto(1); - } else { - if (targets.length) event.goto(1); - else { - var winner = game.findPlayer(function (current) { - return lib.character[current.name1][1] != "ye"; - }); - if (winner) { - game.broadcastAll(function (id) { - game.winner_id = id; - }, winner.playerid); - game.checkResult(); - } - delete _status.showYexings; - event.finish(); - } - } - "step 3"; - var source = event.targets2.shift(); - event.source = source; - event.targets3 = []; - //event.targets4=[source]; - if (!_status.yexinjia_list) _status.yexinjia_list = ["夏", "商", "周", "秦", "汉", "隋", "唐", "宋", "辽", "金", "元", "明"]; - source - .chooseControl(_status.yexinjia_list) - .set("prompt", "请选择自己所属的野心家势力的标识") - .set("ai", () => (_status.yexinjia_list ? _status.yexinjia_list.randomGet() : 0)); - "step 4"; - var text, - source = event.source; - if (result.control) { - text = result.control; - _status.yexinjia_list.remove(result.control); - } else text = _status.yexinjia_list.randomRemove(); - lib.group.push(text); - lib.translate[text + "2"] = text; - lib.groupnature[text] = "kami"; - event.text = text; - game.broadcastAll( - function (player, text) { - player.identity = text; - player.setIdentity(text, "kami"); - }, - source, - text - ); - source.changeGroup(text); - source.removeMark("yexinjia_mark", 1); - var targets = game.filterPlayer(function (current) { - return current.identity != "ye" && current != source && !get.is.jun(current) && !event.targets2.includes(current) && !current.getStorage("yexinjia_friend").length; - }); - if (!targets.length) event.goto(8); - else event.targets = targets; - "step 5"; - var source = event.source; - var target = targets.shift(); - event.target = target; - source.line(target, "green"); - target - .chooseBool("是否响应" + get.translation(source) + "发起的【拉拢人心】?", "将势力改为" + event.text) - .set("ai", _status.event.choice) - .set( - "choice", - (function () { - let fs = target.getFriends(true).length; - if (game.players.length <= 2 * fs) return false; - if (source.getFriends(true).length + fs > game.players.length / 2) return true; - if (target.isDamaged() || target.countCards("h") < 4) return false; - return true; - })() - ); - "step 6"; - if (result.bool) { - target.chat("加入"); - //event.targets4.push(target); - game.broadcastAll( - function (player, text) { - player.identity = text; - player.setIdentity(text, "kami"); - }, - target, - event.text - ); - target.changeGroup(event.text); - } else { - target.chat("拒绝"); - event.targets3.push(target); - } - game.delay(1.5); - if (targets.length) event.goto(5); - /* - else if(event.targets4.length){ - for(var i of event.targets4){ - i.markAuto('yexinjia_friend',event.targets4.filter(j=>j!=i)); - } - } - */ - "step 7"; - if (event.targets3.length) { - for (var i of event.targets3) { - i.drawTo(4); - i.recover(); - } - } - "step 8"; - if (event.targets2.length) event.goto(3); - else { - delete _status.showYexings; - if ( - !game.hasPlayer(current => { - return game.hasPlayer(target => { - return !target.isFriendOf(current); - }); - }) - ) { - game.broadcastAll(function (id) { - game.winner_id = id; - }, event.source.playerid); - game.checkResult(); - } - } - }); - }, - getCharacterChoice(list, num) { - var choice = list.splice(0, num).sort(function (a, b) { - return (get.is.double(a) ? 1 : -1) - (get.is.double(b) ? 1 : -1); - }); - var map = { wei: [], shu: [], wu: [], qun: [], key: [], jin: [], ye: [] }; - for (var i = 0; i < choice.length; i++) { - if (get.is.double(choice[i])) { - var group = get.is.double(choice[i], true); - for (var ii of group) { - if (map[ii] && map[ii].length) { - map[ii].push(choice[i]); - lib.character[choice[i]][1] = ii; - group = false; - break; - } - } - if (group) choice.splice(i--, 1); - } else { - var group = lib.character[choice[i]][1]; - if (map[group]) { - map[group].push(choice[i]); - } - } - } - if (map.ye.length) { - for (var i in map) { - if (i != "ye" && map[i].length) return choice.randomSort(); - } - choice.remove(map.ye[0]); - map.ye.remove(map.ye[0]); - for (var i = 0; i < list.length; i++) { - if (lib.character[list[i]][1] != "ye") { - choice.push(list[i]); - list.splice(i--, 1); - return choice.randomSort(); - } - } - } - for (var i in map) { - if (map[i].length < 2) { - if (map[i].length == 1) { - choice.remove(map[i][0]); - list.push(map[i][0]); - } - map[i] = false; - } - } - if (choice.length == num - 1) { - for (var i = 0; i < list.length; i++) { - if (map[lib.character[list[i]][1]]) { - choice.push(list[i]); - list.splice(i--, 1); - break; - } - } - } else if (choice.length < num - 1) { - var group = null; - for (var i = 0; i < list.length; i++) { - if (group) { - if (lib.character[list[i]][1] == group || lib.character[list[i]][1] == "ye") { - choice.push(list[i]); - list.splice(i--, 1); - if (choice.length >= num) { - break; - } - } - } else { - if (!map[lib.character[list[i]][1]] && !get.is.double(list[i])) { - group = lib.character[list[i]][1]; - if (group == "ye") group = null; - choice.push(list[i]); - list.splice(i--, 1); - if (choice.length >= num) { - break; - } - } - } - } - } - return choice.randomSort(); - }, - getState() { - var state = {}; - for (var i in lib.playerOL) { - var player = lib.playerOL[i]; - state[i] = { - identity: player.identity, - //group:player.group, - shown: player.ai.shown, - }; - } - return state; - }, - updateState(state) { - for (var i in state) { - var player = lib.playerOL[i]; - if (player) { - player.identity = state[i].identity; - //player.group=state[i].group; - player.ai.shown = state[i].shown; - } - } - }, - getRoomInfo(uiintro) { - var num, last; - if (lib.configOL.initshow_draw == "off") { - num = "关闭"; - } else { - num = { mark: "标记", draw: "摸牌" }[lib.configOL.initshow_draw]; - } - uiintro.add('
群雄割据:' + (lib.configOL.separatism ? "开启" : "关闭")); - uiintro.add('
首亮奖励:' + num); - uiintro.add('
珠联璧合:' + (lib.configOL.zhulian ? "开启" : "关闭")); - uiintro.add('
出牌时限:' + lib.configOL.choose_timeout + "秒"); - uiintro.add('
国战牌堆:' + (lib.configOL.guozhanpile ? "开启" : "关闭")); - uiintro.add('
鏖战模式:' + (lib.configOL.aozhan ? "开启" : "关闭")); - last = uiintro.add('
观看下家副将:' + (lib.configOL.viewnext ? "开启" : "关闭")); - last.style.paddingBottom = "8px"; - }, - addRecord(bool) { - if (typeof bool == "boolean") { - var data = lib.config.gameRecord.guozhan.data; - var identity = game.me.identity; - if (!data[identity]) { - data[identity] = [0, 0]; - } - if (bool) { - data[identity][0]++; - } else { - data[identity][1]++; - } - var list = lib.group.slice(0); - list.add("ye"); - var str = ""; - for (var i = 0; i < list.length; i++) { - if (list[i] != "shen" && list[i] != "western" && data[list[i]]) { - str += lib.translate[list[i] + "2"] + ":" + data[list[i]][0] + "胜" + " " + data[list[i]][1] + "负
"; - } - } - lib.config.gameRecord.guozhan.str = str; - game.saveConfig("gameRecord", lib.config.gameRecord); - } - }, - getIdentityList(player) { - if (!player.isUnseen()) return; - if (player == game.me) return; - var list = { - wei: "魏", - shu: "蜀", - wu: "吴", - qun: "群", - ye: "野", - unknown: "猜", - }; - var num = Math.floor((game.players.length + game.dead.length) / 2); - var noye = true; - if (get.population("wei") >= num) { - delete list.wei; - noye = false; - } - if (get.population("shu") >= num) { - delete list.shu; - noye = false; - } - if (get.population("wu") >= num) { - delete list.wu; - noye = false; - } - if (get.population("qun") >= num) { - delete list.qun; - noye = false; - } - if (noye) { - delete list.ye; - } - return list; - }, - getIdentityList2(list) { - for (var i in list) { - switch (i) { - case "unknown": - list[i] = "未知"; - break; - case "ye": - list[i] = "野心家"; - break; - case "qun": - list[i] += "雄"; - break; - case "key": - list[i] = "Key"; - break; - case "jin": - list[i] += "朝"; - break; - default: - list[i] += "国"; - } - } - }, - getVideoName() { - var str = get.translation(game.me.name1) + "/" + get.translation(game.me.name2); - var str2 = _status.separatism - ? get.modetrans({ - mode: lib.config.mode, - separatism: true, - }) - : get.cnNumber(parseInt(get.config("player_number"))) + "人" + get.translation(lib.config.mode); - if (game.me.identity == "ye") { - str2 += " - 野心家"; - } - var name = [str, str2]; - return name; - }, - showIdentity(started) { - if (game.phaseNumber == 0 && !started) return; - for (var i = 0; i < game.players.length; i++) { - game.players[i].showCharacter(2, false); - } - }, - tryResult() { - var map = {}, - sides = [], - pmap = _status.connectMode ? lib.playerOL : game.playerMap, - hiddens = []; - for (var i of game.players) { - if (i.identity == "unknown") { - hiddens.push(i); - continue; - } - var added = false; - for (var j of sides) { - if (i.isFriendOf(pmap[j])) { - added = true; - map[j].push(i); - break; - } - } - if (!added) { - map[i.playerid] = [i]; - sides.push(i.playerid); - } - } - if (!sides.length) return; - else if (sides.length > 1) { - if (!hiddens.length && sides.length == 2) { - if ( - map[sides[0]].length == 1 && - !map[sides[1]].filter(function (i) { - return i.identity != "ye" && i.isUnseen(0); - }).length - ) - map[sides[0]][0].showGiveup(); - if ( - map[sides[1]].length == 1 && - !map[sides[0]].filter(function (i) { - return i.identity != "ye" && i.isUnseen(0); - }).length - ) - map[sides[1]][0].showGiveup(); - } - } else { - var isYe = function (player) { - return player.identity != "ye" && lib.character[player.name1][1] == "ye"; - }; - if (!hiddens.length) { - if (map[sides[0]].length > 1) { - for (var i of map[sides[0]]) { - if (isYe(i)) { - game.showYexings(); - return; - } - } - } - game.broadcastAll(function (id) { - game.winner_id = id; - }, sides[0]); - game.checkResult(); - } else { - var identity = map[sides[0]][0].identity; - if (identity == "ye") return; - for (var i of map[sides[0]]) { - if (isYe(i)) return; - } - for (var ind = 0; ind < hiddens.length; ind++) { - var current = hiddens[ind]; - if (isYe(current) || current.getGuozhanGroup(2) != identity || !current.wontYe(null, ind + 1)) return; - } - game.broadcastAll(function (id) { - game.winner_id = id; - }, sides[0]); - game.checkResult(); - } - } - }, - checkResult() { - _status.overing = true; - var me = game.me._trueMe || game.me; - for (var i = 0; i < game.players.length; i++) { - game.players[i].showCharacter(2); - } - var winner = (_status.connectMode ? lib.playerOL : game.playerMap)[game.winner_id]; - game.over(winner && winner.isFriendOf(me) ? true : false); - game.showIdentity(); - }, - checkOnlineResult(player) { - var winner = lib.playerOL[game.winner_id]; - return winner && winner.isFriendOf(game.me); - }, - chooseCharacter() { - var next = game.createEvent("chooseCharacter"); - next.showConfig = true; - next.addPlayer = true; - next.ai = function (player, list, back) { - if (_status.brawl && _status.brawl.chooseCharacterAi) { - if (_status.brawl.chooseCharacterAi(player, list, back) !== false) { - return; - } - } - var filterChoice = function (name1, name2) { - if (_status.separatism) return true; - var group1 = lib.character[name1][1]; - var group2 = lib.character[name2][1]; - var doublex = get.is.double(name1, true); - if (doublex) { - var double = get.is.double(name2, true); - if (double) return doublex.some(group => double.includes(group)); - return doublex.includes(group2); - } else { - if (group1 == "ye") return group2 != "ye"; - var double = get.is.double(name2, true); - if (double) return double.includes(group1); - return group1 == group2; - } - }; - for (var i = 0; i < list.length - 1; i++) { - for (var j = i + 1; j < list.length; j++) { - if (filterChoice(list[i], list[j]) || filterChoice(list[j], list[i])) { - var mainx = list[i]; - var vicex = list[j]; - if (!filterChoice(mainx, vicex) || (filterChoice(vicex, mainx) && get.guozhanReverse(mainx, vicex))) { - mainx = list[j]; - vicex = list[i]; - } - player.init(mainx, vicex, false); - if (get.is.double(mainx, true)) { - if (!get.is.double(vicex, true)) player.trueIdentity = lib.character[vicex][1]; - else if (get.is.double(mainx, true).removeArray(get.is.double(vicex, true)).length == 0 || get.is.double(vicex, true).removeArray(get.is.double(mainx, true)).length == 0) - player.trueIdentity = get.is - .double(vicex, true) - .filter(group => get.is.double(mainx, true).includes(group)) - .randomGet(); - else player.trueIdentity = get.is.double(mainx, true).find(group => get.is.double(vicex, true).includes(group)); - } else if (lib.character[mainx][1] == "ye" && get.is.double(vicex, true)) player.trueIdentity = get.is.double(vicex, true).randomGet(); - if (back) { - list.remove(player.name1); - list.remove(player.name2); - for (var i = 0; i < list.length; i++) { - back.push(list[i]); - } - } - return; - } - } - } - }; - next.setContent(function () { - "step 0"; - ui.arena.classList.add("choose-character"); - var addSetting = function (dialog) { - dialog.add("选择座位").classList.add("add-setting"); - var seats = document.createElement("table"); - seats.classList.add("add-setting"); - seats.style.margin = "0"; - seats.style.width = "100%"; - seats.style.position = "relative"; - for (var i = 1; i <= game.players.length; i++) { - var td = ui.create.div(".shadowed.reduce_radius.pointerdiv.tdnode"); - td.innerHTML = "" + get.cnNumber(i, true) + ""; - td.link = i - 1; - seats.appendChild(td); - td.addEventListener(lib.config.touchscreen ? "touchend" : "click", function () { - if (_status.dragged) return; - if (_status.justdragged) return; - if (_status.cheat_seat) { - _status.cheat_seat.classList.remove("bluebg"); - if (_status.cheat_seat == this) { - delete _status.cheat_seat; - return; - } - } - this.classList.add("bluebg"); - _status.cheat_seat = this; - }); - } - dialog.content.appendChild(seats); - if (game.me == game.zhu) { - seats.previousSibling.style.display = "none"; - seats.style.display = "none"; - } - - dialog.add(ui.create.div(".placeholder.add-setting")); - dialog.add(ui.create.div(".placeholder.add-setting")); - if (get.is.phoneLayout()) dialog.add(ui.create.div(".placeholder.add-setting")); - }; - var removeSetting = function () { - var dialog = _status.event.dialog; - if (dialog) { - dialog.style.height = ""; - delete dialog._scrollset; - var list = Array.from(dialog.querySelectorAll(".add-setting")); - while (list.length) { - list.shift().remove(); - } - ui.update(); - } - }; - event.addSetting = addSetting; - event.removeSetting = removeSetting; - - var chosen = lib.config.continue_name || []; - game.saveConfig("continue_name"); - event.chosen = chosen; - - var i; - event.list = []; - for (i in lib.character) { - if (i.indexOf("gz_shibing") == 0) continue; - if (chosen.includes(i)) continue; - if (lib.filter.characterDisabled(i)) continue; - if (get.config("onlyguozhan")) { - if (!lib.characterGuozhanFilter.some(pack => lib.characterPack[pack][i])) continue; - if (get.is.jun(i)) continue; - } - if (lib.character[i].hasHiddenSkill) continue; - event.list.push(i); - } - _status.characterlist = event.list.slice(0); - _status.yeidentity = []; - if (_status.brawl && _status.brawl.chooseCharacterFilter) { - event.list = _status.brawl.chooseCharacterFilter(event.list); - } - event.list.randomSort(); - // var list=event.list.splice(0,parseInt(get.config('choice_num'))); - var list; - if (_status.brawl && _status.brawl.chooseCharacter) { - list = _status.brawl.chooseCharacter(event.list, game.me); - } else { - list = game.getCharacterChoice(event.list, parseInt(get.config("choice_num"))); - } - if (_status.auto) { - event.ai(game.me, list); - lib.init.onfree(); - } else if (chosen.length) { - game.me.init(chosen[0], chosen[1], false); - lib.init.onfree(); - } else { - var dialog = ui.create.dialog("选择角色", "hidden", [list, "character"]); - if (!_status.brawl || !_status.brawl.noAddSetting) { - if (get.config("change_identity")) { - addSetting(dialog); - } - } - var next = game.me.chooseButton(dialog, true, 2).set("onfree", true); - next.filterButton = function (button) { - if (ui.dialog.buttons.length <= 10) { - for (var i = 0; i < ui.dialog.buttons.length; i++) { - if (ui.dialog.buttons[i] != button) { - if ( - lib.element.player.perfectPair.call( - { - name1: button.link, - name2: ui.dialog.buttons[i].link, - }, - true - ) - ) { - button.classList.add("glow2"); - } - } - } - } - if (lib.character[button.link].hasHiddenSkill) return false; - var filterChoice = function (name1, name2) { - if (_status.separatism) return true; - var group1 = lib.character[name1][1]; - var group2 = lib.character[name2][1]; - var doublex = get.is.double(name1, true); - if (doublex) { - var double = get.is.double(name2, true); - if (double) return doublex.some(group => double.includes(group)); - return doublex.includes(group2); - } else { - if (group1 == "ye") return group2 != "ye"; - var double = get.is.double(name2, true); - if (double) return double.includes(group1); - return group1 == group2; - } - }; - if (!ui.selected.buttons.length) { - return ui.dialog.buttons.some(but => { - if (but == button) return false; - return filterChoice(button.link, but.link); - }); - } - return filterChoice(ui.selected.buttons[0].link, button.link); - }; - next.switchToAuto = function () { - event.ai(game.me, list); - ui.arena.classList.remove("selecting"); - }; - var createCharacterDialog = function () { - event.dialogxx = ui.create.characterDialog( - "heightset", - function (i) { - if (i.indexOf("gz_shibing") == 0) return true; - if (get.config("onlyguozhan")) { - if (!lib.characterGuozhanFilter.some(pack => lib.characterPack[pack][i])) return true; - if (get.is.jun(i)) return true; - } - }, - get.config("onlyguozhanexpand") ? "expandall" : undefined, - get.config("onlyguozhan") ? "onlypack:mode_guozhan" : undefined - ); - if (ui.cheat2) { - ui.cheat2.addTempClass("controlpressdownx", 500); - ui.cheat2.classList.remove("disabled"); - } - }; - if (lib.onfree) { - lib.onfree.push(createCharacterDialog); - } else { - createCharacterDialog(); - } - ui.create.cheat2 = function () { - ui.cheat2 = ui.create.control("自由选将", function () { - if (this.dialog == _status.event.dialog) { - if (game.changeCoin) { - game.changeCoin(10); - } - this.dialog.close(); - _status.event.dialog = this.backup; - this.backup.open(); - delete this.backup; - game.uncheck(); - game.check(); - if (ui.cheat) { - ui.cheat.addTempClass("controlpressdownx", 500); - ui.cheat.classList.remove("disabled"); - } - } else { - if (game.changeCoin) { - game.changeCoin(-10); - } - this.backup = _status.event.dialog; - _status.event.dialog.close(); - _status.event.dialog = _status.event.parent.dialogxx; - this.dialog = _status.event.dialog; - this.dialog.open(); - game.uncheck(); - game.check(); - if (ui.cheat) { - ui.cheat.classList.add("disabled"); - } - } - }); - if (lib.onfree) { - ui.cheat2.classList.add("disabled"); - } - }; - ui.create.cheat = function () { - _status.createControl = ui.cheat2; - ui.cheat = ui.create.control("更换", function () { - if (ui.cheat2 && ui.cheat2.dialog == _status.event.dialog) { - return; - } - if (game.changeCoin) { - game.changeCoin(-3); - } - event.list = event.list.concat(list); - event.list.randomSort(); - // list=event.list.splice(0,parseInt(get.config('choice_num'))); - list = game.getCharacterChoice(event.list, parseInt(get.config("choice_num"))); - var buttons = ui.create.div(".buttons"); - var node = _status.event.dialog.buttons[0].parentNode; - _status.event.dialog.buttons = ui.create.buttons(list, "character", buttons); - _status.event.dialog.content.insertBefore(buttons, node); - buttons.addTempClass("start"); - node.remove(); - game.uncheck(); - game.check(); - }); - delete _status.createControl; - }; - if (!_status.brawl || !_status.brawl.chooseCharacterFixed) { - if (!ui.cheat && get.config("change_choice")) ui.create.cheat(); - if (!ui.cheat2 && get.config("free_choose")) ui.create.cheat2(); - } - } - "step 1"; - if (ui.cheat) { - ui.cheat.close(); - delete ui.cheat; - } - if (ui.cheat2) { - ui.cheat2.close(); - delete ui.cheat2; - } - if (result.buttons) { - var name1 = result.buttons[0].link, - name2 = result.buttons[1].link; - event.choosen = [name1, name2]; - if (get.is.double(name1, true)) { - if (!get.is.double(name2, true)) event._result = { control: lib.character[name2][1] }; - else if (get.is.double(name1, true).removeArray(get.is.double(name2, true)).length == 0 || get.is.double(name2, true).removeArray(get.is.double(name1, true)).length == 0) - game.me - .chooseControl(get.is.double(name2, true).filter(group => get.is.double(name1, true).includes(group))) - .set("prompt", "请选择你代表的势力") - .set("ai", () => _status.event.controls.randomGet()); - else - event._result = { - control: get.is.double(name1, true).find(group => get.is.double(name2, true).includes(group)), - }; - } else if (lib.character[name1][1] == "ye" && get.is.double(name2, true)) - game.me - .chooseControl(get.is.double(name2, true)) - .set("prompt", "请选择副将代表的势力") - .set("ai", () => _status.event.controls.randomGet()); - } - "step 2"; - if (result && result.control) game.me.trueIdentity = result.control; - if (event.choosen) { - game.me.init(event.choosen[0], event.choosen[1], false); - game.addRecentCharacter(event.choosen[0], event.choosen[1]); - } - event.list.remove(game.me.name1); - event.list.remove(game.me.name2); - for (var i = 0; i < game.players.length; i++) { - if (game.players[i] != game.me) { - event.ai(game.players[i], game.getCharacterChoice(event.list, parseInt(get.config("choice_num"))), event.list); - } - } - for (var i = 0; i < game.players.length; i++) { - game.players[i].classList.add("unseen"); - game.players[i].classList.add("unseen2"); - _status.characterlist.remove(game.players[i].name); - _status.characterlist.remove(game.players[i].name2); - if (game.players[i] != game.me) { - game.players[i].node.identity.firstChild.innerHTML = "猜"; - game.players[i].node.identity.dataset.color = "unknown"; - game.players[i].node.identity.classList.add("guessing"); - } - game.players[i].hiddenSkills = lib.character[game.players[i].name1][3].slice(0); - var hiddenSkills2 = lib.character[game.players[i].name2][3]; - for (var j = 0; j < hiddenSkills2.length; j++) { - game.players[i].hiddenSkills.add(hiddenSkills2[j]); - } - for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { - if (!lib.skill[game.players[i].hiddenSkills[j]]) { - game.players[i].hiddenSkills.splice(j--, 1); - } - } - game.players[i].group = "unknown"; - game.players[i].sex = "unknown"; - game.players[i].name1 = game.players[i].name; - game.players[i].name = "unknown"; - game.players[i].identity = "unknown"; - game.players[i].node.name.show(); - game.players[i].node.name2.show(); - for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { - game.players[i].addSkillTrigger(game.players[i].hiddenSkills[j], true); - } - } - setTimeout(function () { - ui.arena.classList.remove("choose-character"); - }, 500); - }); - }, - chooseCharacterOL() { - var next = game.createEvent("chooseCharacter"); - next.setContent(function () { - "step 0"; - game.broadcastAll(function () { - ui.arena.classList.add("choose-character"); - for (var i = 0; i < game.players.length; i++) { - game.players[i].classList.add("unseen"); - game.players[i].classList.add("unseen2"); - } - }); - var list = []; - for (var i in lib.characterPack.mode_guozhan) { - if (i.indexOf("gz_shibing") == 0) continue; - if (get.is.jun(i)) continue; - if (lib.config.guozhan_banned && lib.config.guozhan_banned.includes(i)) continue; - list.push(i); - } - _status.characterlist = list.slice(0); - _status.yeidentity = []; - event.list = list.slice(0); - var list2 = []; - var num; - if (lib.configOL.number * 6 > list.length) { - num = 5; - } else if (lib.configOL.number * 7 > list.length) { - num = 6; - } else { - num = 7; - } - var filterButton = function (button) { - if (ui.dialog) { - if (ui.dialog.buttons.length <= 10) { - for (var i = 0; i < ui.dialog.buttons.length; i++) { - if (ui.dialog.buttons[i] != button) { - if ( - lib.element.player.perfectPair.call( - { - name1: button.link, - name2: ui.dialog.buttons[i].link, - }, - true - ) - ) { - button.classList.add("glow2"); - } - } - } - } - } - var filterChoice = function (name1, name2) { - if (_status.separatism) return true; - var group1 = lib.character[name1][1]; - var group2 = lib.character[name2][1]; - var doublex = get.is.double(name1, true); - if (doublex) { - var double = get.is.double(name2, true); - if (double) return doublex.some(group => double.includes(group)); - return doublex.includes(group2); - } else { - if (group1 == "ye") return group2 != "ye"; - var double = get.is.double(name2, true); - if (double) return double.includes(group1); - return group1 == group2; - } - }; - if (!ui.selected.buttons.length) { - return ui.dialog.buttons.some(but => { - if (but == button) return false; - return filterChoice(button.link, but.link); - }); - } - return filterChoice(ui.selected.buttons[0].link, button.link); - }; - list.randomSort(); - for (var i = 0; i < game.players.length; i++) { - list2.push([ - game.players[i], - ["选择角色", [game.getCharacterChoice(list, num), "character"]], - 2, - true, - function () { - return Math.random(); - }, - filterButton, - ]); - } - game.me - .chooseButtonOL(list2, function (player, result) { - if (game.online || player == game.me) player.init(result.links[0], result.links[1], false); - }) - .set("switchToAuto", function () { - _status.event.result = "ai"; - }) - .set("processAI", function () { - var buttons = _status.event.dialog.buttons; - var filterChoice = function (name1, name2) { - if (_status.separatism) return true; - var group1 = lib.character[name1][1]; - var group2 = lib.character[name2][1]; - var doublex = get.is.double(name1, true); - if (doublex) { - var double = get.is.double(name2, true); - if (double) return doublex.some(group => double.includes(group)); - return doublex.includes(group2); - } else { - if (group1 == "ye") return group2 != "ye"; - var double = get.is.double(name2, true); - if (double) return double.includes(group1); - return group1 == group2; - } - }; - for (var i = 0; i < buttons.length - 1; i++) { - for (var j = i + 1; j < buttons.length; j++) { - if (filterChoice(buttons[i].link, buttons[j].link) || filterChoice(buttons[j].link, buttons[i].link)) { - var mainx = buttons[i].link; - var vicex = buttons[j].link; - if (!filterChoice(mainx, vicex) || (filterChoice(vicex, mainx) && get.guozhanReverse(mainx, vicex))) { - mainx = buttons[j].link; - vicex = buttons[i].link; - } - var list = [mainx, vicex]; - return { - bool: true, - links: list, - }; - } - } - } - }); - "step 1"; - var sort = true, - chosen = [], - chosenCharacter = []; - for (var i in result) { - if (result[i] && result[i].links) { - for (var j = 0; j < result[i].links.length; j++) { - event.list.remove(result[i].links[j]); - } - } - } - for (var i in result) { - if (result[i] == "ai" || !result[i].links || result[i].links.length < 1) { - if (sort) { - sort = false; - event.list.randomSort(); - } - result[i] = [event.list.shift()]; - var group = lib.character[result[i][0]][1]; - for (var j = 0; j < event.list.length; j++) { - if (lib.character[event.list[j]][1] == group) { - result[i].push(event.list[j]); - event.list.splice(j--, 1); - break; - } - } - } else { - result[i] = result[i].links; - } - var name1 = result[i][0], - name2 = result[i][1]; - if (get.is.double(name1, true)) { - if (!get.is.double(name2, true)) lib.playerOL[i].trueIdentity = lib.character[name2][1]; - else if (get.is.double(name1, true).removeArray(get.is.double(name2, true)).length == 0 || get.is.double(name2, true).removeArray(get.is.double(name1, true)).length == 0) { - chosen.push(lib.playerOL[i]); - chosenCharacter.push([name1, name2]); - } else lib.playerOL[i].trueIdentity = get.is.double(name1, true).find(group => get.is.double(name2, true).includes(group)); - } else if (lib.character[name1][1] == "ye" && get.is.double(name2, true)) { - chosen.push(lib.playerOL[i]); - chosenCharacter.push([name1, name2]); - } - } - event.result2 = result; - if (chosen.length) { - for (var i = 0; i < chosen.length; i++) { - var name1 = chosenCharacter[i][0], - name2 = chosenCharacter[i][1], - str, - choice; - if (get.is.double(name1, true)) { - str = "请选择你代表的势力"; - choice = get.is.double(name2, true).filter(group => get.is.double(name1, true).includes(group)); - } - if (lib.character[name1][1] == "ye") { - str = "请选择你的副将代表的势力"; - choice = get.is.double(name2, true); - } - chosen[i] = [ - chosen[i], - [ - str, - [ - choice.map(function (i) { - return ["", "", "group_" + i]; - }), - "vcard", - ], - ], - 1, - true, - ]; - } - game.me - .chooseButtonOL(chosen, function (player, result) { - if (player == game.me) player.trueIdentity = result.links[0][2].slice(6); - }) - .set("switchToAuto", function () { - _status.event.result = "ai"; - }) - .set("processAI", function () { - return { - bool: true, - links: [_status.event.dialog.buttons.randomGet().link], - }; - }); - } else event._result = {}; - "step 2"; - if (!result) result = {}; - var result2 = event.result2; - game.broadcastAll( - function (result, result2) { - for (var i = 0; i < game.players.length; i++) { - var current = game.players[i], - id = current.playerid; - if (result[id] && !current.name) { - current.init(result[id][0], result[id][1], false); - } - if (result2[id] && result2[id].length) { - current.trueIdentity = result2[id][0][2].slice(6); - } - if (game.players[i] != game.me) { - game.players[i].node.identity.firstChild.innerHTML = "猜"; - game.players[i].node.identity.dataset.color = "unknown"; - game.players[i].node.identity.classList.add("guessing"); - } - game.players[i].hiddenSkills = lib.character[game.players[i].name1][3].slice(0); - var hiddenSkills2 = lib.character[game.players[i].name2][3]; - for (var j = 0; j < hiddenSkills2.length; j++) { - game.players[i].hiddenSkills.add(hiddenSkills2[j]); - } - for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { - if (!lib.skill[game.players[i].hiddenSkills[j]]) { - game.players[i].hiddenSkills.splice(j--, 1); - } - } - game.players[i].group = "unknown"; - game.players[i].sex = "unknown"; - game.players[i].name1 = game.players[i].name; - game.players[i].name = "unknown"; - game.players[i].identity = "unknown"; - game.players[i].node.name.show(); - game.players[i].node.name2.show(); - for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { - game.players[i].addSkillTrigger(game.players[i].hiddenSkills[j], true); - } - } - setTimeout(function () { - ui.arena.classList.remove("choose-character"); - }, 500); - }, - result2, - result - ); - }); - }, - }, + game: gamePatch, ui: { click: { // identity:function(){ diff --git a/mode/guozhan/src/patch/content.js b/mode/guozhan/src/patch/content.js new file mode 100644 index 0000000000..6d8641cbbb --- /dev/null +++ b/mode/guozhan/src/patch/content.js @@ -0,0 +1,193 @@ +import { lib, game as _game, ui, get, ai, _status } from "../../../../noname.js"; +import { GameGuozhan, broadcastAll } from "./game.js"; + +/** @type {GameGuozhan} */ +// @ts-expect-error 类型就是这么定的 +const game = _game; + +/** + * + * @param {GameEvent} event + * @param {GameEvent} _trigger + * @param {Player} player + */ +export async function showYexingsContent(event, _trigger, player) { + /** @type {Player[]} */ + const yexingPlayers = game + .filterPlayer(current => lib.character[current.name1][1] == "ye" && current.identity == "ye") + // @ts-expect-error 祖宗之法就是这么写的 + .sortBySeat(_status.currentPhase); + + /** @type {Player[]} */ + let showYexingPlayers = []; + for (const target of yexingPlayers) { + const next = target.chooseBool("是否【暴露野心】,展示主将并继续战斗?", "若选择“否”,则视为本局游戏失败"); + + next.set("ai", showCheck); + + if (await next.forResultBool()) { + showYexingPlayers.push(target); + target.$fullscreenpop("暴露野心", "thunder"); + game.log(target, "暴露了野心"); + await target.showCharacter(0); + await game.delay(2); + } + + /** + * 是否暴露野心的AI + * + * @param {GameEvent} _event + * @param {Player} _player + */ + function showCheck(_event, _player) { + // TODO: 未来再想AI该怎么写 + return Math.random() < 0.5; + } + } + + // 如果没有人暴露野心,那么游戏结束 + if (showYexingPlayers.length === 0) { + const winner = game.findPlayer(current => lib.character[current.name1][1] != "ye"); + + if (winner) { + broadcastAll(id => { + // @ts-expect-error 祖宗之法就是这么写的 + game.winner_id = id; + }, winner.playerid); + game.checkResult(); + } + + // @ts-expect-error 祖宗之法就是这么写的 + delete _status.showYexings; + return; + } + + let yexingGroupList = ["夏", "商", "周", "秦", "汉", "隋", "唐", "宋", "辽", "金", "元", "明"]; + for (const target of showYexingPlayers) { + // 基本不可能发生 + if (yexingGroupList.length === 0) { + yexingGroupList = ["夏", "商", "周", "秦", "汉", "隋", "唐", "宋", "辽", "金", "元", "明"]; + } + + const next = target.chooseControl(yexingGroupList); + + next.set("prompt", "请选择自己所属的野心家势力的标识"); + next.set("ai", () => (yexingGroupList ? yexingGroupList.randomGet() : 0)); + + /** @type {string} */ + let text; + + const control = await next.forResultControl(); + if (control) { + text = control; + yexingGroupList.remove(control); + } else { + text = yexingGroupList.randomRemove() ?? "野"; + } + + lib.group.push(text); + lib.translate[`${text}2`] = text; + lib.groupnature[text] = "kami"; + + broadcastAll( + /** + * @param {Player} player + * @param {string} text + */ + (player, text) => { + player.identity = text; + player.setIdentity(text, "kami"); + }, + target, + text + ); + + target.changeGroup(text); + target.removeMark("yexinjia_mark", 1); + + /** @type {Player[]} */ + const maybeFriends = game.players.filter(current => current.identity != "ye" && current !== target && !get.is.jun(current) && !yexingPlayers.includes(current) && !current.getStorage("yexinjia_friend").length); + if (maybeFriends.length === 0) { + continue; + } + + /** @type {Player[]} */ + const refused = []; + for (const other of maybeFriends) { + target.line(other, "green"); + + const next = other.chooseBool(`是否响应${get.translation(target)}发起的【拉拢人心】?`, `将势力改为${text}`); + + next.set("source", target); + next.set("ai", check); + + if (await next.forResultBool()) { + other.chat("加入"); + //event.targets4.push(target); + broadcastAll( + /** + * @param {Player} player + * @param {string} text + */ + (player, text) => { + player.identity = text; + player.setIdentity(text, "kami"); + }, + other, + text + ); + other.changeGroup(text); + } else { + other.chat("拒绝"); + refused.push(other); + } + + /** + * @param {GameEvent} _event + * @param {Player} _player + * @returns {boolean} + */ + function check(_event, _player) { + const player = get.player(); + const source = get.event("source"); + const friendsCount = target.getFriends(true, false).length; + + if (game.players.length <= 2 * friendsCount) { + return false; + } + // @ts-expect-error 祖宗之法就是这么写的 + if (source.getFriends(true).length + friendsCount > game.players.length / 2) { + return true; + } + + if (player.isDamaged() || player.countCards("h") < 4) { + return false; + } + + return true; + } + } + + for (const other of refused) { + await other.drawTo(4, []); + await other.recover(); + } + } + + // @ts-expect-error 祖宗之法就是这么写的 + delete _status.showYexings; + + // 如果此时因为机缘巧合,所有玩家均属于一个阵营,则直接获胜 + for (const target of showYexingPlayers) { + if (game.hasPlayer(current => !current.isFriendOf(target))) { + continue; + } + + broadcastAll(id => { + // @ts-expect-error 祖宗之法就是这么写的 + game.winner_id = id; + }, target.playerid); + game.checkResult(); + break; + } +} diff --git a/mode/guozhan/src/patch/game.js b/mode/guozhan/src/patch/game.js index 71eb8a095e..56448fe0d1 100644 --- a/mode/guozhan/src/patch/game.js +++ b/mode/guozhan/src/patch/game.js @@ -1,6 +1,7 @@ import { lib, game, ui, get, ai, _status } from "../../../../noname.js"; import { GameEvent, Dialog, Player } from "../../../../noname/library/element/index.js"; import { Game } from "../../../../noname/game/index.js"; +import { showYexingsContent } from "./content.js"; export class GameGuozhan extends Game { /** @@ -219,9 +220,9 @@ export class GameGuozhan extends Game { // 过滤神和外服势力,以及没有战绩的势力 group = group.filter(group => group !== "shen" && group !== "western" && data[group]); // 将战绩记录转换为字符串 - const strs = group.map(group => { - const name = get.translation(`${group[i]}2`); - const [win, lose] = data[group]; + const strs = group.map(id => { + const name = get.translation(`${group[id]}2`); + const [win, lose] = data[id]; return `${name}: ${win}胜 ${lose}负`; }); @@ -307,9 +308,15 @@ export class GameGuozhan extends Game { } } } - + + /** + * 获取当前对局对应录像的名称 + * + * @returns {[name: string, situation: string]} + */ getVideoName() { var str = get.translation(game.me.name1) + "/" + get.translation(game.me.name2); + // @ts-expect-error 祖宗之法就是这么写的 var str2 = _status.separatism ? get.modetrans({ mode: lib.config.mode, @@ -319,15 +326,24 @@ export class GameGuozhan extends Game { if (game.me.identity == "ye") { str2 += " - 野心家"; } - var name = [str, str2]; - return name; + return [str, str2]; } + + /** + * 显示所有玩家的身份 + * + * @param {boolean} started + */ showIdentity(started) { if (game.phaseNumber == 0 && !started) return; for (var i = 0; i < game.players.length; i++) { game.players[i].showCharacter(2, false); } } + + /** + * > ? + */ tryResult() { var map = {}, sides = [], @@ -403,6 +419,10 @@ export class GameGuozhan extends Game { } } } + + /** + * 检查游戏结果 + */ checkResult() { _status.overing = true; var me = game.me._trueMe || game.me; @@ -413,10 +433,18 @@ export class GameGuozhan extends Game { game.over(winner && winner.isFriendOf(me) ? true : false); game.showIdentity(); } + + /** + * > ? + * @param {Player} player + * @returns {boolean} + */ checkOnlineResult(player) { + // @ts-expect-error 祖宗之法就是这么写的 var winner = lib.playerOL[game.winner_id]; return winner && winner.isFriendOf(game.me); } + chooseCharacter() { var next = game.createEvent("chooseCharacter"); next.showConfig = true; @@ -785,6 +813,7 @@ export class GameGuozhan extends Game { ui.arena.classList.remove("choose-character"); }, 500); }); + return next; } chooseCharacterOL() { var next = game.createEvent("chooseCharacter"); @@ -1050,196 +1079,7 @@ export class GameGuozhan extends Game { result ); }); - } -} - -/** - * - * @param {GameEvent} event - * @param {GameEvent} _trigger - * @param {Player} player - */ -export async function showYexingsContent(event, _trigger, player) { - /** @type {Player[]} */ - // @ts-expect-error 类型就是这样的 - const yexingPlayers = game - .filterPlayer(current => lib.character[current.name1][1] == "ye") - // @ts-expect-error 祖宗之法就是这么写的 - .sortBySeat(_status.currentPhase); - - /** @type {Player[]} */ - let showYexingPlayers = []; - for (const target of yexingPlayers) { - const next = target.chooseBool("是否【暴露野心】,展示主将并继续战斗?", "若选择“否”,则视为本局游戏失败"); - - next.set("ai", showCheck); - - if (await next.forResultBool()) { - showYexingPlayers.push(target); - target.$fullscreenpop("暴露野心", "thunder"); - game.log(target, "暴露了野心"); - await target.showCharacter(0); - await game.delay(2); - } - - /** - * 是否暴露野心的AI - * - * @param {GameEvent} _event - * @param {Player} _player - */ - function showCheck(_event, _player) { - // TODO: 未来再想AI该怎么写 - return Math.random() < 0.5; - } - } - - // 如果没有人暴露野心,那么游戏结束 - if (showYexingPlayers.length === 0) { - const winner = game.findPlayer(current => lib.character[current.name1][1] != "ye"); - - if (winner) { - broadcastAll(id => { - // @ts-expect-error 祖宗之法就是这么写的 - game.winner_id = id; - }, winner.playerid); - // @ts-expect-error 祖宗之法就是这么写的 - game.checkResult(); - } - - // @ts-expect-error 祖宗之法就是这么写的 - delete _status.showYexings; - return; - } - - let yexingGroupList = ["夏", "商", "周", "秦", "汉", "隋", "唐", "宋", "辽", "金", "元", "明"]; - for (const target of showYexingPlayers) { - // 基本不可能发生 - if (yexingGroupList.length === 0) { - yexingGroupList = ["夏", "商", "周", "秦", "汉", "隋", "唐", "宋", "辽", "金", "元", "明"]; - } - - const next = target.chooseControl(yexingGroupList); - - next.set("prompt", "请选择自己所属的野心家势力的标识"); - next.set("ai", () => (yexingGroupList ? yexingGroupList.randomGet() : 0)); - - /** @type {string} */ - let text; - - const control = await next.forResultControl(); - if (control) { - text = control; - yexingGroupList.remove(control); - } else { - text = yexingGroupList.randomRemove() ?? "野"; - } - - lib.group.push(text); - lib.translate[`${text}2`] = text; - lib.groupnature[text] = "kami"; - - broadcastAll( - /** - * @param {Player} player - * @param {string} text - */ - (player, text) => { - player.identity = text; - player.setIdentity(text, "kami"); - }, - target, - text - ); - - target.changeGroup(text); - target.removeMark("yexinjia_mark", 1); - - /** @type {Player[]} */ - // @ts-expect-error 祖宗之法就是这么写的 - const maybeFriends = game.players.filter(current => current.identity != "ye" && current !== target && !get.is.jun(current) && !yexingPlayers.includes(current) && !current.getStorage("yexinjia_friend").length); - if (maybeFriends.length === 0) { - continue; - } - - /** @type {Player[]} */ - const refused = []; - for (const other of maybeFriends) { - target.line(other, "green"); - - const next = other.chooseBool(`是否响应${get.translation(target)}发起的【拉拢人心】?`, `将势力改为${text}`); - - next.set("source", target); - next.set("ai", check); - - if (await next.forResultBool()) { - other.chat("加入"); - //event.targets4.push(target); - broadcastAll( - /** - * @param {Player} player - * @param {string} text - */ - (player, text) => { - player.identity = text; - player.setIdentity(text, "kami"); - }, - other, - text - ); - other.changeGroup(text); - } else { - other.chat("拒绝"); - refused.push(other); - } - - /** - * @param {GameEvent} _event - * @param {Player} _player - * @returns {boolean} - */ - function check(_event, _player) { - const player = get.player(); - const source = get.event("source"); - const friendsCount = target.getFriends(true).length; - - if (game.players.length <= 2 * friendsCount) { - return false; - } - // @ts-expect-error 祖宗之法就是这么写的 - if (source.getFriends(true).length + friendsCount > game.players.length / 2) { - return true; - } - - if (player.isDamaged() || player.countCards("h") < 4) { - return false; - } - - return true; - } - } - - for (const other of refused) { - await other.drawTo(4, []); - await other.recover(); - } - } - - // @ts-expect-error 祖宗之法就是这么写的 - delete _status.showYexings; - if ( - !game.hasPlayer(current => { - return game.hasPlayer(target => { - return !target.isFriendOf(current); - }); - }) - ) { - broadcastAll(id => { - // @ts-expect-error 祖宗之法就是这么写的 - game.winner_id = id; - }, event.source.playerid); - // @ts-expect-error 祖宗之法就是这么写的 - game.checkResult(); + return next; } } diff --git a/mode/guozhan/src/patch/index.js b/mode/guozhan/src/patch/index.js new file mode 100644 index 0000000000..a3d136e663 --- /dev/null +++ b/mode/guozhan/src/patch/index.js @@ -0,0 +1,28 @@ +import { GameGuozhan } from "./game.js"; + +export const gamePatch = _generateExtraFuncions(GameGuozhan.prototype); + +/** + * 一个非常申必的生成额外函数的函数 + * + * @param {any} prototype + * @returns {object} + */ +function _generateExtraFuncions(prototype) { + const result = {}; + const names = Object.getOwnPropertyNames(prototype); + + if (names[0] === "constructor") { + names.shift(); + } else if (names[names.length - 1] === "constructor") { + names.pop(); + } else { + names.remove("constructor"); + } + + for (const name of names) { + result[name] = prototype[name]; + } + + return result; +} From 9a8c6bc49f03de7f895c8bea0128d6787e2b9002 Mon Sep 17 00:00:00 2001 From: Rintim Date: Mon, 10 Mar 2025 21:16:21 +0800 Subject: [PATCH 11/48] =?UTF-8?q?fix:=20=E6=9A=B4=E9=9C=B2=E9=87=8E?= =?UTF-8?q?=E5=BF=83=E7=9A=84=E4=B8=80=E4=BA=9B=E7=BB=86=E8=8A=82=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mode/guozhan/src/patch/content.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/mode/guozhan/src/patch/content.js b/mode/guozhan/src/patch/content.js index 6d8641cbbb..8126ae33da 100644 --- a/mode/guozhan/src/patch/content.js +++ b/mode/guozhan/src/patch/content.js @@ -14,7 +14,8 @@ const game = _game; export async function showYexingsContent(event, _trigger, player) { /** @type {Player[]} */ const yexingPlayers = game - .filterPlayer(current => lib.character[current.name1][1] == "ye" && current.identity == "ye") + // @ts-expect-error 祖宗之法就是这么做的 + .filterPlayer(current => lib.character[current.name1][1] == "ye" && !current._showYexing) // @ts-expect-error 祖宗之法就是这么写的 .sortBySeat(_status.currentPhase); @@ -31,6 +32,17 @@ export async function showYexingsContent(event, _trigger, player) { game.log(target, "暴露了野心"); await target.showCharacter(0); await game.delay(2); + + broadcastAll( + /** + * @param {Player} player + */ + player => { + // @ts-expect-error 祖宗之法就是这么做的 + player._showYexing = true + }, + player + ); } /** From 94782e306a2d294a91f3feedf6f237967d6a3081 Mon Sep 17 00:00:00 2001 From: Rintim Date: Tue, 11 Mar 2025 23:10:29 +0800 Subject: [PATCH 12/48] fix: update type info && straighten the type of `Player` for `GameEvent` when functions of `Player` use properties of `GameEvent`. --- .../noname/get/pinyins/index.d.ts | 2 +- .../noname/library/cache/cacheContext.d.ts | 2 +- .../element/GameEvent/GameEventManager.d.ts | 6 +-- .../noname/library/element/gameEvent.d.ts | 47 ++++++++++--------- .../nonameModules/noname/library/update.d.ts | 34 +++++++------- .../nonameModules/noname/util/config.d.ts | 2 +- .../nonameModules/noname/util/error.d.ts | 6 +-- noname/library/element/gameEvent.js | 1 + 8 files changed, 51 insertions(+), 49 deletions(-) diff --git a/node_modules/@types/noname-typings/nonameModules/noname/get/pinyins/index.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/get/pinyins/index.d.ts index f4f21defe9..efabf5349a 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/get/pinyins/index.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/get/pinyins/index.d.ts @@ -14,7 +14,7 @@ export function convert(pinyin: string | string[], options: any): string | strin */ export function customPinyin(config: { [key: string]: string; -} | undefined, options: any): void; +}, options: any): void; /** * @description: 获取带拼音汉字的 html 字符串 * @param {string} text 要转换的字符串 diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/cache/cacheContext.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/cache/cacheContext.d.ts index 1e90c9af0d..d7163e86bc 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/cache/cacheContext.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/cache/cacheContext.d.ts @@ -33,7 +33,7 @@ export class CacheContext { * @param {Array} methods * @returns */ - static inject(source: any, methods: Array): null | undefined; + static inject(source: any, methods: Array): any; static _getCacheValueFromObject(storage: any, key: any, params: any, source: any, func: any): any; static _ensureMember(obj: any, key: any): any; static _wrapParametersToCacheKey(params: any): string; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/GameEventManager.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/GameEventManager.d.ts index 143776fee5..7c203da255 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/GameEventManager.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/GameEvent/GameEventManager.d.ts @@ -4,8 +4,8 @@ export default class GameEventManager { eventStack: GameEvent[]; rootEvent?: GameEvent; tempEvent?: GameEvent; - get event(): GameEvent | undefined; - getStartedEvent(): GameEvent | undefined; - getStatusEvent(): GameEvent | undefined; + get event(): GameEvent; + getStartedEvent(): GameEvent; + getStatusEvent(): GameEvent; setStatusEvent(event: GameEvent): void; } diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEvent.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEvent.d.ts index 6f78971510..0ef774a280 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEvent.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEvent.d.ts @@ -8,7 +8,7 @@ export class GameEvent implements PromiseLike> { * @param { boolean } [trigger] * @param { GameEventManager } [manager] */ - constructor(name?: string | GameEvent | undefined, trigger?: boolean | undefined, manager?: GameEventManager | undefined); + constructor(name?: string | GameEvent, trigger?: boolean, manager?: GameEventManager); /** * @type { string } */ @@ -196,23 +196,23 @@ export class GameEvent implements PromiseLike> { * @param {number} [value] * @param {number} [baseValue] */ - addNumber(key: keyof this, value?: number | undefined, baseValue?: number | undefined): this; + addNumber(key: keyof this, value?: number, baseValue?: number): this; /** * @param {keyof this} key * @param {number} [baseValue] */ - decrease(key: keyof this, baseValue?: number | undefined): this; + decrease(key: keyof this, baseValue?: number): this; /** * @param {keyof this} key * @param {number} [baseValue] */ - increase(key: keyof this, baseValue?: number | undefined): this; + increase(key: keyof this, baseValue?: number): this; /** * @param {keyof this} key * @param {number} [value] * @param {number} [baseValue] */ - subtractNumber(key: keyof this, value?: number | undefined, baseValue?: number | undefined): this; + subtractNumber(key: keyof this, value?: number, baseValue?: number): this; /** * @param {Parameters[0]} type * @param {GameEvent} event @@ -238,7 +238,7 @@ export class GameEvent implements PromiseLike> { /** * @param {`on${Capitalize}`} [type] */ - hasHandler(type?: `on${Capitalize}` | undefined): boolean; + hasHandler(type?: `on${Capitalize}`): boolean; /** * @overload * @param {...((event: GameEvent, option: { @@ -261,22 +261,22 @@ export class GameEvent implements PromiseLike> { state?: "begin" | "end"; }) => void)[][]): number; putStepCache(key: any, value: any): this; - _stepCache: {} | undefined; + _stepCache: {}; getStepCache(key: any): any; clearStepCache(key: any): this; callFuncUseStepCache(prefix: any, func: any, params: any): any; putTempCache(key1: any, key2: any, value: any): any; - _tempCache: {} | undefined; + _tempCache: {}; getTempCache(key1: any, key2: any): any; changeToZero(): this; - numFixed: boolean | undefined; + numFixed: boolean; finish(): void; /** * @type { boolean } */ finished: boolean; - cancel(all: any, player: any, notrigger: any): GameEvent | undefined; - neutralize(event?: any): Promise | undefined>; + cancel(all: any, player: any, notrigger: any): GameEvent; + neutralize(event?: any): Promise>; /** * @type { boolean } */ @@ -309,11 +309,11 @@ export class GameEvent implements PromiseLike> { * @param {boolean} [includeSelf] 若level不是数字,指定搜索时是否包含事件本身 * @returns {GameEvent|{}|null} */ - getParent(level?: string | number | ((evt: GameEvent) => boolean) | undefined, forced?: boolean | undefined, includeSelf?: boolean | undefined): GameEvent | {} | null; + getParent(level?: number | string | ((evt: GameEvent) => boolean), forced?: boolean, includeSelf?: boolean): GameEvent | {} | null; getTrigger(): any; getRand(name: any): any; - _rand_map: {} | undefined; - _rand: number | undefined; + _rand_map: {}; + _rand: number; insert(content: any, map: any): GameEvent; insertAfter(content: any, map: any): GameEvent; backup(skill: any): this; @@ -322,7 +322,7 @@ export class GameEvent implements PromiseLike> { selectButton: any; filterTarget: any; selectTarget: any; - ignoreMod: boolean | undefined; + ignoreMod: boolean; filterCard2: any; filterCard: any; filterOk: any; @@ -339,8 +339,8 @@ export class GameEvent implements PromiseLike> { _cardChoice: any; _targetChoice: any; _skillChoice: any; - isMine(): any; - isOnline(): any; + isMine(): boolean; + isOnline(): boolean; notLink(): boolean; isPhaseUsing(player: any): boolean; addTrigger(skills: any, player: any): this; @@ -351,7 +351,7 @@ export class GameEvent implements PromiseLike> { * @returns { GameEvent } */ trigger(name: string): GameEvent; - untrigger(all: boolean | undefined, player: any): this; + untrigger(all: boolean, player: any): this; /** * @deprecated */ @@ -389,21 +389,21 @@ export class GameEvent implements PromiseLike> { * @param { ((reason: any) => TResult2 | Promise) | null } [onrejected] The callback to execute when the Promise is rejected. * @returns { Promise } A Promise for the completion of which ever callback is executed. */ - then(onfulfilled?: ((event: Omit) => TResult1 | Promise) | null | undefined, onrejected?: ((reason: any) => TResult2 | Promise) | null | undefined): Promise; + then(onfulfilled?: ((event: Omit) => TResult1 | Promise) | null, onrejected?: ((reason: any) => TResult2 | Promise) | null): Promise; /** * @template TResult * Attaches a callback for only the rejection of the Promise. * @param onrejected The callback to execute when the Promise is rejected.* @param { ((reason: any) => TResult | Promise) | null } [onrejected] The callback to execute when the Promise is rejected. * @returns { Promise | TResult> } A Promise for the completion of which ever callback is executed. */ - catch(onrejected?: ((reason: any) => TResult | Promise) | null | undefined): Promise | TResult>; + catch(onrejected?: ((reason: any) => TResult | Promise) | null): Promise | TResult>; /** * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The * resolved value cannot be modified from the callback. * @param { (() => void) | null } [onfinally] The callback to execute when the Promise is settled (fulfilled or rejected). * @returns { Promise> } A Promise for the completion of the callback. */ - finally(onfinally?: (() => void) | null | undefined): Promise>; + finally(onfinally?: (() => void) | null): Promise>; resolve(): void; start(): Promise; loop(): Promise; @@ -515,11 +515,11 @@ export class GameEvent implements PromiseLike> { /** * 返回result中的targets项。 */ - forResultTargets(): Promise; + forResultTargets(): Promise; /** * 返回result中的cards项 */ - forResultCards(): Promise; + forResultCards(): Promise; /** * 返回result中的card项 * @@ -555,4 +555,5 @@ export class GameEvent implements PromiseLike> { } import GameEventManager from "./GameEvent/GameEventManager.js"; import ContentCompiler from "./GameEvent/compilers/ContentCompiler.js"; +import { Player } from "./index.js"; export { GameEventManager, ContentCompiler }; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/update.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/update.d.ts index 14ed9ad9a7..926325abd3 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/update.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/update.d.ts @@ -35,9 +35,9 @@ export function checkVersion(ver1: string, ver2: string): -1 | 0 | 1; * ``` */ export function getRepoTags(options?: { - username?: string | undefined; - repository?: string | undefined; - accessToken?: string | undefined; + username?: string; + repository?: string; + accessToken?: string; }): Promise<{ commit: { sha: string; @@ -63,9 +63,9 @@ export function getRepoTags(options?: { * ``` */ export function getRepoTagDescription(tagName: string, options?: { - username?: string | undefined; - repository?: string | undefined; - accessToken?: string | undefined; + username?: string; + repository?: string; + accessToken?: string; }): Promise<{ /** @type { { browser_download_url: string, content_type: string, name: string, size: number }[] } tag额外上传的素材包 */ assets: { @@ -110,10 +110,10 @@ export function getRepoTagDescription(tagName: string, options?: { * .catch(error => console.error('Failed to fetch files:', error)); * ``` */ -export function getRepoFilesList(path?: string | undefined, branch?: string | undefined, options?: { - username?: string | undefined; - repository?: string | undefined; - accessToken?: string | undefined; +export function getRepoFilesList(path?: string, branch?: string, options?: { + username?: string; + repository?: string; + accessToken?: string; }): Promise<({ download_url: string; name: string; @@ -149,10 +149,10 @@ export function getRepoFilesList(path?: string | undefined, branch?: string | un * .catch(error => console.error('Failed to fetch files:', error)); * ``` */ -export function flattenRepositoryFiles(path?: string | undefined, branch?: string | undefined, options?: { - username?: string | undefined; - repository?: string | undefined; - accessToken?: string | undefined; +export function flattenRepositoryFiles(path?: string, branch?: string, options?: { + username?: string; + repository?: string; + accessToken?: string; }): Promise<{ download_url: string; name: string; @@ -171,7 +171,7 @@ export function flattenRepositoryFiles(path?: string | undefined, branch?: strin * await getRepoTagDescription('v1.10.10').then(({ zipball_url }) => request(zipball_url)); * ``` */ -export function request(url: string, onProgress?: ((receivedBytes: number, total?: number, filename?: string) => void) | undefined, options?: RequestInit | undefined): Promise; +export function request(url: string, onProgress?: (receivedBytes: number, total?: number, filename?: string) => void, options?: RequestInit): Promise; /** * * @param { string } [title] @@ -180,7 +180,7 @@ export function request(url: string, onProgress?: ((receivedBytes: number, total * @param { string | number } [value] * @returns { progress } */ -export function createProgress(title?: string | undefined, max?: string | number | undefined, fileName?: string | undefined, value?: string | number | undefined): progress; +export function createProgress(title?: string, max?: string | number, fileName?: string, value?: string | number): progress; /** * 从GitHub存储库检索最新版本(tag),不包括特定tag。 * @@ -207,7 +207,7 @@ export function getLatestVersionFromGitHub(owner?: string, repo?: string): Promi * }[][]>} A promise that resolves with trees from the specified directories. * @throws {Error} Will throw an error if unable to fetch the repository tree from GitHub. */ -export function getTreesFromGithub(directories: string[], version: string, owner?: string | undefined, repo?: string | undefined): Promise<{ +export function getTreesFromGithub(directories: string[], version: string, owner?: string, repo?: string): Promise<{ path: string; mode: string; type: "blob" | "tree"; diff --git a/node_modules/@types/noname-typings/nonameModules/noname/util/config.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/util/config.d.ts index d14b5dc3aa..39ad62a931 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/util/config.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/util/config.d.ts @@ -26,7 +26,7 @@ export function has(name: string): boolean; * @param {any} [reinitIndexedDB=undefined] - 是否在用`indexedDB`读取失败时将对应键的值初始化;若给定值,则初始化为给定的值 * @return {Promise} */ -export function load(name: string, type: string, reinitLocalStorage?: boolean | undefined, reinitIndexedDB?: any): Promise; +export function load(name: string, type: string, reinitLocalStorage?: boolean, reinitIndexedDB?: any): Promise; /** * 向数据库中保存数据,根据目前可用情况自动选择相应地数据库 * diff --git a/node_modules/@types/noname-typings/nonameModules/noname/util/error.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/util/error.d.ts index a18860dc27..2173fa23a9 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/util/error.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/util/error.d.ts @@ -8,7 +8,7 @@ export class CodeSnippet { * * @type {CodeSnippet?} */ - static get currentSnippet(): CodeSnippet | null; + static get currentSnippet(): CodeSnippet; /** * ```plain * 压入一个代码片段作为当前代码片段 @@ -51,7 +51,7 @@ export class CodeSnippet { #private; } export class ErrorReporter { - static "__#4@#topAlert": ((message?: any) => void) & typeof alert; + static "__#4@#topAlert": any; static "__#4@#errorLineNoPatterns": RegExp[]; static "__#4@#findLineNo": (line: any) => number; /** @@ -75,7 +75,7 @@ export class ErrorReporter { constructor(error: Error, snippet?: CodeSnippet | null); get message(): string; get stack(): string; - viewCode(): string | null; + viewCode(): string; /** * ```plain * 向用户报告错误信息 diff --git a/noname/library/element/gameEvent.js b/noname/library/element/gameEvent.js index 1d358f8a22..811edbb8c4 100644 --- a/noname/library/element/gameEvent.js +++ b/noname/library/element/gameEvent.js @@ -1,4 +1,5 @@ import { _status, game, get, lib, ui } from "../../../noname.js"; +import { Player } from "./index.js"; import security from "../../util/security.js"; import ContentCompiler from "./GameEvent/compilers/ContentCompiler.js"; import GameEventManager from "./GameEvent/GameEventManager.js"; From a69078491aa937fe464d5df7381a00710648d76d Mon Sep 17 00:00:00 2001 From: Rintim Date: Wed, 12 Mar 2025 16:33:47 +0800 Subject: [PATCH 13/48] pref: remove continue for guozhan mode due to pending the new api. --- noname/library/index.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/noname/library/index.js b/noname/library/index.js index 122cccd6bf..7e4813714e 100644 --- a/noname/library/index.js +++ b/noname/library/index.js @@ -6090,22 +6090,22 @@ export class Library { unlimited: "无限", }, }, - continue_game: { - name: "显示再战", - init: true, - intro: "游戏结束后可选择用相同的武将再进行一局游戏", - onclick(bool) { - game.saveConfig("continue_game", bool, this._link.config.mode); - if (get.config("continue_game") && get.mode() == "guozhan") { - if (!ui.continue_game && _status.over && !_status.brawl && !game.no_continue_game) { - ui.continue_game = ui.create.control("再战", game.reloadCurrent); - } - } else if (ui.continue_game) { - ui.continue_game.close(); - delete ui.continue_game; - } - }, - }, + // continue_game: { + // name: "显示再战", + // init: true, + // intro: "游戏结束后可选择用相同的武将再进行一局游戏", + // onclick(bool) { + // game.saveConfig("continue_game", bool, this._link.config.mode); + // if (get.config("continue_game") && get.mode() == "guozhan") { + // if (!ui.continue_game && _status.over && !_status.brawl && !game.no_continue_game) { + // ui.continue_game = ui.create.control("再战", game.reloadCurrent); + // } + // } else if (ui.continue_game) { + // ui.continue_game.close(); + // delete ui.continue_game; + // } + // }, + // }, dierestart: { name: "死亡后显示重来", init: true, From d9219d1da2504f95bda78f288684877e06168e5b Mon Sep 17 00:00:00 2001 From: Rintim Date: Wed, 12 Mar 2025 23:27:35 +0800 Subject: [PATCH 14/48] revert: undo deleting continue. --- noname/library/index.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/noname/library/index.js b/noname/library/index.js index 7e4813714e..122cccd6bf 100644 --- a/noname/library/index.js +++ b/noname/library/index.js @@ -6090,22 +6090,22 @@ export class Library { unlimited: "无限", }, }, - // continue_game: { - // name: "显示再战", - // init: true, - // intro: "游戏结束后可选择用相同的武将再进行一局游戏", - // onclick(bool) { - // game.saveConfig("continue_game", bool, this._link.config.mode); - // if (get.config("continue_game") && get.mode() == "guozhan") { - // if (!ui.continue_game && _status.over && !_status.brawl && !game.no_continue_game) { - // ui.continue_game = ui.create.control("再战", game.reloadCurrent); - // } - // } else if (ui.continue_game) { - // ui.continue_game.close(); - // delete ui.continue_game; - // } - // }, - // }, + continue_game: { + name: "显示再战", + init: true, + intro: "游戏结束后可选择用相同的武将再进行一局游戏", + onclick(bool) { + game.saveConfig("continue_game", bool, this._link.config.mode); + if (get.config("continue_game") && get.mode() == "guozhan") { + if (!ui.continue_game && _status.over && !_status.brawl && !game.no_continue_game) { + ui.continue_game = ui.create.control("再战", game.reloadCurrent); + } + } else if (ui.continue_game) { + ui.continue_game.close(); + delete ui.continue_game; + } + }, + }, dierestart: { name: "死亡后显示重来", init: true, From 2f2befdf771b3215b7a9586978884d581810846e Mon Sep 17 00:00:00 2001 From: Rintim Date: Thu, 13 Mar 2025 16:58:01 +0800 Subject: [PATCH 15/48] pref: reformat the structure of experimental content. --- noname/get/index.js | 2 +- noname/library/experimental/index.js | 28 +++++++++++++++++++++++---- noname/library/experimental/symbol.js | 6 +----- noname/library/index.js | 26 +++++++++++++++++++++++-- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/noname/get/index.js b/noname/get/index.js index 1f5dc2a5a2..1206d4f8f1 100644 --- a/noname/get/index.js +++ b/noname/get/index.js @@ -2369,7 +2369,7 @@ export class Get extends GetCompatible { if (typeof obj !== "object" || obj === null) return; - if (lib.experimental.symbol.itemType in obj) return obj[lib.experimental.symbol.itemType]; + if (lib.experimental.symbols.ItemType in obj) return obj[lib.experimental.symbols.ItemType]; } equipNum(card) { const subtypes = get.subtypes(card); diff --git a/noname/library/experimental/index.js b/noname/library/experimental/index.js index c8cea9d750..e2aa8d684c 100644 --- a/noname/library/experimental/index.js +++ b/noname/library/experimental/index.js @@ -1,8 +1,28 @@ +import { lib } from "../index.js"; import { Uninstantable } from "../../util/index.js"; -import { ExperimentalSymbol } from "./symbol.js"; +import * as ExperimentalSymbol from "./symbol.js"; -export class Experimental extends Uninstantable { - static symbol = ExperimentalSymbol; - static symbols = ExperimentalSymbol; +export class Experimental { + symbol = ExperimentalSymbol; + symbols = ExperimentalSymbol; + + /** + * @type {boolean} + */ + get enable() { + return Reflect.get(lib.config, "experimental_enable"); + } } + +export let experimental = new Experimental(); + +/** + * @param {Experimental} instance + */ +export function setExperimental(instance) { + experimental = instance || new Experimental(); + if (lib.config.dev) { + Reflect.set(window, "experimental", experimental); + } +}; diff --git a/noname/library/experimental/symbol.js b/noname/library/experimental/symbol.js index 393976b36f..a28d41d088 100644 --- a/noname/library/experimental/symbol.js +++ b/noname/library/experimental/symbol.js @@ -1,5 +1 @@ -import { Uninstantable } from "../../util/index.js"; - -export class ExperimentalSymbol extends Uninstantable { - static itemType = Symbol("noname.experimental.itemType"); -} +export const ItemType = Symbol("Noname.Experimental.ItemType") diff --git a/noname/library/index.js b/noname/library/index.js index 122cccd6bf..f03a134f22 100644 --- a/noname/library/index.js +++ b/noname/library/index.js @@ -19,7 +19,7 @@ import { gnc } from "../gnc/index.js"; import { LibInit } from "./init/index.js"; import { Announce } from "./announce/index.js"; import { Channel } from "./channel/index.js"; -import { Experimental } from "./experimental/index.js"; +import { experimental } from "./experimental/index.js"; import * as Element from "./element/index.js"; import { updateURLs } from "./update-urls.js"; import { defaultHooks } from "./hooks/index.js"; @@ -29,6 +29,8 @@ import { ErrorManager } from "../util/error.js"; import { defaultSplashs } from "../init/onload/index.js"; +const html = String.raw; + export class Library { configprefix = "noname_0.9_"; versionOL = 27; @@ -1129,6 +1131,26 @@ export class Library { }, unfrequent: true, }, + experimental_enable: { + name: "启用实验性功能", + init: false, + intro: html` + 开启后将启用部分仍处于实验性质的功能,将改变无名杀现有的部分逻辑(重启后生效) +
+ ※ 实验性功能无法保证API稳定,如需使用请及时跟进本体进展 +
+ ※ 以API为主的功能不提供具体实现,如需使用请自行实现 +
+ ※ 部分功能将会作用于联机模式 + `, + /** + * @param {boolean} bool + */ + async onclick(bool) { + await game.promises.saveConfig("experimental_enable", bool); + }, + unfrequent: true, + }, extension_alert: { name: "无视扩展报错", init: false, @@ -9816,7 +9838,7 @@ export class Library { phaseJieshu: "结束阶段", }; - experimental = Experimental; + experimental = experimental; element = { content: Element.Content, From 99b58b9bb159f6a3a31f831bd2a25d0dbadf5fd4 Mon Sep 17 00:00:00 2001 From: Rintim Date: Sun, 16 Mar 2025 20:25:54 +0800 Subject: [PATCH 16/48] fix: tired. --- noname/game/index.js | 7 ++++--- noname/library/experimental/index.js | 10 ---------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/noname/game/index.js b/noname/game/index.js index e8acc79a6f..c5138d22c1 100644 --- a/noname/game/index.js +++ b/noname/game/index.js @@ -4145,11 +4145,12 @@ export class Game extends GameCompatible { } } reloadCurrent() { - let names = [game.me.name1 || game.me.name, game.me.name2]; - if (game.me.name1 != game.me.name) names = [game.me.name]; + const me = Reflect.get(_status, "_startPlayerNames") ?? game.me; + let names = [me.name1 || me.name, me.name2]; + if (me.name1 != me.name) names = [me.name]; game.saveConfig("continue_name", names); game.saveConfig("mode", lib.config.mode); - localStorage.setItem(lib.configprefix + "directstart", true); + localStorage.setItem(lib.configprefix + "directstart", "true"); game.reload(); } /** diff --git a/noname/library/experimental/index.js b/noname/library/experimental/index.js index e2aa8d684c..0bebc52cf6 100644 --- a/noname/library/experimental/index.js +++ b/noname/library/experimental/index.js @@ -16,13 +16,3 @@ export class Experimental { } export let experimental = new Experimental(); - -/** - * @param {Experimental} instance - */ -export function setExperimental(instance) { - experimental = instance || new Experimental(); - if (lib.config.dev) { - Reflect.set(window, "experimental", experimental); - } -}; From 478923b6ac293fb75f6a66f0912a82d7ce5aa948 Mon Sep 17 00:00:00 2001 From: Rintim Date: Mon, 17 Mar 2025 01:10:53 +0800 Subject: [PATCH 17/48] =?UTF-8?q?pref:=20=E9=87=8D=E6=9E=84=E5=9B=BD?= =?UTF-8?q?=E6=88=98=E6=A8=A1=E5=BC=8F=E5=AF=B9`Game`=E7=9A=84=E7=8C=B4?= =?UTF-8?q?=E5=AD=90=E8=A1=A5=E4=B8=81=20(2/3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mode/guozhan/src/patch/content.js | 510 +++++++++++++++++++++++++++++- mode/guozhan/src/patch/game.js | 364 +++------------------ 2 files changed, 547 insertions(+), 327 deletions(-) diff --git a/mode/guozhan/src/patch/content.js b/mode/guozhan/src/patch/content.js index 8126ae33da..8233d2fd48 100644 --- a/mode/guozhan/src/patch/content.js +++ b/mode/guozhan/src/patch/content.js @@ -1,9 +1,513 @@ import { lib, game as _game, ui, get, ai, _status } from "../../../../noname.js"; +import { GameEvent, Dialog, Player, Control, Button } from "../../../../noname/library/element/index.js"; import { GameGuozhan, broadcastAll } from "./game.js"; +import { delay } from "../../../../noname/util/index.js"; /** @type {GameGuozhan} */ // @ts-expect-error 类型就是这么定的 const game = _game; +const html = String.raw; + +/** + * + * @param {GameEvent} event + * @param {GameEvent} _trigger + * @param {Player} _player + */ +export async function chooseCharacterContent(event, _trigger, _player) { + ui.arena.classList.add("choose-character"); + + Reflect.set(event, "addSetting", addSetting); + Reflect.set(event, "removeSetting", removeSetting); + + // 再战的角色选择 + const chosen = lib.config.continue_name || []; + game.saveConfig("continue_name"); + Reflect.set(event, "chosen", chosen); + + // 获取可选择的角色 + /** @type {string[]} */ + let characterList = []; + for (const character in lib.character) { + if (character.indexOf("gz_shibing") == 0) continue; + if (chosen.includes(character)) continue; + if (lib.filter.characterDisabled(character)) continue; + if (get.config("onlyguozhan")) { + if (!lib.characterGuozhanFilter.some(pack => lib.characterPack[pack][character])) continue; + if (get.is.jun(character)) continue; + } + if (lib.character[character].hasHiddenSkill) continue; + characterList.push(character); + } + Reflect.set(_status, "characterlist", characterList.slice(0)); + Reflect.set(_status, "yeidentity", []); + + // 乱斗模式下对武将的过滤 + if (_status.brawl && _status.brawl.chooseCharacterFilter) { + characterList = _status.brawl.chooseCharacterFilter(characterList); + } + + characterList.randomSort(); + + // 获取玩家能选择的角色 + /** @type {string[]} */ + let chooseList; + if (_status.brawl && _status.brawl.chooseCharacter) { + chooseList = _status.brawl.chooseCharacter(characterList, game.me); + } else { + chooseList = game.getCharacterChoice(characterList, parseInt(get.config("choice_num"))); + } + + // 如果托管,则自动选择 + if (_status.auto && event.ai != null) { + event.ai(game.me, chooseList); + lib.init.onfree(); + } + // 如果存在“再战”记录,则使用该记录 + else if (chosen.length) { + game.me.init(chosen[0], chosen[1], false, void 0); + lib.init.onfree(); + } + // 反之,显示选择角色的对话框 + else { + const result = await createChooseCharacterDialog().forResult(); + + // 关闭已打开的额外对话框 + for (const name of ["cheat", "cheat2"]) { + if (!Reflect.has(ui, name)) { + continue; + } + + Reflect.get(ui, name).close(); + Reflect.deleteProperty(ui, name); + } + + if (result.buttons) { + /** @type {string} */ + // @ts-expect-error 祖宗之法就是这么写的 + const name1 = result.buttons[0].link; + /** @type {string} */ + // @ts-expect-error 祖宗之法就是这么写的 + const name2 = result.buttons[1].link; + const characterChosen = [name1, name2]; + + /** @type {Partial?} */ + let result2 = null; + + // @ts-expect-error 祖宗之法就是这么写的 + if (get.is.double(name1, true)) { + // @ts-expect-error 祖宗之法就是这么写的 + if (!get.is.double(name2, true)) { + result2 = { control: lib.character[name2][1] }; + } + // 仙人之兮列如麻 + // @ts-expect-error 祖宗之法就是这么写的 + else if (get.is.double(name1, true).removeArray(get.is.double(name2, true)).length == 0 || get.is.double(name2, true).removeArray(get.is.double(name1, true)).length == 0) { + const next = game.me + // @ts-expect-error 祖宗之法就是这么写的 + .chooseControl(get.is.double(name2, true).filter(group => get.is.double(name1, true).includes(group))); + + next.set("prompt", "请选择你代表的势力"); + // @ts-expect-error 祖宗之法就是这么写的 + next.set("ai", () => _status.event.controls.randomGet()); + + result2 = await next.forResult(); + } else { + result2 = { + // @ts-expect-error 祖宗之法就是这么写的 + control: get.is.double(name1, true).find(group => get.is.double(name2, true).includes(group)), + }; + } + } + // @ts-expect-error 祖宗之法就是这么写的 + else if (lib.character[name1][1] == "ye" && get.is.double(name2, true)) { + const next = game.me + // @ts-expect-error 祖宗之法就是这么写的 + .chooseControl(get.is.double(name2, true)); + + next.set("prompt", "请选择副将代表的势力"); + // @ts-expect-error 祖宗之法就是这么写的 + next.set("ai", () => _status.event.controls.randomGet()); + + result = await next.forResult(); + } + + if (result2?.control) { + // @ts-expect-error 祖宗之法就是这么写的 + game.me.trueIdentity = result2.control; + } + if (characterChosen) { + game.me.init(characterChosen[0], characterChosen[1], false, void 0); + game.addRecentCharacter(characterChosen[0], characterChosen[1]); + } + characterList.remove(game.me.name1); + characterList.remove(game.me.name2); + } + } + + Reflect.set(_status, "_startPlayerNames", { + name: game.me.name, + name1: game.me.name1, + name2: game.me.name2, + }); + + for (const player of game.players) { + if (player != game.me) { + event.ai?.(player, game.getCharacterChoice(characterList, parseInt(get.config("choice_num"))), characterList); + } + } + + for (let i = 0; i < game.players.length; ++i) { + game.players[i].classList.add("unseen"); + game.players[i].classList.add("unseen2"); + // @ts-expect-error 祖宗之法就是这么写的 + _status.characterlist.remove(game.players[i].name); + // @ts-expect-error 祖宗之法就是这么写的 + _status.characterlist.remove(game.players[i].name2); + if (game.players[i] != game.me) { + // @ts-expect-error 祖宗之法就是这么写的 + game.players[i].node.identity.firstChild.innerHTML = "猜"; + game.players[i].node.identity.dataset.color = "unknown"; + game.players[i].node.identity.classList.add("guessing"); + } + game.players[i].hiddenSkills = lib.character[game.players[i].name1][3].slice(0); + var hiddenSkills2 = lib.character[game.players[i].name2][3]; + for (var j = 0; j < hiddenSkills2.length; j++) { + game.players[i].hiddenSkills.add(hiddenSkills2[j]); + } + for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { + if (!lib.skill[game.players[i].hiddenSkills[j]]) { + game.players[i].hiddenSkills.splice(j--, 1); + } + } + game.players[i].group = "unknown"; + game.players[i].sex = "unknown"; + game.players[i].name1 = game.players[i].name; + game.players[i].name = "unknown"; + game.players[i].identity = "unknown"; + game.players[i].node.name.show(); + game.players[i].node.name2.show(); + for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { + // @ts-expect-error 祖宗之法就是这么写的 + game.players[i].addSkillTrigger(game.players[i].hiddenSkills[j], true); + } + } + + delay(500).then(() => { + ui.arena.classList.remove("choose-character"); + }); + + return; + + /** + * @param {Dialog} dialog + */ + function addSetting(dialog) { + const seatNode = dialog.add("选择座位"); + if (typeof seatNode === "object" && seatNode instanceof HTMLElement) { + seatNode.classList.add("add-setting"); + } + + const seats = document.createElement("table"); + seats.classList.add("add-setting"); + seats.style.margin = "0"; + seats.style.width = "100%"; + seats.style.position = "relative"; + + for (let i = 1; i <= game.players.length; ++i) { + const td = ui.create.div(".shadowed.reduce_radius.pointerdiv.tdnode"); + td.innerHTML = html`${get.cnNumber(i, true)}`; + Reflect.set(td, "link", i - 1); + + seats.appendChild(td); + + td.addEventListener("pointerup", onPointerup); + + /** + * @param {PointerEvent} event + */ + function onPointerup(event) { + // 对于输入,必须被识别为“主要输入”,如鼠标左键或单点触控 + // 如果不是主要输入,则忽略 + if (!event.isPrimary) { + return; + } + + // 对于鼠标来说,必须是左键点击(对应click) + if (event.button != 0) { + return; + } + + // 如果目前有正在拖拽的元素,就忽略当前点击 + if (_status.dragged) { + return; + } + // 后面不知道,略过 + // @ts-expect-error 祖宗之法就是这么写的 + if (_status.justdragged) return; + // @ts-expect-error 祖宗之法就是这么写的 + if (_status.cheat_seat) { + // @ts-expect-error 祖宗之法就是这么写的 + _status.cheat_seat.classList.remove("bluebg"); + // @ts-expect-error 祖宗之法就是这么写的 + if (_status.cheat_seat == this) { + // @ts-expect-error 祖宗之法就是这么写的 + delete _status.cheat_seat; + return; + } + } + this.classList.add("bluebg"); + // @ts-expect-error 祖宗之法就是这么写的 + _status.cheat_seat = this; + } + } + + dialog.content.appendChild(seats); + + dialog.add(ui.create.div(".placeholder.add-setting")); + dialog.add(ui.create.div(".placeholder.add-setting")); + if (get.is.phoneLayout()) { + dialog.add(ui.create.div(".placeholder.add-setting")); + } + } + + function removeSetting() { + const event = get.event(); + /** @type {Dialog?} */ + const dialog = Reflect.get(event, "dialog"); + if (dialog == null) { + return; + } + + dialog.style.height = ""; + Reflect.deleteProperty(dialog, "_scrollset"); + + const list = dialog.querySelectorAll(".add-setting"); + + for (const node of list) { + node.remove(); + } + + ui.update(); + } + + function createChooseCharacterDialog() { + const dialog = ui.create.dialog("选择角色", "hidden", [chooseList, "character"]); + + // 如果是乱斗模式,添加额外的设置 + if (!_status.brawl || !_status.brawl.noAddSetting) { + if (get.config("change_identity")) { + addSetting(dialog); + } + } + + const next = game.me.chooseButton(dialog, true, 2); + + next.set("onfree", true); + next.set("filterButton", filterButton); + next.set("switchToAuto", switchToAuto); + + if (lib.onfree) { + lib.onfree.push(createCharacterDialog); + } else { + createCharacterDialog(); + } + + Reflect.set(ui.create, "cheat2", createCheat2); + Reflect.set(ui.create, "cheat", createCheat); + + if (!_status.brawl || !_status.brawl.chooseCharacterFixed) { + // @ts-expect-error 祖宗之法就是这么写的 + if (!ui.cheat && get.config("change_choice")) ui.create.cheat(); + // @ts-expect-error 祖宗之法就是这么写的 + if (!ui.cheat2 && get.config("free_choose")) ui.create.cheat2(); + } + + return next; + + /** + * @param {Button} button + */ + function filterButton(button) { + if (ui.dialog.buttons.length <= 10) { + for (var i = 0; i < ui.dialog.buttons.length; i++) { + if (ui.dialog.buttons[i] != button) { + if ( + // @ts-expect-error 祖宗之法就是这么写的 + lib.element.player.perfectPair.call( + { + // @ts-expect-error 祖宗之法就是这么写的 + name1: button.link, + // @ts-expect-error 祖宗之法就是这么写的 + name2: ui.dialog.buttons[i].link, + }, + true + ) + ) { + button.classList.add("glow2"); + } + } + } + } + // @ts-expect-error 祖宗之法就是这么写的 + if (lib.character[button.link].hasHiddenSkill) return false; + var filterChoice = function (name1, name2) { + // @ts-expect-error 祖宗之法就是这么写的 + if (_status.separatism) return true; + var group1 = lib.character[name1][1]; + var group2 = lib.character[name2][1]; + // @ts-expect-error 祖宗之法就是这么写的 + var doublex = get.is.double(name1, true); + if (doublex) { + // @ts-expect-error 祖宗之法就是这么写的 + var double = get.is.double(name2, true); + // @ts-expect-error 祖宗之法就是这么写的 + if (double) return doublex.some(group => double.includes(group)); + // @ts-expect-error 祖宗之法就是这么写的 + return doublex.includes(group2); + } else { + if (group1 == "ye") return group2 != "ye"; + // @ts-expect-error 祖宗之法就是这么写的 + var double = get.is.double(name2, true); + // @ts-expect-error 祖宗之法就是这么写的 + if (double) return double.includes(group1); + return group1 == group2; + } + }; + if (!ui.selected.buttons.length) { + return ui.dialog.buttons.some(but => { + if (but == button) return false; + // @ts-expect-error 祖宗之法就是这么写的 + return filterChoice(button.link, but.link); + }); + } + // @ts-expect-error 祖宗之法就是这么写的 + return filterChoice(ui.selected.buttons[0].link, button.link); + } + + function switchToAuto() { + event.ai?.(game.me, chooseList); + ui.arena.classList.remove("selecting"); + } + } + + function createCharacterDialog() { + const dialogxx = ui.create.characterDialog( + "heightset", + function (i) { + if (i.indexOf("gz_shibing") == 0) return true; + if (get.config("onlyguozhan")) { + if (!lib.characterGuozhanFilter.some(pack => lib.characterPack[pack][i])) return true; + if (get.is.jun(i)) return true; + } + }, + get.config("onlyguozhanexpand") ? "expandall" : undefined, + get.config("onlyguozhan") ? "onlypack:mode_guozhan" : undefined + ); + Reflect.set(event, "dialogxx", dialogxx); + + const cheat2 = Reflect.get(ui, "cheat2"); + if (cheat2 != null) { + cheat2.addTempClass("controlpressdownx", 500); + cheat2.classList.remove("disabled"); + } + } + + function createCheat2() { + const cheat2 = ui.create.control("自由选将", onClick); + Reflect.set(ui, "cheat2", cheat2); + + if (lib.onfree) { + cheat2.classList.add("disabled"); + } + + /** @this {Control} */ + function onClick() { + // @ts-expect-error 祖宗之法就是这么写的 + if (this.dialog == _status.event?.dialog) { + // @ts-expect-error 祖宗之法就是这么写的 + if (game.changeCoin) { + // @ts-expect-error 祖宗之法就是这么写的 + game.changeCoin(10); + } + // @ts-expect-error 祖宗之法就是这么写的 + this.dialog.close(); + // @ts-expect-error 祖宗之法就是这么写的 + _status.event.dialog = this.backup; + // @ts-expect-error 祖宗之法就是这么写的 + this.backup.open(); + // @ts-expect-error 祖宗之法就是这么写的 + delete this.backup; + game.uncheck(); + game.check(); + // @ts-expect-error 祖宗之法就是这么写的 + if (ui.cheat) { + // @ts-expect-error 祖宗之法就是这么写的 + ui.cheat.addTempClass("controlpressdownx", 500); + // @ts-expect-error 祖宗之法就是这么写的 + ui.cheat.classList.remove("disabled"); + } + } else { + // @ts-expect-error 祖宗之法就是这么写的 + if (game.changeCoin) { + // @ts-expect-error 祖宗之法就是这么写的 + game.changeCoin(-10); + } + // @ts-expect-error 祖宗之法就是这么写的 + this.backup = _status.event.dialog; + // @ts-expect-error 祖宗之法就是这么写的 + _status.event.dialog.close(); + // @ts-expect-error 祖宗之法就是这么写的 + _status.event.dialog = _status.event.parent.dialogxx; + // @ts-expect-error 祖宗之法就是这么写的 + this.dialog = _status.event.dialog; + // @ts-expect-error 祖宗之法就是这么写的 + this.dialog.open(); + game.uncheck(); + game.check(); + // @ts-expect-error 祖宗之法就是这么写的 + if (ui.cheat) { + // @ts-expect-error 祖宗之法就是这么写的 + ui.cheat.classList.add("disabled"); + } + } + } + } + + function createCheat() { + // @ts-expect-error 祖宗之法就是这么写的 + _status.createControl = ui.cheat2; + const cheat = ui.create.control("更换", function () { + // @ts-expect-error 祖宗之法就是这么写的 + if (ui.cheat2 && ui.cheat2.dialog == _status.event.dialog) { + return; + } + // @ts-expect-error 祖宗之法就是这么写的 + if (game.changeCoin) { + // @ts-expect-error 祖宗之法就是这么写的 + game.changeCoin(-3); + } + characterList = characterList.concat(chooseList); + characterList.randomSort(); + // list=event.list.splice(0,parseInt(get.config('choice_num'))); + chooseList = game.getCharacterChoice(characterList, parseInt(get.config("choice_num"))); + var buttons = ui.create.div(".buttons"); + // @ts-expect-error 祖宗之法就是这么写的 + var node = _status.event.dialog.buttons[0].parentNode; + // @ts-expect-error 祖宗之法就是这么写的 + _status.event.dialog.buttons = ui.create.buttons(chooseList, "character", buttons); + // @ts-expect-error 祖宗之法就是这么写的 + _status.event.dialog.content.insertBefore(buttons, node); + buttons.addTempClass("start"); + node.remove(); + game.uncheck(); + game.check(); + }); + Reflect.set(ui, "cheat", cheat); + // @ts-expect-error 祖宗之法就是这么写的 + delete _status.createControl; + } +} /** * @@ -13,6 +517,7 @@ const game = _game; */ export async function showYexingsContent(event, _trigger, player) { /** @type {Player[]} */ + // @ts-expect-error 祖宗之法就是这么做的 const yexingPlayers = game // @ts-expect-error 祖宗之法就是这么做的 .filterPlayer(current => lib.character[current.name1][1] == "ye" && !current._showYexing) @@ -39,7 +544,7 @@ export async function showYexingsContent(event, _trigger, player) { */ player => { // @ts-expect-error 祖宗之法就是这么做的 - player._showYexing = true + player._showYexing = true; }, player ); @@ -118,6 +623,7 @@ export async function showYexingsContent(event, _trigger, player) { target.removeMark("yexinjia_mark", 1); /** @type {Player[]} */ + // @ts-expect-error 祖宗之法就是这么做的 const maybeFriends = game.players.filter(current => current.identity != "ye" && current !== target && !get.is.jun(current) && !yexingPlayers.includes(current) && !current.getStorage("yexinjia_friend").length); if (maybeFriends.length === 0) { continue; @@ -185,7 +691,7 @@ export async function showYexingsContent(event, _trigger, player) { await other.recover(); } } - + // @ts-expect-error 祖宗之法就是这么写的 delete _status.showYexings; diff --git a/mode/guozhan/src/patch/game.js b/mode/guozhan/src/patch/game.js index 56448fe0d1..f887de4716 100644 --- a/mode/guozhan/src/patch/game.js +++ b/mode/guozhan/src/patch/game.js @@ -1,7 +1,7 @@ import { lib, game, ui, get, ai, _status } from "../../../../noname.js"; import { GameEvent, Dialog, Player } from "../../../../noname/library/element/index.js"; import { Game } from "../../../../noname/game/index.js"; -import { showYexingsContent } from "./content.js"; +import { showYexingsContent, chooseCharacterContent } from "./content.js"; export class GameGuozhan extends Game { /** @@ -283,7 +283,7 @@ export class GameGuozhan extends Game { } /** - * @param {string[]} list + * @param {string[]} list */ getIdentityList2(list) { for (var i in list) { @@ -308,10 +308,10 @@ export class GameGuozhan extends Game { } } } - + /** * 获取当前对局对应录像的名称 - * + * * @returns {[name: string, situation: string]} */ getVideoName() { @@ -331,8 +331,8 @@ export class GameGuozhan extends Game { /** * 显示所有玩家的身份 - * - * @param {boolean} started + * + * @param {boolean} started */ showIdentity(started) { if (game.phaseNumber == 0 && !started) return; @@ -342,7 +342,7 @@ export class GameGuozhan extends Game { } /** - * > ? + * > ? */ tryResult() { var map = {}, @@ -436,7 +436,7 @@ export class GameGuozhan extends Game { /** * > ? - * @param {Player} player + * @param {Player} player * @returns {boolean} */ checkOnlineResult(player) { @@ -446,27 +446,46 @@ export class GameGuozhan extends Game { } chooseCharacter() { - var next = game.createEvent("chooseCharacter"); - next.showConfig = true; - next.addPlayer = true; - next.ai = function (player, list, back) { + const next = game.createEvent("chooseCharacter"); + + next.set("showConfig", true); + next.set("addPlayer", true); + next.set("ai", check); + next.setContent(chooseCharacterContent); + + return next; + + /** + * @param {Player} player + * @param {string[]} list + * @param {string[]} [back] + * @returns + */ + function check(player, list, back) { if (_status.brawl && _status.brawl.chooseCharacterAi) { if (_status.brawl.chooseCharacterAi(player, list, back) !== false) { return; } } var filterChoice = function (name1, name2) { + // @ts-expect-error 祖宗之法就是这么写的 if (_status.separatism) return true; var group1 = lib.character[name1][1]; var group2 = lib.character[name2][1]; + // @ts-expect-error 祖宗之法就是这么写的 var doublex = get.is.double(name1, true); if (doublex) { + // @ts-expect-error 祖宗之法就是这么写的 var double = get.is.double(name2, true); + // @ts-expect-error 祖宗之法就是这么写的 if (double) return doublex.some(group => double.includes(group)); + // @ts-expect-error 祖宗之法就是这么写的 return doublex.includes(group2); } else { if (group1 == "ye") return group2 != "ye"; + // @ts-expect-error 祖宗之法就是这么写的 var double = get.is.double(name2, true); + // @ts-expect-error 祖宗之法就是这么写的 if (double) return double.includes(group1); return group1 == group2; } @@ -481,14 +500,21 @@ export class GameGuozhan extends Game { vicex = list[i]; } player.init(mainx, vicex, false); + // @ts-expect-error 祖宗之法就是这么写的 if (get.is.double(mainx, true)) { + // @ts-expect-error 祖宗之法就是这么写的 if (!get.is.double(vicex, true)) player.trueIdentity = lib.character[vicex][1]; + // @ts-expect-error 祖宗之法就是这么写的 else if (get.is.double(mainx, true).removeArray(get.is.double(vicex, true)).length == 0 || get.is.double(vicex, true).removeArray(get.is.double(mainx, true)).length == 0) + // @ts-expect-error 祖宗之法就是这么写的 player.trueIdentity = get.is .double(vicex, true) + // @ts-expect-error 祖宗之法就是这么写的 .filter(group => get.is.double(mainx, true).includes(group)) .randomGet(); + // @ts-expect-error 祖宗之法就是这么写的 else player.trueIdentity = get.is.double(mainx, true).find(group => get.is.double(vicex, true).includes(group)); + // @ts-expect-error 祖宗之法就是这么写的 } else if (lib.character[mainx][1] == "ye" && get.is.double(vicex, true)) player.trueIdentity = get.is.double(vicex, true).randomGet(); if (back) { list.remove(player.name1); @@ -501,319 +527,7 @@ export class GameGuozhan extends Game { } } } - }; - next.setContent(function () { - "step 0"; - ui.arena.classList.add("choose-character"); - var addSetting = function (dialog) { - dialog.add("选择座位").classList.add("add-setting"); - var seats = document.createElement("table"); - seats.classList.add("add-setting"); - seats.style.margin = "0"; - seats.style.width = "100%"; - seats.style.position = "relative"; - for (var i = 1; i <= game.players.length; i++) { - var td = ui.create.div(".shadowed.reduce_radius.pointerdiv.tdnode"); - td.innerHTML = "" + get.cnNumber(i, true) + ""; - td.link = i - 1; - seats.appendChild(td); - td.addEventListener(lib.config.touchscreen ? "touchend" : "click", function () { - if (_status.dragged) return; - if (_status.justdragged) return; - if (_status.cheat_seat) { - _status.cheat_seat.classList.remove("bluebg"); - if (_status.cheat_seat == this) { - delete _status.cheat_seat; - return; - } - } - this.classList.add("bluebg"); - _status.cheat_seat = this; - }); - } - dialog.content.appendChild(seats); - if (game.me == game.zhu) { - seats.previousSibling.style.display = "none"; - seats.style.display = "none"; - } - - dialog.add(ui.create.div(".placeholder.add-setting")); - dialog.add(ui.create.div(".placeholder.add-setting")); - if (get.is.phoneLayout()) dialog.add(ui.create.div(".placeholder.add-setting")); - }; - var removeSetting = function () { - var dialog = _status.event.dialog; - if (dialog) { - dialog.style.height = ""; - delete dialog._scrollset; - var list = Array.from(dialog.querySelectorAll(".add-setting")); - while (list.length) { - list.shift().remove(); - } - ui.update(); - } - }; - event.addSetting = addSetting; - event.removeSetting = removeSetting; - - var chosen = lib.config.continue_name || []; - game.saveConfig("continue_name"); - event.chosen = chosen; - - var i; - event.list = []; - for (i in lib.character) { - if (i.indexOf("gz_shibing") == 0) continue; - if (chosen.includes(i)) continue; - if (lib.filter.characterDisabled(i)) continue; - if (get.config("onlyguozhan")) { - if (!lib.characterGuozhanFilter.some(pack => lib.characterPack[pack][i])) continue; - if (get.is.jun(i)) continue; - } - if (lib.character[i].hasHiddenSkill) continue; - event.list.push(i); - } - _status.characterlist = event.list.slice(0); - _status.yeidentity = []; - if (_status.brawl && _status.brawl.chooseCharacterFilter) { - event.list = _status.brawl.chooseCharacterFilter(event.list); - } - event.list.randomSort(); - // var list=event.list.splice(0,parseInt(get.config('choice_num'))); - var list; - if (_status.brawl && _status.brawl.chooseCharacter) { - list = _status.brawl.chooseCharacter(event.list, game.me); - } else { - list = game.getCharacterChoice(event.list, parseInt(get.config("choice_num"))); - } - if (_status.auto) { - event.ai(game.me, list); - lib.init.onfree(); - } else if (chosen.length) { - game.me.init(chosen[0], chosen[1], false); - lib.init.onfree(); - } else { - var dialog = ui.create.dialog("选择角色", "hidden", [list, "character"]); - if (!_status.brawl || !_status.brawl.noAddSetting) { - if (get.config("change_identity")) { - addSetting(dialog); - } - } - var next = game.me.chooseButton(dialog, true, 2).set("onfree", true); - next.filterButton = function (button) { - if (ui.dialog.buttons.length <= 10) { - for (var i = 0; i < ui.dialog.buttons.length; i++) { - if (ui.dialog.buttons[i] != button) { - if ( - lib.element.player.perfectPair.call( - { - name1: button.link, - name2: ui.dialog.buttons[i].link, - }, - true - ) - ) { - button.classList.add("glow2"); - } - } - } - } - if (lib.character[button.link].hasHiddenSkill) return false; - var filterChoice = function (name1, name2) { - if (_status.separatism) return true; - var group1 = lib.character[name1][1]; - var group2 = lib.character[name2][1]; - var doublex = get.is.double(name1, true); - if (doublex) { - var double = get.is.double(name2, true); - if (double) return doublex.some(group => double.includes(group)); - return doublex.includes(group2); - } else { - if (group1 == "ye") return group2 != "ye"; - var double = get.is.double(name2, true); - if (double) return double.includes(group1); - return group1 == group2; - } - }; - if (!ui.selected.buttons.length) { - return ui.dialog.buttons.some(but => { - if (but == button) return false; - return filterChoice(button.link, but.link); - }); - } - return filterChoice(ui.selected.buttons[0].link, button.link); - }; - next.switchToAuto = function () { - event.ai(game.me, list); - ui.arena.classList.remove("selecting"); - }; - var createCharacterDialog = function () { - event.dialogxx = ui.create.characterDialog( - "heightset", - function (i) { - if (i.indexOf("gz_shibing") == 0) return true; - if (get.config("onlyguozhan")) { - if (!lib.characterGuozhanFilter.some(pack => lib.characterPack[pack][i])) return true; - if (get.is.jun(i)) return true; - } - }, - get.config("onlyguozhanexpand") ? "expandall" : undefined, - get.config("onlyguozhan") ? "onlypack:mode_guozhan" : undefined - ); - if (ui.cheat2) { - ui.cheat2.addTempClass("controlpressdownx", 500); - ui.cheat2.classList.remove("disabled"); - } - }; - if (lib.onfree) { - lib.onfree.push(createCharacterDialog); - } else { - createCharacterDialog(); - } - ui.create.cheat2 = function () { - ui.cheat2 = ui.create.control("自由选将", function () { - if (this.dialog == _status.event.dialog) { - if (game.changeCoin) { - game.changeCoin(10); - } - this.dialog.close(); - _status.event.dialog = this.backup; - this.backup.open(); - delete this.backup; - game.uncheck(); - game.check(); - if (ui.cheat) { - ui.cheat.addTempClass("controlpressdownx", 500); - ui.cheat.classList.remove("disabled"); - } - } else { - if (game.changeCoin) { - game.changeCoin(-10); - } - this.backup = _status.event.dialog; - _status.event.dialog.close(); - _status.event.dialog = _status.event.parent.dialogxx; - this.dialog = _status.event.dialog; - this.dialog.open(); - game.uncheck(); - game.check(); - if (ui.cheat) { - ui.cheat.classList.add("disabled"); - } - } - }); - if (lib.onfree) { - ui.cheat2.classList.add("disabled"); - } - }; - ui.create.cheat = function () { - _status.createControl = ui.cheat2; - ui.cheat = ui.create.control("更换", function () { - if (ui.cheat2 && ui.cheat2.dialog == _status.event.dialog) { - return; - } - if (game.changeCoin) { - game.changeCoin(-3); - } - event.list = event.list.concat(list); - event.list.randomSort(); - // list=event.list.splice(0,parseInt(get.config('choice_num'))); - list = game.getCharacterChoice(event.list, parseInt(get.config("choice_num"))); - var buttons = ui.create.div(".buttons"); - var node = _status.event.dialog.buttons[0].parentNode; - _status.event.dialog.buttons = ui.create.buttons(list, "character", buttons); - _status.event.dialog.content.insertBefore(buttons, node); - buttons.addTempClass("start"); - node.remove(); - game.uncheck(); - game.check(); - }); - delete _status.createControl; - }; - if (!_status.brawl || !_status.brawl.chooseCharacterFixed) { - if (!ui.cheat && get.config("change_choice")) ui.create.cheat(); - if (!ui.cheat2 && get.config("free_choose")) ui.create.cheat2(); - } - } - ("step 1"); - if (ui.cheat) { - ui.cheat.close(); - delete ui.cheat; - } - if (ui.cheat2) { - ui.cheat2.close(); - delete ui.cheat2; - } - if (result.buttons) { - var name1 = result.buttons[0].link, - name2 = result.buttons[1].link; - event.choosen = [name1, name2]; - if (get.is.double(name1, true)) { - if (!get.is.double(name2, true)) event._result = { control: lib.character[name2][1] }; - else if (get.is.double(name1, true).removeArray(get.is.double(name2, true)).length == 0 || get.is.double(name2, true).removeArray(get.is.double(name1, true)).length == 0) - game.me - .chooseControl(get.is.double(name2, true).filter(group => get.is.double(name1, true).includes(group))) - .set("prompt", "请选择你代表的势力") - .set("ai", () => _status.event.controls.randomGet()); - else - event._result = { - control: get.is.double(name1, true).find(group => get.is.double(name2, true).includes(group)), - }; - } else if (lib.character[name1][1] == "ye" && get.is.double(name2, true)) - game.me - .chooseControl(get.is.double(name2, true)) - .set("prompt", "请选择副将代表的势力") - .set("ai", () => _status.event.controls.randomGet()); - } - ("step 2"); - if (result && result.control) game.me.trueIdentity = result.control; - if (event.choosen) { - game.me.init(event.choosen[0], event.choosen[1], false); - game.addRecentCharacter(event.choosen[0], event.choosen[1]); - } - event.list.remove(game.me.name1); - event.list.remove(game.me.name2); - for (var i = 0; i < game.players.length; i++) { - if (game.players[i] != game.me) { - event.ai(game.players[i], game.getCharacterChoice(event.list, parseInt(get.config("choice_num"))), event.list); - } - } - for (var i = 0; i < game.players.length; i++) { - game.players[i].classList.add("unseen"); - game.players[i].classList.add("unseen2"); - _status.characterlist.remove(game.players[i].name); - _status.characterlist.remove(game.players[i].name2); - if (game.players[i] != game.me) { - game.players[i].node.identity.firstChild.innerHTML = "猜"; - game.players[i].node.identity.dataset.color = "unknown"; - game.players[i].node.identity.classList.add("guessing"); - } - game.players[i].hiddenSkills = lib.character[game.players[i].name1][3].slice(0); - var hiddenSkills2 = lib.character[game.players[i].name2][3]; - for (var j = 0; j < hiddenSkills2.length; j++) { - game.players[i].hiddenSkills.add(hiddenSkills2[j]); - } - for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { - if (!lib.skill[game.players[i].hiddenSkills[j]]) { - game.players[i].hiddenSkills.splice(j--, 1); - } - } - game.players[i].group = "unknown"; - game.players[i].sex = "unknown"; - game.players[i].name1 = game.players[i].name; - game.players[i].name = "unknown"; - game.players[i].identity = "unknown"; - game.players[i].node.name.show(); - game.players[i].node.name2.show(); - for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { - game.players[i].addSkillTrigger(game.players[i].hiddenSkills[j], true); - } - } - setTimeout(function () { - ui.arena.classList.remove("choose-character"); - }, 500); - }); - return next; + } } chooseCharacterOL() { var next = game.createEvent("chooseCharacter"); From 543981ba21ef9b6d4ade49f6baec745506c25ff0 Mon Sep 17 00:00:00 2001 From: Rintim Date: Mon, 17 Mar 2025 22:39:00 +0800 Subject: [PATCH 18/48] =?UTF-8?q?pref:=20=E9=87=8D=E6=9E=84=E5=9B=BD?= =?UTF-8?q?=E6=88=98=E6=A8=A1=E5=BC=8F=E5=AF=B9`Game`=E7=9A=84=E7=8C=B4?= =?UTF-8?q?=E5=AD=90=E8=A1=A5=E4=B8=81=20(3/3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mode/guozhan/src/patch/content.js | 316 +++++++++++++++++++++++++++++- mode/guozhan/src/patch/game.js | 284 ++------------------------- 2 files changed, 331 insertions(+), 269 deletions(-) diff --git a/mode/guozhan/src/patch/content.js b/mode/guozhan/src/patch/content.js index 8233d2fd48..4481e54c68 100644 --- a/mode/guozhan/src/patch/content.js +++ b/mode/guozhan/src/patch/content.js @@ -1,5 +1,5 @@ import { lib, game as _game, ui, get, ai, _status } from "../../../../noname.js"; -import { GameEvent, Dialog, Player, Control, Button } from "../../../../noname/library/element/index.js"; +import { GameEvent, Dialog, Player, Control, Button, Character } from "../../../../noname/library/element/index.js"; import { GameGuozhan, broadcastAll } from "./game.js"; import { delay } from "../../../../noname/util/index.js"; @@ -9,7 +9,6 @@ const game = _game; const html = String.raw; /** - * * @param {GameEvent} event * @param {GameEvent} _trigger * @param {Player} _player @@ -129,7 +128,7 @@ export async function chooseCharacterContent(event, _trigger, _player) { // @ts-expect-error 祖宗之法就是这么写的 next.set("ai", () => _status.event.controls.randomGet()); - result = await next.forResult(); + result2 = await next.forResult(); } if (result2?.control) { @@ -510,7 +509,316 @@ export async function chooseCharacterContent(event, _trigger, _player) { } /** - * + * @param {GameEvent} event + * @param {GameEvent} _trigger + * @param {Player} _player + */ +export async function chooseCharacterOLContent(event, _trigger, _player) { + broadcastAll(() => { + ui.arena.classList.add("choose-character"); + for (const player of game.players) { + player.classList.add("unseen"); + player.classList.add("unseen2"); + } + }); + + /** @type {Record} */ + const pack = Reflect.get(lib.characterPack, "mode_guozhan"); + const characterList = Object.keys(pack).filter(character => { + return !character.startsWith("gz_shibing") && !get.is.jun(character) && !lib.config.guozhan_banned?.includes(character); + }); + Reflect.set(_status, "characterlist", characterList.slice(0)); + Reflect.set(_status, "yeidentity", []); + + const list2 = []; + let num; + if (lib.configOL.number * 6 > characterList.length) { + num = 5; + } else if (lib.configOL.number * 7 > characterList.length) { + num = 6; + } else { + num = 7; + } + + characterList.randomSort(); + for (const player of game.players) { + list2.push([player, ["选择角色", [game.getCharacterChoice(characterList, num), "character"]], 2, true, () => Math.random(), filterButton]); + } + + const next = game.me.chooseButtonOL( + list2, + (player, result) => { + if (game.online || player == game.me) { + player.init(result.links[0], result.links[1], false); + } + }, + void 0 + ); + + next.set("processAI", chooseCharacterCheck); + next.set("switchToAuto", () => { + Reflect.set(get.event(), "result", "ai"); + }); + + const chooseCharacterResult = await next.forResult(); + + let sort = true; + const chosen = []; + const chosenCharacter = []; + + for (const i in chooseCharacterResult) { + if (chooseCharacterResult[i] && chooseCharacterResult[i].links) { + for (var j = 0; j < chooseCharacterResult[i].links.length; j++) { + characterList.remove(chooseCharacterResult[i].links[j]); + } + } + } + + for (const i in chooseCharacterResult) { + if (chooseCharacterResult[i] == "ai" || !chooseCharacterResult[i].links || chooseCharacterResult[i].links.length < 1) { + if (sort) { + sort = false; + characterList.randomSort(); + } + chooseCharacterResult[i] = [characterList.shift()]; + const group = lib.character[chooseCharacterResult[i][0]][1]; + for (let j = 0; j < characterList.length; j++) { + if (lib.character[characterList[j]][1] == group) { + chooseCharacterResult[i].push(characterList[j]); + characterList.splice(j--, 1); + break; + } + } + } else { + chooseCharacterResult[i] = chooseCharacterResult[i].links; + } + const name1 = chooseCharacterResult[i][0]; + const name2 = chooseCharacterResult[i][1]; + // @ts-expect-error 祖宗之法就是这么写的 + if (get.is.double(name1, true)) { + // @ts-expect-error 祖宗之法就是这么写的 + if (!get.is.double(name2, true)) { + // @ts-expect-error 祖宗之法就是这么写的 + lib.playerOL[i].trueIdentity = lib.character[name2][1]; + // @ts-expect-error 祖宗之法就是这么写的 + } else if (get.is.double(name1, true).removeArray(get.is.double(name2, true)).length == 0 || get.is.double(name2, true).removeArray(get.is.double(name1, true)).length == 0) { + chosen.push(lib.playerOL[i]); + chosenCharacter.push([name1, name2]); + } else { + // @ts-expect-error 祖宗之法就是这么写的 + lib.playerOL[i].trueIdentity = get.is.double(name1, true).find(group => get.is.double(name2, true).includes(group)); + } + // @ts-expect-error 祖宗之法就是这么写的 + } else if (lib.character[name1][1] == "ye" && get.is.double(name2, true)) { + chosen.push(lib.playerOL[i]); + chosenCharacter.push([name1, name2]); + } + } + + let chooseGroupResult = {}; + if (chosen.length) { + for (let i = 0; i < chosen.length; ++i) { + const name1 = chosenCharacter[i][0]; + const name2 = chosenCharacter[i][1]; + let str; + let choice; + if (get.is.double(name1, true)) { + str = "请选择你代表的势力"; + choice = get.is.double(name2, true).filter(group => get.is.double(name1, true).includes(group)); + } + if (lib.character[name1][1] == "ye") { + str = "请选择你的副将代表的势力"; + choice = get.is.double(name2, true); + } + chosen[i] = [chosen[i], [str, [choice.map(i => ["", "", "group_" + i]), "vcard"]], 1, true]; + } + + chooseGroupResult = await game.me + .chooseButtonOL( + chosen, + function (player, result) { + if (player == game.me) player.trueIdentity = result.links[0][2].slice(6); + }, + void 0 + ) + .set("switchToAuto", () => { + // @ts-expect-error 祖宗之法就是这么写的 + _status.event.result = "ai"; + }) + .set("processAI", () => { + return { + bool: true, + // @ts-expect-error 祖宗之法就是这么写的 + links: [_status.event.dialog.buttons.randomGet().link], + }; + }) + .forResult(); + } + + broadcastAll( + (result, result2, delay) => { + for (const current of game.players) { + const id = current.playerid; + // @ts-expect-error 祖宗之法就是这么写的 + if (result[id] && !current.name) { + // @ts-expect-error 祖宗之法就是这么写的 + current.init(result[id][0], result[id][1], false); + } + // @ts-expect-error 祖宗之法就是这么写的 + if (result2[id] && result2[id].length) { + // @ts-expect-error 祖宗之法就是这么写的 + current.trueIdentity = result2[id][0][2].slice(6); + } + if (current != game.me) { + // @ts-expect-error 祖宗之法就是这么写的 + current.node.identity.firstChild.innerHTML = "猜"; + current.node.identity.dataset.color = "unknown"; + current.node.identity.classList.add("guessing"); + } + current.hiddenSkills = lib.character[current.name1][3].slice(0); + const hiddenSkills2 = lib.character[current.name2][3]; + for (const skill of hiddenSkills2) { + current.hiddenSkills.add(skill); + } + for (let j = 0; j < current.hiddenSkills.length; j++) { + if (!lib.skill[current.hiddenSkills[j]]) { + current.hiddenSkills.splice(j--, 1); + } + } + current.group = "unknown"; + current.sex = "unknown"; + current.name1 = current.name; + current.name = "unknown"; + current.identity = "unknown"; + current.node.name.show(); + current.node.name2.show(); + for (const skill of current.hiddenSkills) { + // @ts-expect-error 祖宗之法就是这么写的 + current.addSkillTrigger(skill, true); + } + } + + delay(500).then(() => { + ui.arena.classList.remove("choose-character") + }); + }, + chooseCharacterResult, + chooseGroupResult, + delay + ); + + return; + + function filterButton(button) { + if (ui.dialog) { + if (ui.dialog.buttons.length <= 10) { + for (const btn of ui.dialog.buttons) { + if (btn !== button) { + if ( + // @ts-expect-error 祖宗之法就是这么写的 + lib.element.player.perfectPair.call( + { + name1: button.link, + // @ts-expect-error 祖宗之法就是这么写的 + name2: btn.link, + }, + true + ) + ) { + button.classList.add("glow2"); + } + } + } + } + } + const filterChoice = (name1, name2) => { + // @ts-expect-error 祖宗之法就是这么写的 + if (_status.separatism) return true; + const group1 = lib.character[name1][1]; + const group2 = lib.character[name2][1]; + // @ts-expect-error 祖宗之法就是这么写的 + const doublex = get.is.double(name1, true); + if (doublex) { + // @ts-expect-error 祖宗之法就是这么写的 + const double = get.is.double(name2, true); + // @ts-expect-error 祖宗之法就是这么写的 + if (double) return doublex.some(group => double.includes(group)); + // @ts-expect-error 祖宗之法就是这么写的 + return doublex.includes(group2); + } else { + if (group1 === "ye") return group2 !== "ye"; + // @ts-expect-error 祖宗之法就是这么写的 + const double = get.is.double(name2, true); + // @ts-expect-error 祖宗之法就是这么写的 + if (double) return double.includes(group1); + return group1 === group2; + } + }; + if (!ui.selected.buttons.length) { + return ui.dialog.buttons.some(but => { + if (but === button) return false; + // @ts-expect-error 祖宗之法就是这么写的 + return filterChoice(button.link, but.link); + }); + } + // @ts-expect-error 祖宗之法就是这么写的 + return filterChoice(ui.selected.buttons[0].link, button.link); + } + + function chooseCharacterCheck() { + // @ts-expect-error 祖宗之法就是这么写的 + const buttons = _status.event.dialog.buttons; + + const filterChoice = (name1, name2) => { + // @ts-expect-error 祖宗之法就是这么写的 + if (_status.separatism) return true; + const group1 = lib.character[name1][1]; + const group2 = lib.character[name2][1]; + // @ts-expect-error 祖宗之法就是这么写的 + const doublex = get.is.double(name1, true); + if (doublex) { + // @ts-expect-error 祖宗之法就是这么写的 + const double = get.is.double(name2, true); + // @ts-expect-error 祖宗之法就是这么写的 + if (double) return doublex.some(group => double.includes(group)); + // @ts-expect-error 祖宗之法就是这么写的 + return doublex.includes(group2); + } else { + if (group1 === "ye") return group2 !== "ye"; + // @ts-expect-error 祖宗之法就是这么写的 + const double = get.is.double(name2, true); + // @ts-expect-error 祖宗之法就是这么写的 + if (double) return double.includes(group1); + return group1 === group2; + } + }; + + for (let i = 0; i < buttons.length - 1; ++i) { + const button1 = buttons[i]; + for (let j = i + 1; j < buttons.length; ++j) { + const button2 = buttons[j]; + + if (filterChoice(button1.link, button2.link) || filterChoice(button2.link, button1.link)) { + let mainx = button1.link; + let vicex = button2.link; + + // @ts-expect-error 祖宗之法就是这么写的 + if (!filterChoice(mainx, vicex) || (filterChoice(vicex, mainx) && get.guozhanReverse(mainx, vicex))) { + mainx = button2.link; + vicex = button1.link; + } + const list = [mainx, vicex]; + return { + bool: true, + links: list, + }; + } + } + } + } +} + +/** * @param {GameEvent} event * @param {GameEvent} _trigger * @param {Player} player diff --git a/mode/guozhan/src/patch/game.js b/mode/guozhan/src/patch/game.js index f887de4716..41aa75cae3 100644 --- a/mode/guozhan/src/patch/game.js +++ b/mode/guozhan/src/patch/game.js @@ -1,7 +1,7 @@ import { lib, game, ui, get, ai, _status } from "../../../../noname.js"; import { GameEvent, Dialog, Player } from "../../../../noname/library/element/index.js"; import { Game } from "../../../../noname/game/index.js"; -import { showYexingsContent, chooseCharacterContent } from "./content.js"; +import { showYexingsContent, chooseCharacterContent, chooseCharacterOLContent } from "./content.js"; export class GameGuozhan extends Game { /** @@ -356,6 +356,7 @@ export class GameGuozhan extends Game { } var added = false; for (var j of sides) { + // @ts-expect-error 祖宗之法就是这么写的 if (i.isFriendOf(pmap[j])) { added = true; map[j].push(i); @@ -391,30 +392,38 @@ export class GameGuozhan extends Game { }; if (!hiddens.length) { if (map[sides[0]].length > 1) { + // @ts-expect-error 祖宗之法就是这么写的 for (var i of map[sides[0]]) { if (isYe(i)) { + // @ts-expect-error 祖宗之法就是这么写的 game.showYexings(); return; } } } - game.broadcastAll(function (id) { + broadcastAll(function (id) { + // @ts-expect-error 祖宗之法就是这么写的 game.winner_id = id; }, sides[0]); + // @ts-expect-error 祖宗之法就是这么写的 game.checkResult(); } else { var identity = map[sides[0]][0].identity; if (identity == "ye") return; + // @ts-expect-error 祖宗之法就是这么写的 for (var i of map[sides[0]]) { if (isYe(i)) return; } for (var ind = 0; ind < hiddens.length; ind++) { var current = hiddens[ind]; + // @ts-expect-error 祖宗之法就是这么写的 if (isYe(current) || current.getGuozhanGroup(2) != identity || !current.wontYe(null, ind + 1)) return; } - game.broadcastAll(function (id) { + broadcastAll(function (id) { + // @ts-expect-error 祖宗之法就是这么写的 game.winner_id = id; }, sides[0]); + // @ts-expect-error 祖宗之法就是这么写的 game.checkResult(); } } @@ -424,13 +433,17 @@ export class GameGuozhan extends Game { * 检查游戏结果 */ checkResult() { + // @ts-expect-error 祖宗之法就是这么写的 _status.overing = true; + // @ts-expect-error 祖宗之法就是这么写的 var me = game.me._trueMe || game.me; for (var i = 0; i < game.players.length; i++) { game.players[i].showCharacter(2); } + // @ts-expect-error 祖宗之法就是这么写的 var winner = (_status.connectMode ? lib.playerOL : game.playerMap)[game.winner_id]; game.over(winner && winner.isFriendOf(me) ? true : false); + // @ts-expect-error 祖宗之法就是这么写的 game.showIdentity(); } @@ -495,6 +508,7 @@ export class GameGuozhan extends Game { if (filterChoice(list[i], list[j]) || filterChoice(list[j], list[i])) { var mainx = list[i]; var vicex = list[j]; + // @ts-expect-error 祖宗之法就是这么写的 if (!filterChoice(mainx, vicex) || (filterChoice(vicex, mainx) && get.guozhanReverse(mainx, vicex))) { mainx = list[j]; vicex = list[i]; @@ -508,6 +522,7 @@ export class GameGuozhan extends Game { else if (get.is.double(mainx, true).removeArray(get.is.double(vicex, true)).length == 0 || get.is.double(vicex, true).removeArray(get.is.double(mainx, true)).length == 0) // @ts-expect-error 祖宗之法就是这么写的 player.trueIdentity = get.is + // @ts-expect-error 祖宗之法就是这么写的 .double(vicex, true) // @ts-expect-error 祖宗之法就是这么写的 .filter(group => get.is.double(mainx, true).includes(group)) @@ -531,268 +546,7 @@ export class GameGuozhan extends Game { } chooseCharacterOL() { var next = game.createEvent("chooseCharacter"); - next.setContent(function () { - "step 0"; - game.broadcastAll(function () { - ui.arena.classList.add("choose-character"); - for (var i = 0; i < game.players.length; i++) { - game.players[i].classList.add("unseen"); - game.players[i].classList.add("unseen2"); - } - }); - var list = []; - for (var i in lib.characterPack.mode_guozhan) { - if (i.indexOf("gz_shibing") == 0) continue; - if (get.is.jun(i)) continue; - if (lib.config.guozhan_banned && lib.config.guozhan_banned.includes(i)) continue; - list.push(i); - } - _status.characterlist = list.slice(0); - _status.yeidentity = []; - event.list = list.slice(0); - var list2 = []; - var num; - if (lib.configOL.number * 6 > list.length) { - num = 5; - } else if (lib.configOL.number * 7 > list.length) { - num = 6; - } else { - num = 7; - } - var filterButton = function (button) { - if (ui.dialog) { - if (ui.dialog.buttons.length <= 10) { - for (var i = 0; i < ui.dialog.buttons.length; i++) { - if (ui.dialog.buttons[i] != button) { - if ( - lib.element.player.perfectPair.call( - { - name1: button.link, - name2: ui.dialog.buttons[i].link, - }, - true - ) - ) { - button.classList.add("glow2"); - } - } - } - } - } - var filterChoice = function (name1, name2) { - if (_status.separatism) return true; - var group1 = lib.character[name1][1]; - var group2 = lib.character[name2][1]; - var doublex = get.is.double(name1, true); - if (doublex) { - var double = get.is.double(name2, true); - if (double) return doublex.some(group => double.includes(group)); - return doublex.includes(group2); - } else { - if (group1 == "ye") return group2 != "ye"; - var double = get.is.double(name2, true); - if (double) return double.includes(group1); - return group1 == group2; - } - }; - if (!ui.selected.buttons.length) { - return ui.dialog.buttons.some(but => { - if (but == button) return false; - return filterChoice(button.link, but.link); - }); - } - return filterChoice(ui.selected.buttons[0].link, button.link); - }; - list.randomSort(); - for (var i = 0; i < game.players.length; i++) { - list2.push([ - game.players[i], - ["选择角色", [game.getCharacterChoice(list, num), "character"]], - 2, - true, - function () { - return Math.random(); - }, - filterButton, - ]); - } - game.me - .chooseButtonOL(list2, function (player, result) { - if (game.online || player == game.me) player.init(result.links[0], result.links[1], false); - }) - .set("switchToAuto", function () { - _status.event.result = "ai"; - }) - .set("processAI", function () { - var buttons = _status.event.dialog.buttons; - var filterChoice = function (name1, name2) { - if (_status.separatism) return true; - var group1 = lib.character[name1][1]; - var group2 = lib.character[name2][1]; - var doublex = get.is.double(name1, true); - if (doublex) { - var double = get.is.double(name2, true); - if (double) return doublex.some(group => double.includes(group)); - return doublex.includes(group2); - } else { - if (group1 == "ye") return group2 != "ye"; - var double = get.is.double(name2, true); - if (double) return double.includes(group1); - return group1 == group2; - } - }; - for (var i = 0; i < buttons.length - 1; i++) { - for (var j = i + 1; j < buttons.length; j++) { - if (filterChoice(buttons[i].link, buttons[j].link) || filterChoice(buttons[j].link, buttons[i].link)) { - var mainx = buttons[i].link; - var vicex = buttons[j].link; - if (!filterChoice(mainx, vicex) || (filterChoice(vicex, mainx) && get.guozhanReverse(mainx, vicex))) { - mainx = buttons[j].link; - vicex = buttons[i].link; - } - var list = [mainx, vicex]; - return { - bool: true, - links: list, - }; - } - } - } - }); - ("step 1"); - var sort = true, - chosen = [], - chosenCharacter = []; - for (var i in result) { - if (result[i] && result[i].links) { - for (var j = 0; j < result[i].links.length; j++) { - event.list.remove(result[i].links[j]); - } - } - } - for (var i in result) { - if (result[i] == "ai" || !result[i].links || result[i].links.length < 1) { - if (sort) { - sort = false; - event.list.randomSort(); - } - result[i] = [event.list.shift()]; - var group = lib.character[result[i][0]][1]; - for (var j = 0; j < event.list.length; j++) { - if (lib.character[event.list[j]][1] == group) { - result[i].push(event.list[j]); - event.list.splice(j--, 1); - break; - } - } - } else { - result[i] = result[i].links; - } - var name1 = result[i][0], - name2 = result[i][1]; - if (get.is.double(name1, true)) { - if (!get.is.double(name2, true)) lib.playerOL[i].trueIdentity = lib.character[name2][1]; - else if (get.is.double(name1, true).removeArray(get.is.double(name2, true)).length == 0 || get.is.double(name2, true).removeArray(get.is.double(name1, true)).length == 0) { - chosen.push(lib.playerOL[i]); - chosenCharacter.push([name1, name2]); - } else lib.playerOL[i].trueIdentity = get.is.double(name1, true).find(group => get.is.double(name2, true).includes(group)); - } else if (lib.character[name1][1] == "ye" && get.is.double(name2, true)) { - chosen.push(lib.playerOL[i]); - chosenCharacter.push([name1, name2]); - } - } - event.result2 = result; - if (chosen.length) { - for (var i = 0; i < chosen.length; i++) { - var name1 = chosenCharacter[i][0], - name2 = chosenCharacter[i][1], - str, - choice; - if (get.is.double(name1, true)) { - str = "请选择你代表的势力"; - choice = get.is.double(name2, true).filter(group => get.is.double(name1, true).includes(group)); - } - if (lib.character[name1][1] == "ye") { - str = "请选择你的副将代表的势力"; - choice = get.is.double(name2, true); - } - chosen[i] = [ - chosen[i], - [ - str, - [ - choice.map(function (i) { - return ["", "", "group_" + i]; - }), - "vcard", - ], - ], - 1, - true, - ]; - } - game.me - .chooseButtonOL(chosen, function (player, result) { - if (player == game.me) player.trueIdentity = result.links[0][2].slice(6); - }) - .set("switchToAuto", function () { - _status.event.result = "ai"; - }) - .set("processAI", function () { - return { - bool: true, - links: [_status.event.dialog.buttons.randomGet().link], - }; - }); - } else event._result = {}; - ("step 2"); - if (!result) result = {}; - var result2 = event.result2; - game.broadcastAll( - function (result, result2) { - for (var i = 0; i < game.players.length; i++) { - var current = game.players[i], - id = current.playerid; - if (result[id] && !current.name) { - current.init(result[id][0], result[id][1], false); - } - if (result2[id] && result2[id].length) { - current.trueIdentity = result2[id][0][2].slice(6); - } - if (game.players[i] != game.me) { - game.players[i].node.identity.firstChild.innerHTML = "猜"; - game.players[i].node.identity.dataset.color = "unknown"; - game.players[i].node.identity.classList.add("guessing"); - } - game.players[i].hiddenSkills = lib.character[game.players[i].name1][3].slice(0); - var hiddenSkills2 = lib.character[game.players[i].name2][3]; - for (var j = 0; j < hiddenSkills2.length; j++) { - game.players[i].hiddenSkills.add(hiddenSkills2[j]); - } - for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { - if (!lib.skill[game.players[i].hiddenSkills[j]]) { - game.players[i].hiddenSkills.splice(j--, 1); - } - } - game.players[i].group = "unknown"; - game.players[i].sex = "unknown"; - game.players[i].name1 = game.players[i].name; - game.players[i].name = "unknown"; - game.players[i].identity = "unknown"; - game.players[i].node.name.show(); - game.players[i].node.name2.show(); - for (var j = 0; j < game.players[i].hiddenSkills.length; j++) { - game.players[i].addSkillTrigger(game.players[i].hiddenSkills[j], true); - } - } - setTimeout(function () { - ui.arena.classList.remove("choose-character"); - }, 500); - }, - result2, - result - ); - }); + next.setContent(chooseCharacterOLContent); return next; } } From 77c92cea75fc291bd959e85d71e57563fd980ae5 Mon Sep 17 00:00:00 2001 From: Rintim Date: Fri, 21 Mar 2025 16:44:29 +0800 Subject: [PATCH 19/48] pref: divide other modules to separate files(1/3) --- mode/guozhan.js | 321 +----------------------------- mode/guozhan/src/patch/content.js | 144 +++++++++++++- mode/guozhan/src/patch/game.js | 15 ++ mode/guozhan/src/patch/get.js | 270 +++++++++++++++++++++++++ mode/guozhan/src/patch/index.js | 14 +- mode/guozhan/src/patch/player.js | 51 +++++ 6 files changed, 491 insertions(+), 324 deletions(-) create mode 100644 mode/guozhan/src/patch/get.js create mode 100644 mode/guozhan/src/patch/player.js diff --git a/mode/guozhan.js b/mode/guozhan.js index 1e17220a34..fbb9a58081 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -1,6 +1,6 @@ import { lib, game, ui, get, ai, _status } from "../noname.js"; import { start, startBefore, onreinit } from "./guozhan/src/main.js"; -import { gamePatch } from "./guozhan/src/patch/index.js"; +import { gamePatch, getPatch, contentPatch, playerPatch } from "./guozhan/src/patch/index.js"; export const type = "mode"; /** @@ -20835,87 +20835,7 @@ export default () => { ], element: { content: { - hideCharacter() { - game.addVideo("hideCharacter", player, num); - var skills, - log = event.log; - switch (num) { - case 0: - if (log !== false) game.log(player, "暗置了主将" + get.translation(player.name1)); - skills = lib.character[player.name1][3]; - player.name = player.name2; - player.sex = lib.character[player.name2][0]; - player.classList.add("unseen"); - break; - case 1: - if (log !== false) game.log(player, "暗置了副将" + get.translation(player.name2)); - skills = lib.character[player.name2][3]; - player.classList.add("unseen2"); - break; - } - game.broadcast( - function (player, name, sex, num, skills) { - player.name = name; - player.sex = sex; - switch (num) { - case 0: - player.classList.add("unseen"); - break; - case 1: - player.classList.add("unseen2"); - break; - } - for (var i = 0; i < skills.length; i++) { - if (!player.skills.includes(skills[i])) continue; - player.hiddenSkills.add(skills[i]); - player.skills.remove(skills[i]); - } - }, - player, - player.name, - player.sex, - num, - skills - ); - for (var i = 0; i < skills.length; i++) { - if (!player.skills.includes(skills[i])) continue; - player.hiddenSkills.add(skills[i]); - var info = get.info(skills[i]); - if (info.ondisable && info.onremove) { - info.onremove(player); - } - player.skills.remove(skills[i]); - } - player.checkConflict(); - }, - chooseJunlingFor() { - "step 0"; - var list = ["junling1", "junling2", "junling3", "junling4", "junling5", "junling6"]; - list = list.randomGets(event.num).sort(); - for (var i = 0; i < list.length; i++) list[i] = ["军令", "", list[i]]; - var prompt = event.prompt || "选择一张军令牌"; - if (target != undefined && !event.prompt) { - var str = target == player ? "(你)" : ""; - prompt += ",令" + get.translation(target) + str + "选择是否执行"; - } - player.chooseButton([prompt, [list, "vcard"]], true).set("ai", function (button) { - return get.junlingEffect(_status.event.player, button.link[2], _status.event.getParent().target, [], _status.event.player); - }); - "step 1"; - event.result = { - junling: result.links[0][2], - targets: [], - }; - if (result.links[0][2] == "junling1") - player.chooseTarget("选择一名角色,做为若该军令被执行,受到伤害的角色", true).set("ai", function (_target) { - return get.damageEffect(_target, target, player); - }); - "step 2"; - if (result.targets.length) { - player.line(result.targets, "green"); - event.result.targets = result.targets; - } - }, + ...contentPatch, chooseJunlingControl() { "step 0"; var dialog = []; @@ -21153,23 +21073,7 @@ export default () => { }, }, player: { - getGuozhanGroup(num) { - if (this.trueIdentity) { - if (lib.character[this.name1][1] != "ye" || num == 1) return this.trueIdentity; - return "ye"; - } - if (get.is.double(this.name2)) return lib.character[this.name1][1]; - if (num == 1) return lib.character[this.name2][1]; - return lib.character[this.name1][1]; - }, - chooseJunlingFor(target) { - var next = game.createEvent("chooseJunlingFor"); - next.player = this; - next.target = target; - next.num = 2; - next.setContent("chooseJunlingFor"); - return next; - }, + ...playerPatch, chooseJunlingControl(source, junling, targets) { var next = game.createEvent("chooseJunlingControl"); next.player = this; @@ -21706,224 +21610,7 @@ export default () => { }, }, }, - get: { - guozhanReverse(name1, name2) { - if (get.is.double(name2)) return false; - if (["gz_xunyou", "gz_lvfan", "gz_liubei"].includes(name2)) return true; - if (name1 == "gz_re_xushu") return true; - if (name2 == "gz_dengai") return lib.character[name1][2] % 2 == 1; - if (["gz_sunce", "gz_jiangwei"].includes(name1)) return name2 == "gz_zhoutai" || lib.character[name2][2] % 2 == 1; - return false; - }, - guozhanRank(name, player) { - if (name.indexOf("gz_shibing") == 0) return -1; - if (name.indexOf("gz_jun_") == 0) return 7; - if (player) { - var skills = lib.character[name][3].slice(0); - for (var i = 0; i < skills.length; i++) { - if (lib.skill[skills[i]].limited && player.awakenedSkills.includes(skills[i])) return skills.length - 1; - } - } - if (_status._aozhan) { - for (var i in lib.aozhanRank) { - if (lib.aozhanRank[i].includes(name)) return parseInt(i); - } - } - for (var i in lib.guozhanRank) { - if (lib.guozhanRank[i].includes(name)) return parseInt(i); - } - return 0; - }, - junlingEffect(source, junling, performer, targets, viewer) { - var att1 = get.attitude(viewer, source), - att2 = get.attitude(viewer, performer); - var eff1 = 0, - eff2 = 0; - switch (junling) { - case "junling1": - if ( - !targets.length && - game.countPlayer(function (current) { - return get.damageEffect(viewer, current, viewer) > 0; - }) - ) - eff1 = 2; - else { - if (get.damageEffect(targets[0], performer, source) >= 0) eff1 = 2; - else eff1 = -2; - if (get.damageEffect(targets[0], source, performer) >= 0) eff2 = 2; - else eff2 = -2; - } - break; - case "junling2": - if (performer.countCards("he")) { - eff1 = 1; - eff2 = 0; - } else { - eff1 = 2; - eff2 = -1; - } - break; - case "junling3": - if (performer.hp == 1 && !performer.hasSkillTag("save", true)) eff2 = -5; - else { - if (performer == viewer) { - if (performer.hasSkillTag("maihp", true)) eff2 = 3; - else eff2 = -2; - } else { - if (performer.hasSkillTag("maihp", false)) eff2 = 3; - else eff2 = -2; - } - } - break; - case "junling4": - eff1 = 0; - eff2 = -2; - break; - case "junling5": - var td = performer.isTurnedOver(); - if (td) { - if (performer == viewer) { - if (_status.currentPhase == performer && performer.hasSkill("jushou")) eff2 = -3; - else eff2 = 3; - } else eff2 = 3; - } else { - if (performer == viewer) { - if (performer.hasSkillTag("noturn", true)) eff2 = 0; - else eff2 = -3; - } else { - if (performer.hasSkillTag("noturn", false)) eff2 = 0; - else eff2 = -3; - } - } - break; - case "junling6": - if (performer.countCards("h") > 1) eff2 += 1 - performer.countCards("h"); - if (performer.countCards("e") > 1) eff2 += 1 - performer.countCards("e"); - break; - } - return Math.sign(att1) * eff1 + Math.sign(att2) * eff2; - }, - realAttitude(from, to, difficulty, toidentity) { - var getIdentity = function (player) { - if (player.isUnseen()) { - if (!player.wontYe()) return "ye"; - return player.getGuozhanGroup(0); - } - return player.identity; - }; - var fid = getIdentity(from); - if (fid == toidentity && toidentity != "ye") { - return 4 + difficulty; - } - if (from.identity == "unknown" && fid == toidentity) { - if (from.wontYe()) return 4 + difficulty; - } - var groups = []; - var map = {}, - sides = [], - pmap = _status.connectMode ? lib.playerOL : game.playerMap, - player; - for (var i of game.players) { - if (i.identity == "unknown") continue; - var added = false; - for (var j of sides) { - if (i.isFriendOf(pmap[j])) { - added = true; - map[j].push(i); - if (i == this) player = j; - break; - } - } - if (!added) { - map[i.playerid] = [i]; - sides.push(i.playerid); - if (i == this) player = i.playerid; - } - } - for (var i in map) { - var num = map[i].length; - groups.push(num); - } - var max = Math.max.apply(this, groups); - if (max <= 1) return -3; - var from_p; - if (from.identity == "unknown" && from.wontYe()) from_p = get.population(fid); - else - from_p = game.countPlayer(function (current) { - return current.isFriendOf(from); - }); - var to_p = game.countPlayer(function (current) { - return current.isFriendOf(to); - }); - if (to.identity == "ye") to_p += 1.5; - - if (to_p >= max) return -5; - if (from_p >= max) return -2 - to_p; - if (max >= game.players.length / 2) { - if (to_p <= from_p) { - return 0.5; - } - return 0; - } - if (to_p < max - 1) return 0; - return -0.5; - }, - rawAttitude(from, to) { - var getIdentity = function (player) { - if (player.isUnseen()) { - if (!player.wontYe()) return "ye"; - return player.getGuozhanGroup(0); - } - return player.identity; - }; - var fid = getIdentity(from), - tid = getIdentity(to); - if (to.identity == "unknown" && game.players.length == 2) return -5; - if (_status.currentPhase == from && from.ai.tempIgnore && from.ai.tempIgnore.includes(to) && to.identity == "unknown" && (!from.storage.zhibi || !from.storage.zhibi.includes(to))) return 0; - var difficulty = 0; - if (to == game.me) difficulty = (2 - get.difficulty()) * 1.5; - if (from == to) return 5 + difficulty; - if (from.isFriendOf(to)) return 5 + difficulty; - if (from.identity == "unknown" && fid == to.identity) { - if (from.wontYe()) return 4 + difficulty; - } - var att = get.realAttitude(from, to, difficulty, tid); - if (from.storage.zhibi && from.storage.zhibi.includes(to)) { - return att; - } - if (to.ai.shown >= 0.5) return att * to.ai.shown; - - var nshown = 0; - for (var i = 0; i < game.players.length; i++) { - if (game.players[i] != from && game.players[i].identity == "unknown") { - nshown++; - } - } - if (to.ai.shown == 0) { - if (nshown >= game.players.length / 2 && att >= 0) { - return 0; - } - return Math.min(0, Math.random() - 0.5) + difficulty; - } - if (to.ai.shown >= 0.2) { - if (att > 2) { - return Math.max(0, Math.random() - 0.5) + difficulty; - } - if (att >= 0) { - return 0; - } - return Math.min(0, Math.random() - 0.7) + difficulty; - } - if (att > 2) { - return Math.max(0, Math.random() - 0.7) + difficulty; - } - if (att >= 0) { - return Math.min(0, Math.random() - 0.3) + difficulty; - } - return Math.min(0, Math.random() - 0.5) + difficulty; - }, - }, + get: getPatch, help: { 国战模式: '
声明
  • 以下所有规则均为根据公开爆料整理,经村规改动后制定的临时规则。不代表任何官方意见。请以后续发布的官方规则作为标准。
' + diff --git a/mode/guozhan/src/patch/content.js b/mode/guozhan/src/patch/content.js index 4481e54c68..322337d863 100644 --- a/mode/guozhan/src/patch/content.js +++ b/mode/guozhan/src/patch/content.js @@ -1,11 +1,15 @@ -import { lib, game as _game, ui, get, ai, _status } from "../../../../noname.js"; +import { lib, game as _game, ui, get as _get, ai, _status } from "../../../../noname.js"; import { GameEvent, Dialog, Player, Control, Button, Character } from "../../../../noname/library/element/index.js"; -import { GameGuozhan, broadcastAll } from "./game.js"; +import { GameGuozhan, broadcast, broadcastAll } from "./game.js"; +import { GetGuozhan } from "./get.js"; import { delay } from "../../../../noname/util/index.js"; /** @type {GameGuozhan} */ // @ts-expect-error 类型就是这么定的 const game = _game; +/** @type {GetGuozhan} */ +// @ts-expect-error 类型就是这么定的 +const get = _get; const html = String.raw; /** @@ -622,12 +626,15 @@ export async function chooseCharacterOLContent(event, _trigger, _player) { const name2 = chosenCharacter[i][1]; let str; let choice; + // @ts-expect-error 祖宗之法就是这么写的 if (get.is.double(name1, true)) { str = "请选择你代表的势力"; + // @ts-expect-error 祖宗之法就是这么写的 choice = get.is.double(name2, true).filter(group => get.is.double(name1, true).includes(group)); } if (lib.character[name1][1] == "ye") { str = "请选择你的副将代表的势力"; + // @ts-expect-error 祖宗之法就是这么写的 choice = get.is.double(name2, true); } chosen[i] = [chosen[i], [str, [choice.map(i => ["", "", "group_" + i]), "vcard"]], 1, true]; @@ -699,7 +706,7 @@ export async function chooseCharacterOLContent(event, _trigger, _player) { } delay(500).then(() => { - ui.arena.classList.remove("choose-character") + ui.arena.classList.remove("choose-character"); }); }, chooseCharacterResult, @@ -802,7 +809,6 @@ export async function chooseCharacterOLContent(event, _trigger, _player) { let mainx = button1.link; let vicex = button2.link; - // @ts-expect-error 祖宗之法就是这么写的 if (!filterChoice(mainx, vicex) || (filterChoice(vicex, mainx) && get.guozhanReverse(mainx, vicex))) { mainx = button2.link; vicex = button1.link; @@ -1017,3 +1023,133 @@ export async function showYexingsContent(event, _trigger, player) { break; } } + +/** + * @param {GameEvent} event + * @param {GameEvent} _trigger + * @param {Player} player + */ +export async function hideCharacter(event, _trigger, player) { + const { num } = event; + + game.addVideo("hideCharacter", player, num); + + const log = Reflect.get(event, "log"); + let skills; + switch (num) { + case 0: + if (log !== false) game.log(player, "暗置了主将" + get.translation(player.name1)); + skills = lib.character[player.name1][3]; + player.name = player.name2; + player.sex = lib.character[player.name2][0]; + player.classList.add("unseen"); + break; + case 1: + if (log !== false) game.log(player, "暗置了副将" + get.translation(player.name2)); + skills = lib.character[player.name2][3]; + player.classList.add("unseen2"); + break; + // 为skills赋值,避免报错 + default: + skills = []; + break; + } + + broadcast( + (player, name, sex, num, skills) => { + player.name = name; + player.sex = sex; + switch (num) { + case 0: + player.classList.add("unseen"); + break; + case 1: + player.classList.add("unseen2"); + break; + } + for (var i = 0; i < skills.length; i++) { + if (!player.skills.includes(skills[i])) continue; + player.hiddenSkills.add(skills[i]); + player.skills.remove(skills[i]); + } + }, + player, + player.name, + player.sex, + num, + skills + ); + + for (let i = 0; i < skills.length; ++i) { + if (!player.skills.includes(skills[i])) { + continue; + } + + player.hiddenSkills.add(skills[i]); + + const info = get.info(skills[i]); + if (info.ondisable && info.onremove) { + // @ts-expect-error 祖宗之法就是这么写的 + info.onremove(player); + } + + player.skills.remove(skills[i]); + } + + player.checkConflict(); +} + +/** + * @param {GameEvent} event + * @param {GameEvent} _trigger + * @param {Player} player + */ +export async function chooseJunlingFor(event, _trigger, player) { + const { num, target } = event; + let prompt = Reflect.get(event, "prompt", event); + + let junlingNames = ["junling1", "junling2", "junling3", "junling4", "junling5", "junling6"]; + junlingNames = junlingNames.randomGets(event.num).sort(); + + const junlings = junlingNames.map(name => ["军令", "", name]); + + if (target != undefined && !prompt) { + const selfPrompt = target == player ? "(你)" : ""; + prompt = `选择一张军令牌,令${get.translation(target)}${selfPrompt}选择是否执行`; + } + + const chooseResult = await player + .chooseButton([prompt, [junlings, "vcard"]], true) + .set("ai", button => { + // @ts-expect-error 祖宗之法就是这么写的 + return get.junlingEffect(get.player(), button.link[2], get.event()?.getParent()?.target, [], get.player()); + }) + .forResultLinks(); + + const result = { + junling: chooseResult[0][2], + /** @type {Player[]} */ + targets: [], + }; + + if (result.junling == "junling1") { + /** @type {Player[]} */ + // @ts-expect-error 祖宗之法就是这么写的 + const targets = await player + .chooseTarget("选择一名角色,做为若该军令被执行,受到伤害的角色", true) + .set("ai", other => get.damageEffect(other, target, player)) + .forResultTargets(); + + if (targets.length > 0) { + player.line(targets, "green"); + result.targets = targets; + } + } + + Reflect.set(event, "result", result); +} + +export default Object.freeze({ + hideCharacter, + chooseJunlingFor, +}); diff --git a/mode/guozhan/src/patch/game.js b/mode/guozhan/src/patch/game.js index 41aa75cae3..dd27a05ac8 100644 --- a/mode/guozhan/src/patch/game.js +++ b/mode/guozhan/src/patch/game.js @@ -544,11 +544,26 @@ export class GameGuozhan extends Game { } } } + chooseCharacterOL() { var next = game.createEvent("chooseCharacter"); next.setContent(chooseCharacterOLContent); return next; } + + /** + * 类型兼容版本 + * + * @param {string} type + * @param {Player?} player + * @param {any} [content] + * @returns + */ + // @ts-expect-error 祖宗之法就是这么写的 + addVideo(type, player, content) { + // @ts-expect-error 祖宗之法就是这么写的 + return super.addVideo(type, player, content); + } } /** diff --git a/mode/guozhan/src/patch/get.js b/mode/guozhan/src/patch/get.js new file mode 100644 index 0000000000..69ff2e3444 --- /dev/null +++ b/mode/guozhan/src/patch/get.js @@ -0,0 +1,270 @@ +// @ts-nocheck + +import { lib, game, ui, get, ai, _status } from "../../../../noname.js" +import { GameEvent, Dialog, Player } from "../../../../noname/library/element/index.js"; +import { Get } from "../../../../noname/get/index.js"; +import { showYexingsContent, chooseCharacterContent, chooseCharacterOLContent } from "./content.js"; + +export class GetGuozhan extends Get { + /** + * > ?.? + * + * @param {*} source + * @param {*} junling + * @param {*} performer + * @param {*} targets + * @param {*} viewer + * @returns + */ + junlingEffect(source, junling, performer, targets, viewer) { + var att1 = get.attitude(viewer, source), + att2 = get.attitude(viewer, performer); + var eff1 = 0, + eff2 = 0; + switch (junling) { + case "junling1": + if ( + !targets.length && + game.countPlayer(function (current) { + return get.damageEffect(viewer, current, viewer) > 0; + }) + ) + eff1 = 2; + else { + if (get.damageEffect(targets[0], performer, source) >= 0) eff1 = 2; + else eff1 = -2; + if (get.damageEffect(targets[0], source, performer) >= 0) eff2 = 2; + else eff2 = -2; + } + break; + case "junling2": + if (performer.countCards("he")) { + eff1 = 1; + eff2 = 0; + } else { + eff1 = 2; + eff2 = -1; + } + break; + case "junling3": + if (performer.hp == 1 && !performer.hasSkillTag("save", true)) eff2 = -5; + else { + if (performer == viewer) { + if (performer.hasSkillTag("maihp", true)) eff2 = 3; + else eff2 = -2; + } else { + if (performer.hasSkillTag("maihp", false)) eff2 = 3; + else eff2 = -2; + } + } + break; + case "junling4": + eff1 = 0; + eff2 = -2; + break; + case "junling5": + var td = performer.isTurnedOver(); + if (td) { + if (performer == viewer) { + // @ts-expect-error 祖宗之法就是这么写的 + if (_status.currentPhase == performer && performer.hasSkill("jushou")) eff2 = -3; + else eff2 = 3; + } else eff2 = 3; + } else { + if (performer == viewer) { + if (performer.hasSkillTag("noturn", true)) eff2 = 0; + else eff2 = -3; + } else { + if (performer.hasSkillTag("noturn", false)) eff2 = 0; + else eff2 = -3; + } + } + break; + case "junling6": + if (performer.countCards("h") > 1) eff2 += 1 - performer.countCards("h"); + if (performer.countCards("e") > 1) eff2 += 1 - performer.countCards("e"); + break; + } + return Math.sign(att1) * eff1 + Math.sign(att2) * eff2; + } + + /** + * > ??.? + * + * @param {string} name1 + * @param {string} name2 + * @returns {boolean} + */ + guozhanReverse(name1, name2) { + if (get.is.double(name2)) return false; + if (["gz_xunyou", "gz_lvfan", "gz_liubei"].includes(name2)) return true; + if (name1 == "gz_re_xushu") return true; + if (name2 == "gz_dengai") return lib.character[name1][2] % 2 == 1; + if (["gz_sunce", "gz_jiangwei"].includes(name1)) return name2 == "gz_zhoutai" || lib.character[name2][2] % 2 == 1; + return false; + } + + /** + * 获取武将的等级 + * + * @param {string} name + * @param {Player} player + * @returns + */ + guozhanRank(name, player) { + if (name.indexOf("gz_shibing") == 0) return -1; + if (name.indexOf("gz_jun_") == 0) return 7; + if (player) { + var skills = lib.character[name][3].slice(0); + for (var i = 0; i < skills.length; i++) { + if (lib.skill[skills[i]].limited && player.awakenedSkills.includes(skills[i])) return skills.length - 1; + } + } + if (_status._aozhan) { + for (var i in lib.aozhanRank) { + if (lib.aozhanRank[i].includes(name)) return parseInt(i); + } + } + for (var i in lib.guozhanRank) { + if (lib.guozhanRank[i].includes(name)) return parseInt(i); + } + return 0; + } + + /** + * > ?.?? + * + * @param {Player} from + * @param {Player} to + * @param {number} difficulty + * @param {string} toidentity + * @returns + */ + realAttitude(from, to, difficulty, toidentity) { + var getIdentity = function (player) { + if (player.isUnseen()) { + if (!player.wontYe()) return "ye"; + return player.getGuozhanGroup(0); + } + return player.identity; + }; + var fid = getIdentity(from); + if (fid == toidentity && toidentity != "ye") { + return 4 + difficulty; + } + if (from.identity == "unknown" && fid == toidentity) { + if (from.wontYe()) return 4 + difficulty; + } + var groups = []; + var map = {}, + sides = [], + pmap = _status.connectMode ? lib.playerOL : game.playerMap, + player; + for (var i of game.players) { + if (i.identity == "unknown") continue; + var added = false; + for (var j of sides) { + if (i.isFriendOf(pmap[j])) { + added = true; + map[j].push(i); + if (i == this) player = j; + break; + } + } + if (!added) { + map[i.playerid] = [i]; + sides.push(i.playerid); + if (i == this) player = i.playerid; + } + } + for (var i in map) { + var num = map[i].length; + groups.push(num); + } + var max = Math.max.apply(this, groups); + if (max <= 1) return -3; + var from_p; + if (from.identity == "unknown" && from.wontYe()) from_p = get.population(fid); + else + from_p = game.countPlayer(function (current) { + return current.isFriendOf(from); + }); + var to_p = game.countPlayer(function (current) { + return current.isFriendOf(to); + }); + if (to.identity == "ye") to_p += 1.5; + + if (to_p >= max) return -5; + if (from_p >= max) return -2 - to_p; + if (max >= game.players.length / 2) { + if (to_p <= from_p) { + return 0.5; + } + return 0; + } + if (to_p < max - 1) return 0; + return -0.5; + } + + /** + * > ??.?? + * + * @param {Player} from + * @param {Player} to + * @returns + */ + rawAttitude(from, to) { + var getIdentity = function (player) { + if (player.isUnseen()) { + if (!player.wontYe()) return "ye"; + return player.getGuozhanGroup(0); + } + return player.identity; + }; + var fid = getIdentity(from), + tid = getIdentity(to); + if (to.identity == "unknown" && game.players.length == 2) return -5; + if (_status.currentPhase == from && from.ai.tempIgnore && from.ai.tempIgnore.includes(to) && to.identity == "unknown" && (!from.storage.zhibi || !from.storage.zhibi.includes(to))) return 0; + var difficulty = 0; + if (to == game.me) difficulty = (2 - get.difficulty()) * 1.5; + if (from == to) return 5 + difficulty; + if (from.isFriendOf(to)) return 5 + difficulty; + if (from.identity == "unknown" && fid == to.identity) { + if (from.wontYe()) return 4 + difficulty; + } + var att = get.realAttitude(from, to, difficulty, tid); + if (from.storage.zhibi && from.storage.zhibi.includes(to)) { + return att; + } + if (to.ai.shown >= 0.5) return att * to.ai.shown; + + var nshown = 0; + for (var i = 0; i < game.players.length; i++) { + if (game.players[i] != from && game.players[i].identity == "unknown") { + nshown++; + } + } + if (to.ai.shown == 0) { + if (nshown >= game.players.length / 2 && att >= 0) { + return 0; + } + return Math.min(0, Math.random() - 0.5) + difficulty; + } + if (to.ai.shown >= 0.2) { + if (att > 2) { + return Math.max(0, Math.random() - 0.5) + difficulty; + } + if (att >= 0) { + return 0; + } + return Math.min(0, Math.random() - 0.7) + difficulty; + } + if (att > 2) { + return Math.max(0, Math.random() - 0.7) + difficulty; + } + if (att >= 0) { + return Math.min(0, Math.random() - 0.3) + difficulty; + } + return Math.min(0, Math.random() - 0.5) + difficulty; + } +} diff --git a/mode/guozhan/src/patch/index.js b/mode/guozhan/src/patch/index.js index a3d136e663..ab50130e15 100644 --- a/mode/guozhan/src/patch/index.js +++ b/mode/guozhan/src/patch/index.js @@ -1,14 +1,22 @@ import { GameGuozhan } from "./game.js"; +import { GetGuozhan } from "./get.js"; +import { PlayerGuozhan } from "./player.js"; +import ContentGuozhan from "./content.js"; export const gamePatch = _generateExtraFuncions(GameGuozhan.prototype); +export const getPatch = _generateExtraFuncions(GetGuozhan.prototype); +export const playerPatch = _generateExtraFuncions(PlayerGuozhan.prototype); +export const contentPatch = ContentGuozhan; /** * 一个非常申必的生成额外函数的函数 - * - * @param {any} prototype - * @returns {object} + * + * @template {object} T + * @param {T} prototype + * @returns {{ [K in T]: T[K] }} */ function _generateExtraFuncions(prototype) { + /** @type {object} */ const result = {}; const names = Object.getOwnPropertyNames(prototype); diff --git a/mode/guozhan/src/patch/player.js b/mode/guozhan/src/patch/player.js new file mode 100644 index 0000000000..58a692680b --- /dev/null +++ b/mode/guozhan/src/patch/player.js @@ -0,0 +1,51 @@ +import { lib, game, ui, get, ai, _status } from "../../../../noname.js"; +import { GameEvent, Dialog, Player } from "../../../../noname/library/element/index.js"; + +export class PlayerGuozhan extends Player { + /** + * @type {string} + */ + trueIdentity; + + /** + * 获取玩家的势力 + * + * @param {Number} [num = 0] - 根据哪张武将牌返回势力,`0`为主将,`1`为副将(默认为0) + * @returns {string} + */ + getGuozhanGroup(num = 0) { + if (this.trueIdentity) { + if (lib.character[this.name1][1] != "ye" || num == 1) { + return this.trueIdentity; + } + return "ye"; + } + if (get.is.double(this.name2)) { + return lib.character[this.name1].group; + } + if (num == 1) { + return lib.character[this.name2].group; + } + return lib.character[this.name1].group; + } + + /** + * 选择军令 + * + * @param {Player} target + * @returns + */ + chooseJunlingFor(target) { + const next = game.createEvent("chooseJunlingFor"); + + // @ts-expect-error 类型就是这么写的 + next.player = this; + next.target = target; + next.num = 2; + + // @ts-expect-error 类型就是这么写的 + next.setContent("chooseJunlingFor"); + + return next; + } +} From f91c14b8d862340b45ca0a63103ef384f49b191e Mon Sep 17 00:00:00 2001 From: Rintim Date: Mon, 7 Apr 2025 14:40:35 +0800 Subject: [PATCH 20/48] feat: use vue format to rewrite help. --- mode/guozhan.js | 10 ++-------- mode/guozhan/src/help/App.js | 35 ++++++++++++++++++++++++++++++++++ mode/guozhan/src/help/index.js | 5 +++++ 3 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 mode/guozhan/src/help/App.js create mode 100644 mode/guozhan/src/help/index.js diff --git a/mode/guozhan.js b/mode/guozhan.js index fbb9a58081..d9a181b8e7 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -1,6 +1,7 @@ import { lib, game, ui, get, ai, _status } from "../noname.js"; import { start, startBefore, onreinit } from "./guozhan/src/main.js"; import { gamePatch, getPatch, contentPatch, playerPatch } from "./guozhan/src/patch/index.js"; +import help from "./guozhan/src/help/index.js"; export const type = "mode"; /** @@ -21611,13 +21612,6 @@ export default () => { }, }, get: getPatch, - help: { - 国战模式: - '
声明
  • 以下所有规则均为根据公开爆料整理,经村规改动后制定的临时规则。不代表任何官方意见。请以后续发布的官方规则作为标准。
' + - '
双势力武将
  • 双势力武将牌可以和野心家武将牌/包含势力单武将牌/含有重叠势力的其他双势力武将牌组合,若你的主将为双势力武将,则:若你的副将为单势力武将牌,你的势力视为此势力;若你的副将为双势力武将,你的势力视为两张武将牌上的重叠势力(若重叠势力不止一个则需在游戏开始时选择一个作为自己的势力);野心家武将牌为主将,双势力武将牌为副将时,游戏开始时需选择一个副将所含势力作为副将的势力。
  • 变更副将时,可以选择包含原势力的双势力武将牌。左慈发动〖役鬼〗时,可以使用双势力武将牌同时指定两个不同势力的角色为目标。
  • 特殊地,“冈崎汐”作为多势力武将牌,结算流程和规则与其他双势力武将相同。
' + - '
野心家武将
  • 野心家武将只能放在主将位置。副将可以为任意非野心家武将牌。
  • 选择了野心家武将牌的角色(以下简称“野心家角色”)仅明置副将时,若副将为单势力武将牌,则势力暂时视为与该武将牌相同。若副将为双势力武将牌,则势力视为游戏开始时选择的副将代表的势力。
  • 野心家角色明置主将时,其势力改为野心家。若其是首次明置该武将牌,则其获得一个“野心家”标记。
  • “野心家”标记可以当做“先驱”标记,“阴阳鱼”标记或是“珠联璧合”标记使用。当同时拥有两种标记时,优先弃置原装标记,下次发动时才弃置“野心家”标记。
  • 野心家角色变更副将时,若其主将未明置过,则按照副将的势力进行变更。若主将已经明置过,则可以选择所有的非野心家武将牌。左慈发动〖役鬼〗时,可以使用野心家武将牌同时指定所有势力的角色为目标。' + - "
  • 当场上触发了胜利条件时,若这些角色中存在未明置过主将的野心家角色,则这些野心家角色选择是否“暴露野心”。若无人选择“是”且场上存在非野心家角色存活,则所有非野心家角色胜利,野心家角色失败。若有人选择“是”,则这些角色明置主将,然后选择是否发起“拉拢人心”。
  • 选择发起“拉拢人心”的野心家角色选择一个新的势力作为自己的势力,弃置“野心家”标记,令所有其他非野心家角色且非君主且非已“结盟”角色依次选择是否和该野心家角色“结盟”。选择“是”的角色将势力改为和该野心家势力相同。此次“拉拢人心”对所有其他角色询问结束后,所有选择“否”的角色将手牌摸至四张并回复1点体力。
" + - '
纵横捭阖
  • 当一名角色对目标角色发动具有拥有“纵横”衍生技的技能时,其可以令对方获得“纵横”衍生技直到其下回合结束。
', - }, + help, }; }; diff --git a/mode/guozhan/src/help/App.js b/mode/guozhan/src/help/App.js new file mode 100644 index 0000000000..b0d162a462 --- /dev/null +++ b/mode/guozhan/src/help/App.js @@ -0,0 +1,35 @@ +import html from "../../../../game/dedent.js"; + +export default { + template: html` +
声明
+
    +
  • 以下所有规则均为根据公开爆料整理,经村规改动后制定的临时规则。不代表任何官方意见。请以后续发布的官方规则作为标准。
  • +
+ +
双势力武将
+
    +
  • 双势力武将牌可以和野心家武将牌/包含势力单武将牌/含有重叠势力的其他双势力武将牌组合,若你的主将为双势力武将,则:若你的副将为单势力武将牌,你的势力视为此势力;若你的副将为双势力武将,你的势力视为两张武将牌上的重叠势力(若重叠势力不止一个则需在游戏开始时选择一个作为自己的势力);野心家武将牌为主将,双势力武将牌为副将时,游戏开始时需选择一个副将所含势力作为副将的势力。
  • +
  • 变更副将时,可以选择包含原势力的双势力武将牌。左慈发动〖役鬼〗时,可以使用双势力武将牌同时指定两个不同势力的角色为目标。
  • +
  • 特殊地,“冈崎汐”作为多势力武将牌,结算流程和规则与其他双势力武将相同。
  • +
+ +
野心家武将
+
    +
  • 野心家武将只能放在主将位置。副将可以为任意非野心家武将牌。
  • +
  • 选择了野心家武将牌的角色(以下简称“野心家角色”)仅明置副将时,若副将为单势力武将牌,则势力暂时视为与该武将牌相同。若副将为双势力武将牌,则势力视为游戏开始时选择的副将代表的势力。
  • +
  • 野心家角色明置主将时,其势力改为野心家。若其是首次明置该武将牌,则其获得一个“野心家”标记。
  • +
  • “野心家”标记可以当做“先驱”标记,“阴阳鱼”标记或是“珠联璧合”标记使用。当同时拥有两种标记时,优先弃置原装标记,下次发动时才弃置“野心家”标记。
  • +
  • 野心家角色变更副将时,若其主将未明置过,则按照副将的势力进行变更。若主将已经明置过,则可以选择所有的非野心家武将牌。左慈发动〖役鬼〗时,可以使用野心家武将牌同时指定所有势力的角色为目标。
  • +
  • 当场上触发了胜利条件时,若这些角色中存在未明置过主将的野心家角色,则这些野心家角色选择是否“暴露野心”。若无人选择“是”且场上存在非野心家角色存活,则所有非野心家角色胜利,野心家角色失败。若有人选择“是”,则这些角色明置主将,然后选择是否发起“拉拢人心”。
  • +
  • 选择发起“拉拢人心”的野心家角色选择一个新的势力作为自己的势力,弃置“野心家”标记,令所有其他非野心家角色且非君主且非已“结盟”角色依次选择是否和该野心家角色“结盟”。选择“是”的角色将势力改为和该野心家势力相同。此次“拉拢人心”对所有其他角色询问结束后,所有选择“否”的角色将手牌摸至四张并回复1点体力。
  • +
+ +
纵横捭阖
+
    +
  • 当一名角色对目标角色发动具有拥有“纵横”衍生技的技能时,其可以令对方获得“纵横”衍生技直到其下回合结束。
  • +
+ `, + + setup() {}, +}; diff --git a/mode/guozhan/src/help/index.js b/mode/guozhan/src/help/index.js new file mode 100644 index 0000000000..463c76d0f7 --- /dev/null +++ b/mode/guozhan/src/help/index.js @@ -0,0 +1,5 @@ +import App from "./App.js"; + +export default { + 国战模式: App, +} From e5d893a03b7e6093e78efe2dc081e62ac33cb140 Mon Sep 17 00:00:00 2001 From: Rintim Date: Mon, 7 Apr 2025 14:48:52 +0800 Subject: [PATCH 21/48] refactor: use some vue features. --- mode/guozhan/src/help/App.js | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/mode/guozhan/src/help/App.js b/mode/guozhan/src/help/App.js index b0d162a462..062bd1403d 100644 --- a/mode/guozhan/src/help/App.js +++ b/mode/guozhan/src/help/App.js @@ -2,20 +2,20 @@ import html from "../../../../game/dedent.js"; export default { template: html` -
声明
-
    +
    声明
    +
    • 以下所有规则均为根据公开爆料整理,经村规改动后制定的临时规则。不代表任何官方意见。请以后续发布的官方规则作为标准。
    -
    双势力武将
    -
      +
      双势力武将
      +
      • 双势力武将牌可以和野心家武将牌/包含势力单武将牌/含有重叠势力的其他双势力武将牌组合,若你的主将为双势力武将,则:若你的副将为单势力武将牌,你的势力视为此势力;若你的副将为双势力武将,你的势力视为两张武将牌上的重叠势力(若重叠势力不止一个则需在游戏开始时选择一个作为自己的势力);野心家武将牌为主将,双势力武将牌为副将时,游戏开始时需选择一个副将所含势力作为副将的势力。
      • 变更副将时,可以选择包含原势力的双势力武将牌。左慈发动〖役鬼〗时,可以使用双势力武将牌同时指定两个不同势力的角色为目标。
      • 特殊地,“冈崎汐”作为多势力武将牌,结算流程和规则与其他双势力武将相同。
      -
      野心家武将
      -
        +
        野心家武将
        +
        • 野心家武将只能放在主将位置。副将可以为任意非野心家武将牌。
        • 选择了野心家武将牌的角色(以下简称“野心家角色”)仅明置副将时,若副将为单势力武将牌,则势力暂时视为与该武将牌相同。若副将为双势力武将牌,则势力视为游戏开始时选择的副将代表的势力。
        • 野心家角色明置主将时,其势力改为野心家。若其是首次明置该武将牌,则其获得一个“野心家”标记。
        • @@ -25,11 +25,24 @@ export default {
        • 选择发起“拉拢人心”的野心家角色选择一个新的势力作为自己的势力,弃置“野心家”标记,令所有其他非野心家角色且非君主且非已“结盟”角色依次选择是否和该野心家角色“结盟”。选择“是”的角色将势力改为和该野心家势力相同。此次“拉拢人心”对所有其他角色询问结束后,所有选择“否”的角色将手牌摸至四张并回复1点体力。
        -
        纵横捭阖
        -
          +
          纵横捭阖
          +
          • 当一名角色对目标角色发动具有拥有“纵横”衍生技的技能时,其可以令对方获得“纵横”衍生技直到其下回合结束。
          `, - setup() {}, + setup() { + const titleStyle = { + margin: "10px" + }; + + const listStyle = { + marginTop: "0" + }; + + return { + titleStyle, + listStyle + } + }, }; From 470ba8fa31b45e4f5f0c5df2f063b60967a825be Mon Sep 17 00:00:00 2001 From: Rintim Date: Tue, 8 Apr 2025 09:09:47 +0800 Subject: [PATCH 22/48] pref: rewrite unperfectly. --- mode/guozhan.js | 1308 +---------------------------- mode/guozhan/src/card/index.js | 36 + mode/guozhan/src/info/index.js | 4 + mode/guozhan/src/info/pile.js | 467 ++++++++++ mode/guozhan/src/info/rank.js | 21 + mode/guozhan/src/patch/content.js | 328 +++++++- mode/guozhan/src/patch/player.js | 651 +++++++++++++- mode/guozhan/src/skill/index.js | 0 8 files changed, 1512 insertions(+), 1303 deletions(-) create mode 100644 mode/guozhan/src/card/index.js create mode 100644 mode/guozhan/src/info/index.js create mode 100644 mode/guozhan/src/info/pile.js create mode 100644 mode/guozhan/src/info/rank.js create mode 100644 mode/guozhan/src/skill/index.js diff --git a/mode/guozhan.js b/mode/guozhan.js index d9a181b8e7..7bed7c5a1e 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -1,6 +1,8 @@ import { lib, game, ui, get, ai, _status } from "../noname.js"; import { start, startBefore, onreinit } from "./guozhan/src/main.js"; import { gamePatch, getPatch, contentPatch, playerPatch } from "./guozhan/src/patch/index.js"; +import * as info from "./guozhan/src/info/index.js"; +import card from "./guozhan/src/card/index.js"; import help from "./guozhan/src/help/index.js"; export const type = "mode"; @@ -13,61 +15,10 @@ export default () => { startBefore, onreinit, start, - card: { - junling1: { - type: "junling", - vanish: true, - derivation: "guozhan", - }, - junling2: { - type: "junling", - vanish: true, - derivation: "guozhan", - }, - junling3: { - type: "junling", - vanish: true, - derivation: "guozhan", - }, - junling4: { - type: "junling", - vanish: true, - derivation: "guozhan", - }, - junling5: { - type: "junling", - vanish: true, - derivation: "guozhan", - }, - junling6: { - type: "junling", - vanish: true, - derivation: "guozhan", - }, - zhulian_card: { - cardimage: "wuzhong", - }, - }, - aozhanRank: { - 8: ["gz_ol_lisu", "gz_panjun"], - 7: ["gz_zhongyan", "gz_yangyan"], - 6: ["gz_caoang", "gz_xianglang", "gz_wangyi"], - 5: ["gz_re_panshu", "gz_lukang", "gz_caoren", "gz_lvfan", "gz_machao", "gz_ganfuren", "gz_madai", "gz_jiling", "gz_pangde", "gz_huangzu"], - 4: ["gz_caozhen", "gz_re_lidian", "gz_yuejin", "gz_huangzhong", "gz_menghuo", "gz_sunshangxiang", "gz_lvmeng", "gz_lvbu", "gz_xiahouba", "gz_chendao", "gz_tw_tianyu"], - 3: ["gz_mazhong", "gz_tengyin", "gz_simayi", "gz_luxun", "gz_wuguotai", "gz_caiwenji", "gz_shibao", "gz_xuyou", "gz_zhugeke", "gz_re_nanhualaoxian", "gz_zhouyi"], - 2: ["gz_bulianshi", "gz_maliang", "gz_re_lusu", "gz_zhangzhang", "gz_jin_simashi", "gz_jin_zhangchunhua", "gz_zhugejin"], - 1: ["gz_caocao", "gz_guojia", "gz_xiahoudun", "gz_xunyu", "gz_caopi", "gz_liubei", "gz_fazheng", "gz_dongzhuo", "gz_yuji", "gz_liqueguosi", "gz_huanggai", "gz_re_xushu", "gz_panjun", "gz_yangxiu"], - }, - guozhanRank: { - 8: ["gz_xurong", "gz_xunyou", "gz_re_lidian", "gz_caopi", "gz_shamoke", "gz_lifeng", "gz_wangping", "gz_xiaoqiao", "gz_zhoutai", "gz_lvfan", "gz_beimihu", "gz_mateng", "gz_jiaxu", "gz_jin_wangyuanji", "gz_huaxin", "gz_duyu", "gz_zhonghui", "gz_xuyou", "gz_simazhao"], - 7: ["gz_xianglang", "gz_wangyi", "gz_zhanghe", "gz_jianggan", "gz_simayi", "gz_weiyan", "gz_huangyueying", "gz_zhugeliang", "gz_lingtong", "gz_sunshangxiang", "gz_sunce", "gz_re_yuanshao", "gz_yuanshu", "gz_hetaihou", "gz_jin_simashi", "gz_sp_duyu", "gz_shibao", "gz_gongsunyuan", "gz_panjun", "gz_re_nanhualaoxian", "gz_xin_zhuran", "gz_jin_jiachong", "gz_jin_yanghu"], - 6: ["gz_caoang", "gz_tengyin", "gz_wangji", "gz_zhenji", "gz_guojia", "gz_yujin", "gz_jiangwei", "gz_zhangfei", "gz_sp_zhugeliang", "gz_zhouyu", "gz_lingcao", "gz_daqiao", "gz_dingfeng", "gz_yuji", "gz_caiwenji", "gz_diaochan", "gz_zuoci", "gz_key_ushio", "gz_jin_simazhao", "gz_dongzhao", "gz_liuba", "gz_zhouyi", "gz_re_xunchen", "gz_fuwan", "gz_zhugejin", "gz_yangxiu", "gz_yangyan", "gz_tw_tianyu", "gz_yangwan", "gz_wangling"], - 5: ["gz_bulianshi", "gz_re_panshu", "gz_zhangliao", "gz_caocao", "gz_xuhuang", "gz_liushan", "gz_pangtong", "gz_zhaoyun", "gz_re_lusu", "gz_sunquan", "gz_ganning", "gz_zhangxiu", "gz_liqueguosi", "gz_huatuo", "gz_zhanghuyuechen", "gz_re_xushu", "gz_mifangfushiren", "gz_huangzu", "gz_weiguan", "gz_miheng", "gz_wenqin", "gz_zumao", "gz_xuangongzhu", "gz_tw_xiahoushang"], - 4: ["gz_mazhong", "gz_caozhen", "gz_dianwei", "gz_dengai", "gz_xunyu", "gz_madai", "gz_liubei", "gz_mifuren", "gz_wuguotai", "gz_luxun", "gz_re_taishici", "gz_zhangjiao", "gz_pangde", "gz_liuqi", "gz_jin_zhangchunhua", "gz_zongyu", "gz_shixie", "gz_jin_yanghuiyu", "gz_tangzi", "gz_yanbaihu", "gz_wujing", "gz_zhugeke", "gz_sunchen", "gz_liaohua", "gz_zhongyan", "gz_xinchang", "gz_tw_liufuren"], - 3: ["gz_maliang", "gz_xiahoudun", "gz_yuejin", "gz_caoren", "gz_machao", "gz_masu", "gz_fazheng", "gz_zhangzhang", "gz_lvmeng", "gz_huanggai", "gz_jiling", "gz_lvbu", "gz_dongzhuo", "gz_jin_xiahouhui", "gz_simazhou", "gz_zhanglu", "gz_chendao", "gz_yangzhi", "gz_old_huaxiong", "gz_gaoshun"], - 2: ["gz_cuimao", "gz_xiahouyuan", "gz_caohong", "gz_zhurong", "gz_zhurong", "gz_jiangfei", "gz_xusheng", "gz_luyusheng", "gz_sunjian", "gz_zhangren", "gz_kongrong", "gz_yanwen", "gz_jin_simayi", "gz_mengda", "gz_xiahouba"], - 1: ["gz_zangba", "gz_bianfuren", "gz_xuzhu", "gz_menghuo", "gz_ganfuren", "gz_guanyu", "gz_lukang", "gz_jiangqing", "gz_chendong", "gz_zoushi", "gz_panfeng", "gz_tianfeng", "gz_sufei", "gz_yanyan"], - }, + // @ts-expect-error 类型就是这么写的 + card, + aozhanRank: info.rank.aozhan, + guozhanRank: info.rank.guozhan, yingbian_guozhan: { gz_sp_duyu: ["male", "qun", 4, ["fakezhufu"]], gz_wangji: ["male", "wei", 3, ["fakeqizhi", "fakejinqu"]], @@ -20368,1248 +20319,13 @@ export default () => { "#mobiledanshou1": "此诚危难,我定当竭尽全力!", "#weishu2": "吴人来犯,当用心戒备。", }, - junList: ["liubei", "zhangjiao", "sunquan", "caocao"], - guozhanPile_yingbian: [ - //黑桃普通 - ["spade", 1, "shandian"], - ["spade", 1, "xietianzi"], - ["spade", 1, "juedou"], - ["spade", 2, "bagua"], - ["spade", 2, "heiguangkai"], - ["spade", 2, "cixiong"], - ["spade", 2, "taigongyinfu"], - ["spade", 3, "zhujinqiyuan", null, ["yingbian_zhuzhan", "yingbian_add"]], - ["spade", 3, "huoshaolianying"], - ["spade", 3, "shuiyanqijunx", null, ["yingbian_zhuzhan", "yingbian_add"]], - ["spade", 4, "guohe"], - ["spade", 4, "sha"], - ["spade", 4, "shuiyanqijunx", null, ["yingbian_zhuzhan", "yingbian_add"]], - ["spade", 5, "jueying"], - ["spade", 5, "qinglong"], - ["spade", 5, "sha"], - ["spade", 6, "qinggang"], - ["spade", 6, "jiu"], - ["spade", 6, "sha", "ice"], - ["spade", 7, "sha"], - ["spade", 7, "sha"], - ["spade", 7, "sha", "ice"], - ["spade", 8, "sha", "ice"], - ["spade", 8, "sha", "ice"], - ["spade", 8, "sha"], - ["spade", 9, "jiu"], - ["spade", 9, "sha", "thunder"], - ["spade", 9, "sha"], - ["spade", 10, "bingliang"], - ["spade", 10, "sha", "thunder"], - ["spade", 10, "sha", null, ["yingbian_canqu", "yingbian_add"]], - ["spade", 11, "wuxie", null, ["yingbian_kongchao", "yingbian_draw"]], - ["spade", 11, "sha", null, ["yingbian_canqu", "yingbian_add"]], - ["spade", 11, "sha", "thunder"], - ["spade", 12, "zhangba"], - ["spade", 12, "lulitongxin"], - ["spade", 12, "tiesuo"], - ["spade", 13, "wutiesuolian"], - ["spade", 13, "wuxie"], - ["spade", 13, "nanman", null, ["yingbian_fujia", "yingbian_remove"]], - //草花普通 - ["club", 1, "juedou"], - ["club", 1, "yuxi"], - ["club", 1, "huxinjing"], - ["club", 2, "sha"], - ["club", 2, "tianjitu"], - ["club", 2, "renwang"], - ["club", 2, "tengjia"], - ["club", 3, "sha"], - ["club", 3, "chiling"], - ["club", 3, "zhibi"], - ["club", 4, "sha", null, ["yingbian_kongchao", "yingbian_add"]], - ["club", 4, "sha", "thunder"], - ["club", 4, "zhibi"], - ["club", 5, "sha", null, ["yingbian_kongchao", "yingbian_add"]], - ["club", 5, "sha", "thunder"], - ["club", 5, "tongque"], - ["club", 6, "sha", "thunder"], - ["club", 6, "sha", null, ["yingbian_kongchao", "yingbian_add"]], - ["club", 6, "lebu"], - ["club", 7, "sha", "thunder"], - ["club", 7, "sha"], - ["club", 7, "nanman", null, ["yingbian_fujia", "yingbian_remove"]], - ["club", 8, "sha", "thunder"], - ["club", 8, "sha", null, ["yingbian_canqu", "yingbian_add"]], - ["club", 8, "sha"], - ["club", 9, "sha"], - ["club", 9, "jiu"], - ["club", 9, "jiu"], - ["club", 10, "bingliang"], - ["club", 10, "lulitongxin"], - ["club", 10, "sha"], - ["club", 11, "sha"], - ["club", 11, "huoshaolianying"], - ["club", 11, "sha"], - ["club", 12, "zhujinqiyuan", null, ["yingbian_zhuzhan", "yingbian_add"]], - ["club", 12, "jiedao", null, ["yingbian_fujia", "yingbian_hit"]], - ["club", 12, "tiesuo"], - ["club", 13, "tiesuo"], - ["club", 13, "wuxie", null, ["guo"]], - ["club", 13, "wuxie", null, ["guo"]], - //红桃普通 - ["heart", 1, "wanjian"], - ["heart", 1, "taoyuan"], - ["heart", 1, "lianjunshengyan"], - ["heart", 2, "shan"], - ["heart", 2, "chuqibuyi", null, ["yingbian_zhuzhan", "yingbian_add"]], - ["heart", 2, "diaohulishan"], - ["heart", 3, "chuqibuyi", null, ["yingbian_zhuzhan", "yingbian_add"]], - ["heart", 3, "wugu"], - ["heart", 3, "jingfanma"], - ["heart", 4, "tao"], - ["heart", 4, "sha", "fire", ["yingbian_canqu", "yingbian_damage"]], - ["heart", 4, "shan"], - ["heart", 5, "qilin"], - ["heart", 5, "chitu"], - ["heart", 5, "shan", null, ["yingbian_kongchao", "yingbian_draw"]], - ["heart", 6, "lebu"], - ["heart", 6, "tao"], - ["heart", 6, "shan", null, ["yingbian_kongchao", "yingbian_draw"]], - ["heart", 7, "tao"], - ["heart", 7, "dongzhuxianji"], - ["heart", 7, "shan"], - ["heart", 8, "tao"], - ["heart", 8, "dongzhuxianji"], - ["heart", 8, "tao"], - ["heart", 9, "tao"], - ["heart", 9, "yuanjiao"], - ["heart", 9, "tao"], - ["heart", 10, "sha"], - ["heart", 10, "shan"], - ["heart", 10, "sha"], - ["heart", 11, "yiyi"], - ["heart", 11, "tao"], - ["heart", 11, "sha", null, ["yingbian_zhuzhan", "yingbian_add"]], - ["heart", 12, "tao"], - ["heart", 12, "sha"], - ["heart", 12, "huoshaolianying"], - ["heart", 13, "zhuahuang"], - ["heart", 13, "shan"], - ["heart", 13, "huogong", null, ["yingbian_zhuzhan", "yingbian_add"]], - //方片普通 - ["diamond", 1, "wuxinghelingshan"], - ["diamond", 1, "zhuge"], - ["diamond", 1, "xietianzi"], - ["diamond", 2, "shan"], - ["diamond", 2, "tao"], - ["diamond", 2, "tao"], - ["diamond", 3, "shunshou"], - ["diamond", 3, "shan"], - ["diamond", 3, "tao"], - ["diamond", 4, "yiyi"], - ["diamond", 4, "sha", "fire", ["yingbian_canqu", "yingbian_damage"]], - ["diamond", 4, "sha", "fire", ["yingbian_zhuzhan", "yingbian_add"]], - ["diamond", 5, "guanshi"], - ["diamond", 5, "sha", "fire"], - ["diamond", 5, "muniu"], - ["diamond", 6, "wuliu"], - ["diamond", 6, "shan"], - ["diamond", 6, "shan"], - ["diamond", 7, "shan", null, ["yingbian_kongchao", "yingbian_draw"]], - ["diamond", 7, "shan", null, ["yingbian_kongchao", "yingbian_draw"]], - ["diamond", 7, "shan"], - ["diamond", 8, "shan", null, ["yingbian_kongchao", "yingbian_draw"]], - ["diamond", 8, "shan", null, ["yingbian_kongchao", "yingbian_draw"]], - ["diamond", 8, "sha", "fire"], - ["diamond", 9, "jiu"], - ["diamond", 9, "shan"], - ["diamond", 9, "sha", "fire"], - ["diamond", 10, "shan"], - ["diamond", 10, "sha"], - ["diamond", 10, "diaohulishan"], - ["diamond", 11, "sha"], - ["diamond", 11, "shan"], - ["diamond", 11, "wuxie", null, ["guo"]], - ["diamond", 12, "sha"], - ["diamond", 12, "sanjian"], - ["diamond", 12, "wuxie", null, ["guo"]], - ["diamond", 12, "fangtian"], - ["diamond", 13, "zixin"], - ["diamond", 13, "shan"], - ["diamond", 13, "shan"], - //特殊 - ["heart", 3, "taipingyaoshu"], - ["diamond", 4, "dinglanyemingzhu"], - ["heart", 5, "liulongcanjia"], - ["spade", 6, "feilongduofeng"], - ["club", 12, "gz_wenheluanwu"], - ["heart", 1, "gz_guguoanbang"], - ["spade", 12, "gz_haolingtianxia"], - ["diamond", 1, "gz_kefuzhongyuan"], - ], - guozhanPile_old: [ - ["spade", 1, "juedou"], - ["spade", 1, "shandian"], - ["spade", 2, "cixiong"], - ["spade", 2, "bagua"], - ["spade", 2, "hanbing"], - ["spade", 3, "guohe"], - ["spade", 3, "shunshou"], - ["spade", 4, "guohe"], - ["spade", 4, "shunshou"], - ["spade", 5, "sha"], - ["spade", 5, "jueying"], - ["spade", 6, "qinggang"], - ["spade", 6, "sha", "thunder"], - ["spade", 7, "sha"], - ["spade", 7, "sha", "thunder"], - ["spade", 8, "sha"], - ["spade", 8, "sha"], - ["spade", 9, "sha"], - ["spade", 9, "jiu"], - ["spade", 10, "sha"], - ["spade", 10, "bingliang"], - ["spade", 11, "sha"], - ["spade", 11, "wuxie"], - ["spade", 12, "zhangba"], - ["spade", 12, "tiesuo"], - ["spade", 13, "nanman"], - ["spade", 13, "dawan"], - - ["club", 1, "juedou"], - ["club", 1, "baiyin"], - ["club", 2, "sha"], - ["club", 2, "tengjia"], - ["club", 2, "renwang"], - ["club", 3, "sha"], - ["club", 3, "zhibi"], - ["club", 4, "sha"], - ["club", 4, "zhibi"], - ["club", 5, "sha"], - ["club", 5, "dilu"], - ["club", 6, "lebu"], - ["club", 6, "sha", "thunder"], - ["club", 7, "nanman"], - ["club", 7, "sha", "thunder"], - ["club", 8, "sha"], - ["club", 8, "sha", "thunder"], - ["club", 9, "sha"], - ["club", 9, "jiu"], - ["club", 10, "sha"], - ["club", 10, "bingliang"], - ["club", 11, "sha"], - ["club", 11, "sha"], - ["club", 12, "jiedao"], - ["club", 12, "tiesuo"], - ["club", 13, "wuxie", null, ["guo"]], - ["club", 13, "tiesuo"], - - ["diamond", 1, "zhuge"], - ["diamond", 1, "zhuque"], - ["diamond", 2, "shan"], - ["diamond", 2, "tao"], - ["diamond", 3, "shan"], - ["diamond", 3, "shunshou"], - ["diamond", 4, "yiyi"], - ["diamond", 4, "sha", "fire"], - ["diamond", 5, "guanshi"], - ["diamond", 5, "sha", "fire"], - ["diamond", 6, "shan"], - ["diamond", 6, "wuliu"], - ["diamond", 7, "shan"], - ["diamond", 7, "shan"], - ["diamond", 8, "shan"], - ["diamond", 8, "shan"], - ["diamond", 9, "shan"], - ["diamond", 9, "jiu"], - ["diamond", 10, "shan"], - ["diamond", 10, "sha"], - ["diamond", 11, "shan"], - ["diamond", 11, "sha"], - ["diamond", 12, "sha"], - ["diamond", 12, "sanjian"], - ["diamond", 12, "wuxie", null, ["guo"]], - ["diamond", 13, "shan"], - ["diamond", 13, "zixin"], - - ["heart", 1, "taoyuan"], - ["heart", 1, "wanjian"], - ["heart", 2, "shan"], - ["heart", 2, "huogong"], - ["heart", 3, "wugu"], - ["heart", 3, "huogong"], - ["heart", 4, "tao"], - ["heart", 4, "sha", "fire"], - ["heart", 5, "qilin"], - ["heart", 5, "chitu"], - ["heart", 6, "tao"], - ["heart", 6, "lebu"], - ["heart", 7, "tao"], - ["heart", 7, "wuzhong"], - ["heart", 8, "tao"], - ["heart", 8, "wuzhong"], - ["heart", 9, "tao"], - ["heart", 9, "yuanjiao"], - ["heart", 10, "tao"], - ["heart", 10, "sha"], - ["heart", 11, "shan"], - ["heart", 11, "yiyi"], - ["heart", 12, "tao"], - ["heart", 12, "sha"], - ["heart", 12, "guohe"], - ["heart", 13, "shan"], - ["heart", 13, "zhuahuang"], - ], - guozhanPile: [ - ["spade", 1, "juedou"], - ["spade", 1, "shandian"], - ["spade", 2, "feilongduofeng"], - ["spade", 2, "bagua"], - ["spade", 2, "hanbing"], - ["spade", 3, "guohe"], - ["spade", 3, "shunshou"], - ["spade", 4, "guohe"], - ["spade", 4, "shunshou"], - ["spade", 5, "sha"], - ["spade", 5, "jueying"], - ["spade", 6, "qinggang"], - ["spade", 6, "sha", "thunder"], - ["spade", 7, "sha"], - ["spade", 7, "sha", "thunder"], - ["spade", 8, "sha"], - ["spade", 8, "sha"], - ["spade", 9, "sha"], - ["spade", 9, "jiu"], - ["spade", 10, "sha"], - ["spade", 10, "bingliang"], - ["spade", 11, "sha"], - ["spade", 11, "wuxie"], - ["spade", 12, "zhangba"], - ["spade", 12, "tiesuo"], - ["spade", 13, "nanman"], - ["spade", 13, "dawan"], - - ["club", 1, "juedou"], - ["club", 1, "baiyin"], - ["club", 2, "sha"], - ["club", 2, "tengjia"], - ["club", 2, "renwang"], - ["club", 3, "sha"], - ["club", 3, "zhibi"], - ["club", 4, "sha"], - ["club", 4, "zhibi"], - ["club", 5, "sha"], - ["club", 5, "dilu"], - ["club", 6, "lebu"], - ["club", 6, "sha", "thunder"], - ["club", 7, "nanman"], - ["club", 7, "sha", "thunder"], - ["club", 8, "sha"], - ["club", 8, "sha", "thunder"], - ["club", 9, "sha"], - ["club", 9, "jiu"], - ["club", 10, "sha"], - ["club", 10, "bingliang"], - ["club", 11, "sha"], - ["club", 11, "sha"], - ["club", 12, "jiedao"], - ["club", 12, "tiesuo"], - ["club", 13, "wuxie", null, ["guo"]], - ["club", 13, "tiesuo"], - - ["diamond", 1, "zhuge"], - ["diamond", 1, "zhuque"], - ["diamond", 2, "shan"], - ["diamond", 2, "tao"], - ["diamond", 3, "shan"], - ["diamond", 3, "shunshou"], - ["diamond", 4, "yiyi"], - ["diamond", 4, "sha", "fire"], - ["diamond", 5, "guanshi"], - ["diamond", 5, "sha", "fire"], - ["diamond", 6, "shan"], - ["diamond", 6, "wuliu"], - ["diamond", 7, "shan"], - ["diamond", 7, "shan"], - ["diamond", 8, "shan"], - ["diamond", 8, "shan"], - ["diamond", 9, "shan"], - ["diamond", 9, "jiu"], - ["diamond", 10, "shan"], - ["diamond", 10, "sha"], - ["diamond", 11, "shan"], - ["diamond", 11, "sha"], - ["diamond", 12, "sha"], - ["diamond", 12, "sanjian"], - ["diamond", 12, "wuxie", null, ["guo"]], - ["diamond", 13, "shan"], - ["diamond", 13, "zixin"], - - ["heart", 1, "taoyuan"], - ["heart", 1, "wanjian"], - ["heart", 2, "shan"], - ["heart", 2, "huogong"], - ["heart", 3, "wugu"], - ["heart", 3, "taipingyaoshu"], - ["heart", 3, "huogong"], - ["heart", 4, "tao"], - ["heart", 4, "sha", "fire"], - ["heart", 5, "qilin"], - ["heart", 5, "chitu"], - ["heart", 6, "tao"], - ["heart", 6, "lebu"], - ["heart", 7, "tao"], - ["heart", 7, "wuzhong"], - ["heart", 8, "tao"], - ["heart", 8, "wuzhong"], - ["heart", 9, "tao"], - ["heart", 9, "yuanjiao"], - ["heart", 10, "tao"], - ["heart", 10, "sha"], - ["heart", 11, "shan"], - ["heart", 11, "yiyi"], - ["heart", 12, "tao"], - ["heart", 12, "sha"], - ["heart", 12, "guohe"], - ["heart", 13, "shan"], - ["heart", 13, "zhuahuang"], - - ["spade", 1, "xietianzi", null, ["lianheng"]], - ["spade", 2, "minguangkai"], - ["spade", 3, "huoshaolianying", null, ["lianheng"]], - ["spade", 4, "sha"], - ["spade", 5, "qinglong"], - ["spade", 6, "jiu", null, ["lianheng"]], - ["spade", 7, "sha"], - ["spade", 8, "sha"], - ["spade", 9, "sha", "thunder"], - ["spade", 10, "sha", "thunder"], - ["spade", 11, "sha", "thunder", ["lianheng"]], - ["spade", 12, "lulitongxin"], - ["spade", 13, "wuxie"], - - ["heart", 1, "lianjunshengyan"], - ["heart", 2, "diaohulishan"], - ["heart", 3, "jingfanma", null, ["lianheng"]], - ["heart", 4, "shan"], - ["heart", 5, "shan"], - ["heart", 6, "shan", null, ["lianheng"]], - ["heart", 7, "shan"], - ["heart", 8, "tao"], - ["heart", 9, "tao"], - ["heart", 10, "sha"], - ["heart", 11, "sha"], - ["heart", 12, "huoshaolianying", null, ["lianheng"]], - ["heart", 13, "shuiyanqijunx"], - - ["club", 1, "yuxi"], - ["club", 2, "huxinjing", null, ["lianheng"]], - ["club", 3, "chiling"], - ["club", 4, "sha"], - ["club", 5, "sha", "thunder", ["lianheng"]], - ["club", 6, "sha"], - ["club", 7, "sha"], - ["club", 8, "sha"], - ["club", 9, "jiu"], - ["club", 10, "lulitongxin"], - ["club", 11, "huoshaolianying", null, ["lianheng"]], - ["club", 12, "shuiyanqijunx"], - ["club", 13, "wuxie", null, ["guo"]], - - ["diamond", 1, "xietianzi", null, ["lianheng"]], - ["diamond", 2, "tao"], - ["diamond", 3, "tao", null, ["lianheng"]], - ["diamond", 4, "xietianzi", null, ["lianheng"]], - ["diamond", 5, "muniu"], - ["diamond", 6, "shan"], - ["diamond", 7, "shan"], - ["diamond", 8, "sha", "fire"], - ["diamond", 9, "sha", "fire"], - ["diamond", 10, "diaohulishan", null, ["lianheng"]], - ["diamond", 11, "wuxie", null, ["guo"]], - ["diamond", 12, "fangtian"], - ["diamond", 13, "shan"], - - ["diamond", 6, "dinglanyemingzhu"], - ["heart", 13, "liulongcanjia"], - - //['spade',12,'gz_haolingtianxia'], - //['diamond',1,'gz_kefuzhongyuan'], - //['heart',1,'gz_guguoanbang'], - //['club',12,'gz_wenheluanwu'], - ], + junList: info.junList, + guozhanPile_yingbian: info.pile.yingbian, + guozhanPile_old: info.pile.old, + guozhanPile: info.pile.normal, element: { - content: { - ...contentPatch, - chooseJunlingControl() { - "step 0"; - var dialog = []; - var str1 = source == player ? "(你)" : ""; - var str2 = event.targets ? "(被指定的角色为" + get.translation(event.targets) + ")" : ""; - if (!event.prompt) dialog.add(get.translation(event.source) + str1 + "选择的军令" + str2 + "为"); - else { - dialog.add(event.prompt); - dialog.add(get.translation(event.source) + str1 + "选择的军令" + str2 + "为"); - } - dialog.add([[event.junling], "vcard"]); - var controls = []; - if (event.choiceList) { - for (var i = 0; i < event.choiceList.length; i++) { - dialog.add('"); - controls.push("选项" + get.cnNumber(i + 1, true)); - } - } else if (event.controls) controls = event.controls; - else controls = ["执行该军令", "不执行该军令"]; - if (!event.ai) - event.ai = function () { - return Math.floor(controls.length * Math.random()); - }; - player.chooseControl(controls).set("dialog", dialog).set("ai", event.ai); - "step 1"; - event.result = { - index: result.index, - control: result.control, - }; - }, - carryOutJunling() { - "step 0"; - switch (event.junling) { - case "junling1": { - if (targets[0].isAlive()) { - player.line(targets, "green"); - targets[0].damage(player); - } - break; - } - case "junling2": - player.draw(); - event.num = 1; - break; - case "junling3": - player.loseHp(); - break; - case "junling4": - player.addTempSkill("junling4_eff"); - player.addTempSkill("fengyin_vice"); - player.addTempSkill("fengyin_main"); - break; - case "junling5": - player.turnOver(); - player.addTempSkill("junling5_eff"); - break; - } - "step 1"; - if (event.junling == "junling2" && source != player && player.countCards("he") > 0) { - player.chooseCard("交给" + get.translation(source) + "第" + get.cnNumber(event.num) + "张牌(共两张)", "he", true); - event.ing = true; - } - if (event.junling == "junling6") { - var position = "", - num0 = 0; - if (player.countCards("h")) { - position += "h"; - num0++; - } - if (player.countCards("e")) { - position += "e"; - num0++; - } - player - .chooseCard( - "选择一张手牌和一张装备区内牌(若有),然后弃置其余的牌", - position, - num0, - function (card) { - if (ui.selected.cards.length) return get.position(card) != get.position(ui.selected.cards[0]); - return true; - }, - true - ) - .set("complexCard", true) - .set("ai", function (card) { - return get.value(card); - }); - } - "step 2"; - if (event.junling == "junling2" && source != player) { - if (result.cards.length && event.ing) { - player.give(result.cards, source); - } - event.num++; - if (event.num < 3) { - event.ing = false; - event.goto(1); - } - } - if (event.junling == "junling6") { - var cards = player.getCards("he"); - for (var i = 0; i < result.cards.length; i++) cards.remove(result.cards[i]); - player.discard(cards); - } - }, - doubleDraw() { - if (!player.hasMark("yinyang_mark")) player.addMark("yinyang_mark", 1); - }, - changeViceOnline() { - "step 0"; - player.showCharacter(2); - var group = lib.character[player.name1][1]; - _status.characterlist.randomSort(); - var name = false; - for (var i = 0; i < _status.characterlist.length; i++) { - var goon = false, - group2 = lib.character[_status.characterlist[i]][1]; - if (game.hasPlayer2(current => get.nameList(current).includes(_status.characterlist[i]))) continue; - if (group == "ye") { - if (group2 != "ye") goon = true; - } else { - if (group == group2) goon = true; - else { - var double = get.is.double(_status.characterlist[i], true); - if (double && double.includes(group)) goon = true; - } - } - if (goon) { - name = _status.characterlist[i]; - break; - } - } - if (!name) { - event.finish(); - return; - } - _status.characterlist.remove(name); - if (player.hasViceCharacter()) { - event.change = true; - _status.characterlist.add(player.name2); - } - event.toRemove = player.name2; - event.toChange = name; - if (event.change) event.trigger("removeCharacterBefore"); - "step 1"; - if (event.hidden) { - if (!player.isUnseen(1)) player.hideCharacter(1); - } - "step 2"; - var name = event.toChange; - if (event.hidden) game.log(player, "替换了副将", "#g" + get.translation(player.name2)); - else game.log(player, "将副将从", "#g" + get.translation(player.name2), "变更为", "#g" + get.translation(name)); - player.viceChanged = true; - player.reinitCharacter(player.name2, name, false); - }, - changeVice() { - "step 0"; - player.showCharacter(2); - if (!event.num) event.num = 3; - var group = player.identity; - if (!lib.group.includes(group)) group = lib.character[player.name1][1]; - _status.characterlist.randomSort(); - event.tochange = []; - for (var i = 0; i < _status.characterlist.length; i++) { - if (_status.characterlist[i].indexOf("gz_jun_") == 0) continue; - if (game.hasPlayer2(current => get.nameList(current).includes(_status.characterlist[i]))) continue; - var goon = false, - group2 = lib.character[_status.characterlist[i]][1]; - if (group == "ye") { - if (group2 != "ye") goon = true; - } else { - if (group == group2) goon = true; - else { - var double = get.is.double(_status.characterlist[i], true); - if (double && double.includes(group)) goon = true; - } - } - if (goon) { - event.tochange.push(_status.characterlist[i]); - if (event.tochange.length == event.num) break; - } - } - if (!event.tochange.length) event.finish(); - else { - if (event.tochange.length == 1) - event._result = { - bool: true, - links: event.tochange, - }; - else - player.chooseButton(true, ["选择要变更的武将牌", [event.tochange, "character"]]).ai = function (button) { - return get.guozhanRank(button.link); - }; - } - "step 1"; - var name = result.links[0]; - _status.characterlist.remove(name); - if (player.hasViceCharacter()) { - event.change = true; - _status.characterlist.add(player.name2); - } - event.toRemove = player.name2; - event.toChange = name; - if (event.change) event.trigger("removeCharacterBefore"); - if (event.hidden) { - if (!player.isUnseen(1)) player.hideCharacter(1); - } - "step 2"; - var name = event.toChange; - if (event.hidden) game.log(player, "替换了副将", "#g" + get.translation(player.name2)); - else game.log(player, "将副将从", "#g" + get.translation(player.name2), "变更为", "#g" + get.translation(name)); - player.viceChanged = true; - player.reinitCharacter(player.name2, name, false); - }, - /*----分界线----*/ - mayChangeVice() { - "step 0"; - player.chooseBool("是否变更副将?").set("ai", function () { - var player = _status.event.player; - return get.guozhanRank(player.name2, player) <= 3; - }); - "step 1"; - if (result.bool) { - if (!event.repeat) { - if (!_status.changedSkills[player.playerid]) _status.changedSkills[player.playerid] = []; - _status.changedSkills[player.playerid].add(event.skill); - } - player.changeVice(event.hidden); - } - }, - zhulian() { - player.popup("珠联璧合"); - if (!player.hasMark("zhulianbihe_mark")) player.addMark("zhulianbihe_mark", 1); - }, - }, - player: { - ...playerPatch, - chooseJunlingControl(source, junling, targets) { - var next = game.createEvent("chooseJunlingControl"); - next.player = this; - next.source = source; - next.junling = junling; - if (targets.length) next.targets = targets; - next.setContent("chooseJunlingControl"); - return next; - }, - carryOutJunling(source, junling, targets) { - var next = game.createEvent("carryOutJunling"); - next.source = source; - next.player = this; - if (targets.length) next.targets = targets; - next.junling = junling; - next.setContent("carryOutJunling"); - return next; - }, - /**/ - mayChangeVice(repeat, hidden) { - if (!_status.changedSkills) _status.changedSkills = {}; - var skill = _status.event.name; - if (repeat || !_status.changedSkills[this.playerid] || !_status.changedSkills[this.playerid].includes(skill)) { - var next = game.createEvent("mayChangeVice"); - next.setContent("mayChangeVice"); - next.player = this; - next.skill = skill; - if (repeat || (!_status.connectMode && get.config("changeViceType") == "online")) next.repeat = true; - if (hidden == "hidden") next.hidden = true; - return next; - } - }, - differentIdentityFrom(target, self) { - if (this == target) return false; - if (this.getStorage("yexinjia_friend").includes(target)) return false; - if (target.getStorage("yexinjia_friend").includes(this)) return false; - if (self) { - if (target.identity == "unknown") return false; - if (target.identity == "ye" || this.identity == "ye") return true; - if (this.identity == "unknown") { - var identity = lib.character[this.name1][1]; - if (this.wontYe()) return identity != target.identity; - return true; - } - } else { - if (this.identity == "unknown" || target.identity == "unknown") return false; - if (this.identity == "ye" || target.identity == "ye") return true; - } - return this.identity != target.identity; - }, - sameIdentityAs(target, shown) { - if (this.getStorage("yexinjia_friend").includes(target)) return true; - if (target.getStorage("yexinjia_friend").includes(this)) return true; - if (shown) { - if (this.identity == "ye" || this.identity == "unknown") return false; - } else { - if (this == target) return true; - if (target.identity == "unknown" || target.identity == "ye" || this.identity == "ye") return false; - if (this.identity == "unknown") { - var identity = lib.character[this.name1][1]; - if (this.wontYe()) return identity == target.identity; - return false; - } - } - return this.identity == target.identity; - }, - getModeState() { - return { - unseen: this.isUnseen(0), - unseen2: this.isUnseen(1), - }; - }, - setModeState(info) { - if (info.mode.unseen) this.classList.add("unseen"); - if (info.mode.unseen2) this.classList.add("unseen2"); - if (!info.name) return; - // if(info.name.indexOf('unknown')==0){ - // if(this==game.me){ - // lib.translate[info.name]+='(你)'; - // } - // } - this.init(info.name1, info.name2, false); - this.name1 = info.name1; - this.name = info.name; - this.node.name_seat = ui.create.div(".name.name_seat", get.verticalStr(lib.translate[this.name].slice(0, 3)), this); - if (info.identityShown) { - this.setIdentity(info.identity); - this.node.identity.classList.remove("guessing"); - } else if (this != game.me) { - this.node.identity.firstChild.innerHTML = "猜"; - this.node.identity.dataset.color = "unknown"; - this.node.identity.classList.add("guessing"); - } - }, - dieAfter2(source) { - var that = this; - if (that.hasSkillTag("noDieAfter", null, source)) return; - if (source && source.hasSkillTag("noDieAfter2", null, that)) return; - if (source && source.shijun) { - source.discard(source.getCards("he")); - delete source.shijun; - } else if (source && source.identity != "unknown") { - if (source.identity == "ye" && !source.getStorage("yexinjia_friend").length) source.draw(3); - else if (source.shijun2) { - delete source.shijun2; - source.draw( - 1 + - game.countPlayer(function (current) { - return current.group == that.group; - }) - ); - } else if (that.identity == "ye") { - if (that.getStorage("yexinjia_friend").includes(source) || source.getStorage("yexinjia_friend").includes(that)) source.discard(source.getCards("he")); - else - source.draw( - 1 + - game.countPlayer(function (current) { - if (current == that) return false; - if (current.getStorage("yexinjia_friend").includes(that)) return true; - if (that.getStorage("yexinjia_friend").includes(current)) return true; - return false; - }) - ); - } else if (that.identity != source.identity) source.draw(get.population(that.identity) + 1); - else source.discard(source.getCards("he")); - } - }, - dieAfter(source) { - this.showCharacter(2); - if (get.is.jun(this.name1)) { - if (source && source.identity == this.identity) source.shijun = true; - else if (source && source.identity != "ye") source.shijun2 = true; - var yelist = []; - for (var i = 0; i < game.players.length; i++) { - if (game.players[i].identity == this.identity) { - yelist.push(game.players[i]); - } - } - game.broadcastAll(function (list) { - for (var i = 0; i < list.length; i++) { - list[i].identity = "ye"; - list[i].setIdentity(); - } - }, yelist); - _status.yeidentity.add(this.identity); - } - game.tryResult(); - }, - viewCharacter(target, num) { - if (num != 0 && num != 1) { - num = 2; - } - if (!target.isUnseen(num)) { - return; - } - var next = game.createEvent("viewCharacter"); - next.player = this; - next.target = target; - next.num = num; - next.setContent(function () { - if (!player.storage.zhibi) { - player.storage.zhibi = []; - } - player.storage.zhibi.add(target); - var content, - str = get.translation(target) + "的"; - if (event.num == 0 || !target.isUnseen(1)) { - content = [str + "主将", [[target.name1], "character"]]; - game.log(player, "观看了", target, "的主将"); - } else if (event.num == 1 || !target.isUnseen(0)) { - content = [str + "副将", [[target.name2], "character"]]; - game.log(player, "观看了", target, "的副将"); - } else { - content = [str + "主将和副将", [[target.name1, target.name2], "character"]]; - game.log(player, "观看了", target, "的主将和副将"); - } - player.chooseControl("ok").set("dialog", content); - }); - }, - checkViceSkill(skill, disable) { - if (game.expandSkills(lib.character[this.name2][3].slice(0)).includes(skill)) { - return true; - } else { - if (disable !== false) { - this.awakenSkill(skill); - } - return false; - } - }, - checkMainSkill(skill, disable) { - if (game.expandSkills(lib.character[this.name1][3].slice(0)).includes(skill)) { - return true; - } else { - if (disable !== false) { - this.awakenSkill(skill); - } - return false; - } - }, - removeMaxHp(num) { - if (game.online) return; - if (!num) num = 1; - while (num > 0) { - num--; - if (typeof this.singleHp == "boolean") { - if (this.singleHp) { - this.singleHp = false; - } else { - this.singleHp = true; - this.maxHp--; - } - } else { - this.maxHp--; - } - } - this.update(); - }, - hideCharacter(num, log) { - if (this.isUnseen(2)) return; - var name = this["name" + (num + 1)]; - var next = game.createEvent("hideCharacter"); - next.player = this; - next.toHide = name; - next.num = num; - next.log = log; - next.setContent("hideCharacter"); - return next; - }, - removeCharacter(num) { - var name = this["name" + (num + 1)]; - var next = game.createEvent("removeCharacter"); - next.player = this; - next.toRemove = name; - next.num = num; - next.setContent("removeCharacter"); - return next; - }, - $removeCharacter(num) { - var name = this["name" + (num + 1)]; - var info = lib.character[name]; - if (!info) return; - var to = "gz_shibing" + (info[0] == "male" ? 1 : 2) + info[1]; - game.log(this, "移除了" + (num ? "副将" : "主将"), "#b" + name); - this.reinit(name, to, false); - this.showCharacter(num, false); - _status.characterlist.add(name); - }, - changeVice(hidden) { - var next = game.createEvent("changeVice"); - next.player = this; - next.setContent("changeVice"); - next.num = !_status.connectMode && get.config("changeViceType") == "online" ? 1 : 3; - if (hidden) next.hidden = true; - return next; - }, - hasMainCharacter() { - return this.name1.indexOf("gz_shibing") != 0; - }, - hasViceCharacter() { - return this.name2.indexOf("gz_shibing") != 0; - }, - $showCharacter(num, log) { - var showYe = false; - if (num == 0 && !this.isUnseen(0)) { - return; - } - if (num == 1 && !this.isUnseen(1)) { - return; - } - if (!this.isUnseen(2)) { - return; - } - game.addVideo("showCharacter", this, num); - if (this.identity == "unknown" || ((num == 0 || num == 2) && lib.character[this.name1][1] == "ye")) { - this.group = this.getGuozhanGroup(num); - if ((num == 0 || num == 2) && lib.character[this.name1][1] == "ye") { - this.identity = "ye"; - if (!this._ye) { - this._ye = true; - showYe = true; - } - } else if (get.is.jun(this.name1) && this.isAlive()) { - this.identity = this.group; - } else if (this.wontYe(this.group)) { - this.identity = this.group; - } else { - this.identity = "ye"; - } - this.setIdentity(this.identity); - this.ai.shown = 1; - this.node.identity.classList.remove("guessing"); - - if (_status.clickingidentity && _status.clickingidentity[0] == this) { - for (var i = 0; i < _status.clickingidentity[1].length; i++) { - _status.clickingidentity[1][i].delete(); - _status.clickingidentity[1][i].style.transform = ""; - } - delete _status.clickingidentity; - } - game.addVideo("setIdentity", this, this.identity); - } - var skills; - switch (num) { - case 0: - if (log !== false) game.log(this, "展示了主将", "#b" + this.name1); - this.name = this.name1; - skills = lib.character[this.name][3]; - this.sex = lib.character[this.name][0]; - this.classList.remove("unseen"); - break; - case 1: - if (log !== false) game.log(this, "展示了副将", "#b" + this.name2); - skills = lib.character[this.name2][3]; - if (this.sex == "unknown") this.sex = lib.character[this.name2][0]; - if (this.name.indexOf("unknown") == 0) this.name = this.name2; - this.classList.remove("unseen2"); - break; - case 2: - if (log !== false) game.log(this, "展示了主将", "#b" + this.name1, "、副将", "#b" + this.name2); - this.name = this.name1; - skills = lib.character[this.name][3].concat(lib.character[this.name2][3]); - this.sex = lib.character[this.name][0]; - this.classList.remove("unseen"); - this.classList.remove("unseen2"); - break; - } - game.broadcast( - function (player, name, sex, num, identity, group) { - player.identityShown = true; - player.group = group; - player.name = name; - player.sex = sex; - player.node.identity.classList.remove("guessing"); - switch (num) { - case 0: - player.classList.remove("unseen"); - break; - case 1: - player.classList.remove("unseen2"); - break; - case 2: - player.classList.remove("unseen"); - player.classList.remove("unseen2"); - break; - } - player.ai.shown = 1; - player.identity = identity; - player.setIdentity(identity); - if (_status.clickingidentity && _status.clickingidentity[0] == player) { - for (var i = 0; i < _status.clickingidentity[1].length; i++) { - _status.clickingidentity[1][i].delete(); - _status.clickingidentity[1][i].style.transform = ""; - } - delete _status.clickingidentity; - } - }, - this, - this.name, - this.sex, - num, - this.identity, - this.group - ); - this.identityShown = true; - for (var i = 0; i < skills.length; i++) { - this.hiddenSkills.remove(skills[i]); - this.addSkill(skills[i]); - } - this.checkConflict(); - if (!this.viceChanged) { - var initdraw = get.config("initshow_draw"); - if (_status.connectMode) initdraw = lib.configOL.initshow_draw; - if (!_status.initshown && !_status.overing && initdraw != "off" && this.isAlive() && _status.mode != "mingjiang") { - this.popup("首亮"); - if (initdraw == "draw") { - game.log(this, "首先明置武将,得到奖励"); - game.log(this, "摸了两张牌"); - this.draw(2).log = false; - } else { - this.addMark("xianqu_mark", 1); - } - _status.initshown = true; - } - if (!this.isUnseen(2) && !this._mingzhied) { - this._mingzhied = true; - if (this.singleHp) { - this.doubleDraw(); - } - if (this.perfectPair()) { - var next = game.createEvent("guozhanDraw"); - next.player = this; - next.setContent("zhulian"); - } - } - if (showYe) { - this.addMark("yexinjia_mark", 1); - } - } - game.tryResult(); - }, - wontYe(group, numOfReadyToShow) { - if (!group) { - if (this.trueIdentity) group = this.trueIdentity; - else group = lib.character[this.name1][1]; - } - if (_status.yeidentity && _status.yeidentity.includes(group)) return false; - if (get.zhu(this, null, group)) return true; - if (!numOfReadyToShow) numOfReadyToShow = 1; - return get.totalPopulation(group) + numOfReadyToShow <= (_status.separatism ? Math.max(get.population() / 2 - 1, 1) : get.population() / 2); - }, - perfectPair(choosing) { - if (_status.connectMode) { - if (!lib.configOL.zhulian) return false; - } else { - if (!get.config("zhulian")) return false; - } - var name1 = this.name1; - var name2 = this.name2; - if (name1.indexOf("gz_shibing") == 0) return false; - if (name2.indexOf("gz_shibing") == 0) return false; - if (get.is.jun(this.name1)) return true; - if (choosing && lib.character[name1][1] != "ye" && lib.character[name2][1] != "ye" && lib.character[name1][1] != lib.character[name2][1]) return false; - if (name1.indexOf("gz_") == 0) { - name1 = name1.slice(name1.indexOf("_") + 1); - } else { - while (name1.indexOf("_") != -1 && !lib.perfectPair[name1]) { - name1 = name1.slice(name1.indexOf("_") + 1); - } - } - if (name2.indexOf("gz_") == 0) { - name2 = name2.slice(name2.indexOf("_") + 1); - } else { - while (name2.indexOf("_") != -1 && !lib.perfectPair[name2]) { - name2 = name2.slice(name2.indexOf("_") + 1); - } - } - var list = Object.keys(lib.perfectPair).concat(Object.values(lib.perfectPair)).flat(); - if (!list.includes(name1) || !list.includes(name2)) return false; - return (lib.perfectPair[name1] && lib.perfectPair[name1].flat(Infinity).includes(name2)) || (lib.perfectPair[name2] && lib.perfectPair[name2].flat(Infinity).includes(name1)); - }, - siege(player) { - if (this.identity == "unknown" || this.hasSkill("undist")) return false; - if (!player) { - var next = this.getNext(); - if (next && next.sieged()) return true; - var previous = this.getPrevious(); - if (previous && previous.sieged()) return true; - return false; - } else { - return player.sieged() && (player.getNext() == this || player.getPrevious() == this); - } - }, - sieged(player) { - if (this.identity == "unknown") return false; - if (player) { - return player.siege(this); - } else { - var next = this.getNext(); - var previous = this.getPrevious(); - if (next && previous && next != previous) { - if (next.identity == "unknown" || next.isFriendOf(this)) return false; - return next.isFriendOf(previous); - } - return false; - } - }, - inline() { - if (this.identity == "unknown" || this.identity == "ye" || this.hasSkill("undist")) return false; - var next = this, - previous = this; - var list = []; - for (var i = 0; next || previous; i++) { - if (next) { - next = next.getNext(); - if (!next.isFriendOf(this) || next == this) { - next = null; - } else { - list.add(next); - } - } - if (previous) { - previous = previous.getPrevious(); - if (!previous.isFriendOf(this) || previous == this) { - previous = null; - } else { - list.add(previous); - } - } - } - if (!list.length) return false; - for (var i = 0; i < arguments.length; i++) { - if (!list.includes(arguments[i]) && arguments[i] != this) return false; - } - return true; - }, - logAi(targets, card) { - if (this.ai.shown == 1 || this.isMad()) return; - if (typeof targets == "number") { - this.ai.shown += targets; - } else { - var effect = 0, - c, - shown; - var info = get.info(card); - if (info.ai && info.ai.expose) { - if (_status.event.name == "_wuxie") { - if (_status.event.source && _status.event.source.ai.shown) { - this.ai.shown += 0.2; - } - } else { - this.ai.shown += info.ai.expose; - } - } - if (targets.length > 0) { - for (var i = 0; i < targets.length; i++) { - shown = Math.abs(targets[i].ai.shown); - if (shown < 0.2 || targets[i].identity == "nei") c = 0; - else if (shown < 0.4) c = 0.5; - else if (shown < 0.6) c = 0.8; - else c = 1; - effect += get.effect(targets[i], card, this) * c; - } - } - if (effect > 0) { - if (effect < 1) c = 0.5; - else c = 1; - if (targets.length == 1 && targets[0] == this); - else if (targets.length == 1) this.ai.shown += 0.2 * c; - else this.ai.shown += 0.1 * c; - } - } - if (this.ai.shown > 0.95) this.ai.shown = 0.95; - if (this.ai.shown < -0.5) this.ai.shown = -0.5; - }, - }, + content: contentPatch, + player: playerPatch, }, get: getPatch, help, diff --git a/mode/guozhan/src/card/index.js b/mode/guozhan/src/card/index.js new file mode 100644 index 0000000000..54002ccb60 --- /dev/null +++ b/mode/guozhan/src/card/index.js @@ -0,0 +1,36 @@ + +export default Object.freeze({ + junling1: { + type: "junling", + vanish: true, + derivation: "guozhan", + }, + junling2: { + type: "junling", + vanish: true, + derivation: "guozhan", + }, + junling3: { + type: "junling", + vanish: true, + derivation: "guozhan", + }, + junling4: { + type: "junling", + vanish: true, + derivation: "guozhan", + }, + junling5: { + type: "junling", + vanish: true, + derivation: "guozhan", + }, + junling6: { + type: "junling", + vanish: true, + derivation: "guozhan", + }, + zhulian_card: { + cardimage: "wuzhong", + }, +}); diff --git a/mode/guozhan/src/info/index.js b/mode/guozhan/src/info/index.js new file mode 100644 index 0000000000..58f5f900eb --- /dev/null +++ b/mode/guozhan/src/info/index.js @@ -0,0 +1,4 @@ +export * as rank from "./rank.js"; +export * as pile from "./pile.js"; + +export const junList = ["liubei", "zhangjiao", "sunquan", "caocao"]; diff --git a/mode/guozhan/src/info/pile.js b/mode/guozhan/src/info/pile.js new file mode 100644 index 0000000000..c744b85e50 --- /dev/null +++ b/mode/guozhan/src/info/pile.js @@ -0,0 +1,467 @@ +export const normal = [ + ["spade", 1, "juedou"], + ["spade", 1, "shandian"], + ["spade", 2, "feilongduofeng"], + ["spade", 2, "bagua"], + ["spade", 2, "hanbing"], + ["spade", 3, "guohe"], + ["spade", 3, "shunshou"], + ["spade", 4, "guohe"], + ["spade", 4, "shunshou"], + ["spade", 5, "sha"], + ["spade", 5, "jueying"], + ["spade", 6, "qinggang"], + ["spade", 6, "sha", "thunder"], + ["spade", 7, "sha"], + ["spade", 7, "sha", "thunder"], + ["spade", 8, "sha"], + ["spade", 8, "sha"], + ["spade", 9, "sha"], + ["spade", 9, "jiu"], + ["spade", 10, "sha"], + ["spade", 10, "bingliang"], + ["spade", 11, "sha"], + ["spade", 11, "wuxie"], + ["spade", 12, "zhangba"], + ["spade", 12, "tiesuo"], + ["spade", 13, "nanman"], + ["spade", 13, "dawan"], + + ["club", 1, "juedou"], + ["club", 1, "baiyin"], + ["club", 2, "sha"], + ["club", 2, "tengjia"], + ["club", 2, "renwang"], + ["club", 3, "sha"], + ["club", 3, "zhibi"], + ["club", 4, "sha"], + ["club", 4, "zhibi"], + ["club", 5, "sha"], + ["club", 5, "dilu"], + ["club", 6, "lebu"], + ["club", 6, "sha", "thunder"], + ["club", 7, "nanman"], + ["club", 7, "sha", "thunder"], + ["club", 8, "sha"], + ["club", 8, "sha", "thunder"], + ["club", 9, "sha"], + ["club", 9, "jiu"], + ["club", 10, "sha"], + ["club", 10, "bingliang"], + ["club", 11, "sha"], + ["club", 11, "sha"], + ["club", 12, "jiedao"], + ["club", 12, "tiesuo"], + ["club", 13, "wuxie", null, ["guo"]], + ["club", 13, "tiesuo"], + + ["diamond", 1, "zhuge"], + ["diamond", 1, "zhuque"], + ["diamond", 2, "shan"], + ["diamond", 2, "tao"], + ["diamond", 3, "shan"], + ["diamond", 3, "shunshou"], + ["diamond", 4, "yiyi"], + ["diamond", 4, "sha", "fire"], + ["diamond", 5, "guanshi"], + ["diamond", 5, "sha", "fire"], + ["diamond", 6, "shan"], + ["diamond", 6, "wuliu"], + ["diamond", 7, "shan"], + ["diamond", 7, "shan"], + ["diamond", 8, "shan"], + ["diamond", 8, "shan"], + ["diamond", 9, "shan"], + ["diamond", 9, "jiu"], + ["diamond", 10, "shan"], + ["diamond", 10, "sha"], + ["diamond", 11, "shan"], + ["diamond", 11, "sha"], + ["diamond", 12, "sha"], + ["diamond", 12, "sanjian"], + ["diamond", 12, "wuxie", null, ["guo"]], + ["diamond", 13, "shan"], + ["diamond", 13, "zixin"], + + ["heart", 1, "taoyuan"], + ["heart", 1, "wanjian"], + ["heart", 2, "shan"], + ["heart", 2, "huogong"], + ["heart", 3, "wugu"], + ["heart", 3, "taipingyaoshu"], + ["heart", 3, "huogong"], + ["heart", 4, "tao"], + ["heart", 4, "sha", "fire"], + ["heart", 5, "qilin"], + ["heart", 5, "chitu"], + ["heart", 6, "tao"], + ["heart", 6, "lebu"], + ["heart", 7, "tao"], + ["heart", 7, "wuzhong"], + ["heart", 8, "tao"], + ["heart", 8, "wuzhong"], + ["heart", 9, "tao"], + ["heart", 9, "yuanjiao"], + ["heart", 10, "tao"], + ["heart", 10, "sha"], + ["heart", 11, "shan"], + ["heart", 11, "yiyi"], + ["heart", 12, "tao"], + ["heart", 12, "sha"], + ["heart", 12, "guohe"], + ["heart", 13, "shan"], + ["heart", 13, "zhuahuang"], + + ["spade", 1, "xietianzi", null, ["lianheng"]], + ["spade", 2, "minguangkai"], + ["spade", 3, "huoshaolianying", null, ["lianheng"]], + ["spade", 4, "sha"], + ["spade", 5, "qinglong"], + ["spade", 6, "jiu", null, ["lianheng"]], + ["spade", 7, "sha"], + ["spade", 8, "sha"], + ["spade", 9, "sha", "thunder"], + ["spade", 10, "sha", "thunder"], + ["spade", 11, "sha", "thunder", ["lianheng"]], + ["spade", 12, "lulitongxin"], + ["spade", 13, "wuxie"], + + ["heart", 1, "lianjunshengyan"], + ["heart", 2, "diaohulishan"], + ["heart", 3, "jingfanma", null, ["lianheng"]], + ["heart", 4, "shan"], + ["heart", 5, "shan"], + ["heart", 6, "shan", null, ["lianheng"]], + ["heart", 7, "shan"], + ["heart", 8, "tao"], + ["heart", 9, "tao"], + ["heart", 10, "sha"], + ["heart", 11, "sha"], + ["heart", 12, "huoshaolianying", null, ["lianheng"]], + ["heart", 13, "shuiyanqijunx"], + + ["club", 1, "yuxi"], + ["club", 2, "huxinjing", null, ["lianheng"]], + ["club", 3, "chiling"], + ["club", 4, "sha"], + ["club", 5, "sha", "thunder", ["lianheng"]], + ["club", 6, "sha"], + ["club", 7, "sha"], + ["club", 8, "sha"], + ["club", 9, "jiu"], + ["club", 10, "lulitongxin"], + ["club", 11, "huoshaolianying", null, ["lianheng"]], + ["club", 12, "shuiyanqijunx"], + ["club", 13, "wuxie", null, ["guo"]], + + ["diamond", 1, "xietianzi", null, ["lianheng"]], + ["diamond", 2, "tao"], + ["diamond", 3, "tao", null, ["lianheng"]], + ["diamond", 4, "xietianzi", null, ["lianheng"]], + ["diamond", 5, "muniu"], + ["diamond", 6, "shan"], + ["diamond", 7, "shan"], + ["diamond", 8, "sha", "fire"], + ["diamond", 9, "sha", "fire"], + ["diamond", 10, "diaohulishan", null, ["lianheng"]], + ["diamond", 11, "wuxie", null, ["guo"]], + ["diamond", 12, "fangtian"], + ["diamond", 13, "shan"], + + ["diamond", 6, "dinglanyemingzhu"], + ["heart", 13, "liulongcanjia"], + + //['spade',12,'gz_haolingtianxia'], + //['diamond',1,'gz_kefuzhongyuan'], + //['heart',1,'gz_guguoanbang'], + //['club',12,'gz_wenheluanwu'], +]; + +export const old = [ + ["spade", 1, "juedou"], + ["spade", 1, "shandian"], + ["spade", 2, "cixiong"], + ["spade", 2, "bagua"], + ["spade", 2, "hanbing"], + ["spade", 3, "guohe"], + ["spade", 3, "shunshou"], + ["spade", 4, "guohe"], + ["spade", 4, "shunshou"], + ["spade", 5, "sha"], + ["spade", 5, "jueying"], + ["spade", 6, "qinggang"], + ["spade", 6, "sha", "thunder"], + ["spade", 7, "sha"], + ["spade", 7, "sha", "thunder"], + ["spade", 8, "sha"], + ["spade", 8, "sha"], + ["spade", 9, "sha"], + ["spade", 9, "jiu"], + ["spade", 10, "sha"], + ["spade", 10, "bingliang"], + ["spade", 11, "sha"], + ["spade", 11, "wuxie"], + ["spade", 12, "zhangba"], + ["spade", 12, "tiesuo"], + ["spade", 13, "nanman"], + ["spade", 13, "dawan"], + + ["club", 1, "juedou"], + ["club", 1, "baiyin"], + ["club", 2, "sha"], + ["club", 2, "tengjia"], + ["club", 2, "renwang"], + ["club", 3, "sha"], + ["club", 3, "zhibi"], + ["club", 4, "sha"], + ["club", 4, "zhibi"], + ["club", 5, "sha"], + ["club", 5, "dilu"], + ["club", 6, "lebu"], + ["club", 6, "sha", "thunder"], + ["club", 7, "nanman"], + ["club", 7, "sha", "thunder"], + ["club", 8, "sha"], + ["club", 8, "sha", "thunder"], + ["club", 9, "sha"], + ["club", 9, "jiu"], + ["club", 10, "sha"], + ["club", 10, "bingliang"], + ["club", 11, "sha"], + ["club", 11, "sha"], + ["club", 12, "jiedao"], + ["club", 12, "tiesuo"], + ["club", 13, "wuxie", null, ["guo"]], + ["club", 13, "tiesuo"], + + ["diamond", 1, "zhuge"], + ["diamond", 1, "zhuque"], + ["diamond", 2, "shan"], + ["diamond", 2, "tao"], + ["diamond", 3, "shan"], + ["diamond", 3, "shunshou"], + ["diamond", 4, "yiyi"], + ["diamond", 4, "sha", "fire"], + ["diamond", 5, "guanshi"], + ["diamond", 5, "sha", "fire"], + ["diamond", 6, "shan"], + ["diamond", 6, "wuliu"], + ["diamond", 7, "shan"], + ["diamond", 7, "shan"], + ["diamond", 8, "shan"], + ["diamond", 8, "shan"], + ["diamond", 9, "shan"], + ["diamond", 9, "jiu"], + ["diamond", 10, "shan"], + ["diamond", 10, "sha"], + ["diamond", 11, "shan"], + ["diamond", 11, "sha"], + ["diamond", 12, "sha"], + ["diamond", 12, "sanjian"], + ["diamond", 12, "wuxie", null, ["guo"]], + ["diamond", 13, "shan"], + ["diamond", 13, "zixin"], + + ["heart", 1, "taoyuan"], + ["heart", 1, "wanjian"], + ["heart", 2, "shan"], + ["heart", 2, "huogong"], + ["heart", 3, "wugu"], + ["heart", 3, "huogong"], + ["heart", 4, "tao"], + ["heart", 4, "sha", "fire"], + ["heart", 5, "qilin"], + ["heart", 5, "chitu"], + ["heart", 6, "tao"], + ["heart", 6, "lebu"], + ["heart", 7, "tao"], + ["heart", 7, "wuzhong"], + ["heart", 8, "tao"], + ["heart", 8, "wuzhong"], + ["heart", 9, "tao"], + ["heart", 9, "yuanjiao"], + ["heart", 10, "tao"], + ["heart", 10, "sha"], + ["heart", 11, "shan"], + ["heart", 11, "yiyi"], + ["heart", 12, "tao"], + ["heart", 12, "sha"], + ["heart", 12, "guohe"], + ["heart", 13, "shan"], + ["heart", 13, "zhuahuang"], +]; + +export const yingbian = [ + //黑桃普通 + ["spade", 1, "shandian"], + ["spade", 1, "xietianzi"], + ["spade", 1, "juedou"], + ["spade", 2, "bagua"], + ["spade", 2, "heiguangkai"], + ["spade", 2, "cixiong"], + ["spade", 2, "taigongyinfu"], + ["spade", 3, "zhujinqiyuan", null, ["yingbian_zhuzhan", "yingbian_add"]], + ["spade", 3, "huoshaolianying"], + ["spade", 3, "shuiyanqijunx", null, ["yingbian_zhuzhan", "yingbian_add"]], + ["spade", 4, "guohe"], + ["spade", 4, "sha"], + ["spade", 4, "shuiyanqijunx", null, ["yingbian_zhuzhan", "yingbian_add"]], + ["spade", 5, "jueying"], + ["spade", 5, "qinglong"], + ["spade", 5, "sha"], + ["spade", 6, "qinggang"], + ["spade", 6, "jiu"], + ["spade", 6, "sha", "ice"], + ["spade", 7, "sha"], + ["spade", 7, "sha"], + ["spade", 7, "sha", "ice"], + ["spade", 8, "sha", "ice"], + ["spade", 8, "sha", "ice"], + ["spade", 8, "sha"], + ["spade", 9, "jiu"], + ["spade", 9, "sha", "thunder"], + ["spade", 9, "sha"], + ["spade", 10, "bingliang"], + ["spade", 10, "sha", "thunder"], + ["spade", 10, "sha", null, ["yingbian_canqu", "yingbian_add"]], + ["spade", 11, "wuxie", null, ["yingbian_kongchao", "yingbian_draw"]], + ["spade", 11, "sha", null, ["yingbian_canqu", "yingbian_add"]], + ["spade", 11, "sha", "thunder"], + ["spade", 12, "zhangba"], + ["spade", 12, "lulitongxin"], + ["spade", 12, "tiesuo"], + ["spade", 13, "wutiesuolian"], + ["spade", 13, "wuxie"], + ["spade", 13, "nanman", null, ["yingbian_fujia", "yingbian_remove"]], + //草花普通 + ["club", 1, "juedou"], + ["club", 1, "yuxi"], + ["club", 1, "huxinjing"], + ["club", 2, "sha"], + ["club", 2, "tianjitu"], + ["club", 2, "renwang"], + ["club", 2, "tengjia"], + ["club", 3, "sha"], + ["club", 3, "chiling"], + ["club", 3, "zhibi"], + ["club", 4, "sha", null, ["yingbian_kongchao", "yingbian_add"]], + ["club", 4, "sha", "thunder"], + ["club", 4, "zhibi"], + ["club", 5, "sha", null, ["yingbian_kongchao", "yingbian_add"]], + ["club", 5, "sha", "thunder"], + ["club", 5, "tongque"], + ["club", 6, "sha", "thunder"], + ["club", 6, "sha", null, ["yingbian_kongchao", "yingbian_add"]], + ["club", 6, "lebu"], + ["club", 7, "sha", "thunder"], + ["club", 7, "sha"], + ["club", 7, "nanman", null, ["yingbian_fujia", "yingbian_remove"]], + ["club", 8, "sha", "thunder"], + ["club", 8, "sha", null, ["yingbian_canqu", "yingbian_add"]], + ["club", 8, "sha"], + ["club", 9, "sha"], + ["club", 9, "jiu"], + ["club", 9, "jiu"], + ["club", 10, "bingliang"], + ["club", 10, "lulitongxin"], + ["club", 10, "sha"], + ["club", 11, "sha"], + ["club", 11, "huoshaolianying"], + ["club", 11, "sha"], + ["club", 12, "zhujinqiyuan", null, ["yingbian_zhuzhan", "yingbian_add"]], + ["club", 12, "jiedao", null, ["yingbian_fujia", "yingbian_hit"]], + ["club", 12, "tiesuo"], + ["club", 13, "tiesuo"], + ["club", 13, "wuxie", null, ["guo"]], + ["club", 13, "wuxie", null, ["guo"]], + //红桃普通 + ["heart", 1, "wanjian"], + ["heart", 1, "taoyuan"], + ["heart", 1, "lianjunshengyan"], + ["heart", 2, "shan"], + ["heart", 2, "chuqibuyi", null, ["yingbian_zhuzhan", "yingbian_add"]], + ["heart", 2, "diaohulishan"], + ["heart", 3, "chuqibuyi", null, ["yingbian_zhuzhan", "yingbian_add"]], + ["heart", 3, "wugu"], + ["heart", 3, "jingfanma"], + ["heart", 4, "tao"], + ["heart", 4, "sha", "fire", ["yingbian_canqu", "yingbian_damage"]], + ["heart", 4, "shan"], + ["heart", 5, "qilin"], + ["heart", 5, "chitu"], + ["heart", 5, "shan", null, ["yingbian_kongchao", "yingbian_draw"]], + ["heart", 6, "lebu"], + ["heart", 6, "tao"], + ["heart", 6, "shan", null, ["yingbian_kongchao", "yingbian_draw"]], + ["heart", 7, "tao"], + ["heart", 7, "dongzhuxianji"], + ["heart", 7, "shan"], + ["heart", 8, "tao"], + ["heart", 8, "dongzhuxianji"], + ["heart", 8, "tao"], + ["heart", 9, "tao"], + ["heart", 9, "yuanjiao"], + ["heart", 9, "tao"], + ["heart", 10, "sha"], + ["heart", 10, "shan"], + ["heart", 10, "sha"], + ["heart", 11, "yiyi"], + ["heart", 11, "tao"], + ["heart", 11, "sha", null, ["yingbian_zhuzhan", "yingbian_add"]], + ["heart", 12, "tao"], + ["heart", 12, "sha"], + ["heart", 12, "huoshaolianying"], + ["heart", 13, "zhuahuang"], + ["heart", 13, "shan"], + ["heart", 13, "huogong", null, ["yingbian_zhuzhan", "yingbian_add"]], + //方片普通 + ["diamond", 1, "wuxinghelingshan"], + ["diamond", 1, "zhuge"], + ["diamond", 1, "xietianzi"], + ["diamond", 2, "shan"], + ["diamond", 2, "tao"], + ["diamond", 2, "tao"], + ["diamond", 3, "shunshou"], + ["diamond", 3, "shan"], + ["diamond", 3, "tao"], + ["diamond", 4, "yiyi"], + ["diamond", 4, "sha", "fire", ["yingbian_canqu", "yingbian_damage"]], + ["diamond", 4, "sha", "fire", ["yingbian_zhuzhan", "yingbian_add"]], + ["diamond", 5, "guanshi"], + ["diamond", 5, "sha", "fire"], + ["diamond", 5, "muniu"], + ["diamond", 6, "wuliu"], + ["diamond", 6, "shan"], + ["diamond", 6, "shan"], + ["diamond", 7, "shan", null, ["yingbian_kongchao", "yingbian_draw"]], + ["diamond", 7, "shan", null, ["yingbian_kongchao", "yingbian_draw"]], + ["diamond", 7, "shan"], + ["diamond", 8, "shan", null, ["yingbian_kongchao", "yingbian_draw"]], + ["diamond", 8, "shan", null, ["yingbian_kongchao", "yingbian_draw"]], + ["diamond", 8, "sha", "fire"], + ["diamond", 9, "jiu"], + ["diamond", 9, "shan"], + ["diamond", 9, "sha", "fire"], + ["diamond", 10, "shan"], + ["diamond", 10, "sha"], + ["diamond", 10, "diaohulishan"], + ["diamond", 11, "sha"], + ["diamond", 11, "shan"], + ["diamond", 11, "wuxie", null, ["guo"]], + ["diamond", 12, "sha"], + ["diamond", 12, "sanjian"], + ["diamond", 12, "wuxie", null, ["guo"]], + ["diamond", 12, "fangtian"], + ["diamond", 13, "zixin"], + ["diamond", 13, "shan"], + ["diamond", 13, "shan"], + //特殊 + ["heart", 3, "taipingyaoshu"], + ["diamond", 4, "dinglanyemingzhu"], + ["heart", 5, "liulongcanjia"], + ["spade", 6, "feilongduofeng"], + ["club", 12, "gz_wenheluanwu"], + ["heart", 1, "gz_guguoanbang"], + ["spade", 12, "gz_haolingtianxia"], + ["diamond", 1, "gz_kefuzhongyuan"], +]; diff --git a/mode/guozhan/src/info/rank.js b/mode/guozhan/src/info/rank.js new file mode 100644 index 0000000000..2fc11867b2 --- /dev/null +++ b/mode/guozhan/src/info/rank.js @@ -0,0 +1,21 @@ +export const aozhan = { + 8: ["gz_ol_lisu", "gz_panjun"], + 7: ["gz_zhongyan", "gz_yangyan"], + 6: ["gz_caoang", "gz_xianglang", "gz_wangyi"], + 5: ["gz_re_panshu", "gz_lukang", "gz_caoren", "gz_lvfan", "gz_machao", "gz_ganfuren", "gz_madai", "gz_jiling", "gz_pangde", "gz_huangzu"], + 4: ["gz_caozhen", "gz_re_lidian", "gz_yuejin", "gz_huangzhong", "gz_menghuo", "gz_sunshangxiang", "gz_lvmeng", "gz_lvbu", "gz_xiahouba", "gz_chendao", "gz_tw_tianyu"], + 3: ["gz_mazhong", "gz_tengyin", "gz_simayi", "gz_luxun", "gz_wuguotai", "gz_caiwenji", "gz_shibao", "gz_xuyou", "gz_zhugeke", "gz_re_nanhualaoxian", "gz_zhouyi"], + 2: ["gz_bulianshi", "gz_maliang", "gz_re_lusu", "gz_zhangzhang", "gz_jin_simashi", "gz_jin_zhangchunhua", "gz_zhugejin"], + 1: ["gz_caocao", "gz_guojia", "gz_xiahoudun", "gz_xunyu", "gz_caopi", "gz_liubei", "gz_fazheng", "gz_dongzhuo", "gz_yuji", "gz_liqueguosi", "gz_huanggai", "gz_re_xushu", "gz_panjun", "gz_yangxiu"], +}; + +export const guozhan = { + 8: ["gz_xurong", "gz_xunyou", "gz_re_lidian", "gz_caopi", "gz_shamoke", "gz_lifeng", "gz_wangping", "gz_xiaoqiao", "gz_zhoutai", "gz_lvfan", "gz_beimihu", "gz_mateng", "gz_jiaxu", "gz_jin_wangyuanji", "gz_huaxin", "gz_duyu", "gz_zhonghui", "gz_xuyou", "gz_simazhao"], + 7: ["gz_xianglang", "gz_wangyi", "gz_zhanghe", "gz_jianggan", "gz_simayi", "gz_weiyan", "gz_huangyueying", "gz_zhugeliang", "gz_lingtong", "gz_sunshangxiang", "gz_sunce", "gz_re_yuanshao", "gz_yuanshu", "gz_hetaihou", "gz_jin_simashi", "gz_sp_duyu", "gz_shibao", "gz_gongsunyuan", "gz_panjun", "gz_re_nanhualaoxian", "gz_xin_zhuran", "gz_jin_jiachong", "gz_jin_yanghu"], + 6: ["gz_caoang", "gz_tengyin", "gz_wangji", "gz_zhenji", "gz_guojia", "gz_yujin", "gz_jiangwei", "gz_zhangfei", "gz_sp_zhugeliang", "gz_zhouyu", "gz_lingcao", "gz_daqiao", "gz_dingfeng", "gz_yuji", "gz_caiwenji", "gz_diaochan", "gz_zuoci", "gz_key_ushio", "gz_jin_simazhao", "gz_dongzhao", "gz_liuba", "gz_zhouyi", "gz_re_xunchen", "gz_fuwan", "gz_zhugejin", "gz_yangxiu", "gz_yangyan", "gz_tw_tianyu", "gz_yangwan", "gz_wangling"], + 5: ["gz_bulianshi", "gz_re_panshu", "gz_zhangliao", "gz_caocao", "gz_xuhuang", "gz_liushan", "gz_pangtong", "gz_zhaoyun", "gz_re_lusu", "gz_sunquan", "gz_ganning", "gz_zhangxiu", "gz_liqueguosi", "gz_huatuo", "gz_zhanghuyuechen", "gz_re_xushu", "gz_mifangfushiren", "gz_huangzu", "gz_weiguan", "gz_miheng", "gz_wenqin", "gz_zumao", "gz_xuangongzhu", "gz_tw_xiahoushang"], + 4: ["gz_mazhong", "gz_caozhen", "gz_dianwei", "gz_dengai", "gz_xunyu", "gz_madai", "gz_liubei", "gz_mifuren", "gz_wuguotai", "gz_luxun", "gz_re_taishici", "gz_zhangjiao", "gz_pangde", "gz_liuqi", "gz_jin_zhangchunhua", "gz_zongyu", "gz_shixie", "gz_jin_yanghuiyu", "gz_tangzi", "gz_yanbaihu", "gz_wujing", "gz_zhugeke", "gz_sunchen", "gz_liaohua", "gz_zhongyan", "gz_xinchang", "gz_tw_liufuren"], + 3: ["gz_maliang", "gz_xiahoudun", "gz_yuejin", "gz_caoren", "gz_machao", "gz_masu", "gz_fazheng", "gz_zhangzhang", "gz_lvmeng", "gz_huanggai", "gz_jiling", "gz_lvbu", "gz_dongzhuo", "gz_jin_xiahouhui", "gz_simazhou", "gz_zhanglu", "gz_chendao", "gz_yangzhi", "gz_old_huaxiong", "gz_gaoshun"], + 2: ["gz_cuimao", "gz_xiahouyuan", "gz_caohong", "gz_zhurong", "gz_zhurong", "gz_jiangfei", "gz_xusheng", "gz_luyusheng", "gz_sunjian", "gz_zhangren", "gz_kongrong", "gz_yanwen", "gz_jin_simayi", "gz_mengda", "gz_xiahouba"], + 1: ["gz_zangba", "gz_bianfuren", "gz_xuzhu", "gz_menghuo", "gz_ganfuren", "gz_guanyu", "gz_lukang", "gz_jiangqing", "gz_chendong", "gz_zoushi", "gz_panfeng", "gz_tianfeng", "gz_sufei", "gz_yanyan"], +}; diff --git a/mode/guozhan/src/patch/content.js b/mode/guozhan/src/patch/content.js index 322337d863..1eeeb660ab 100644 --- a/mode/guozhan/src/patch/content.js +++ b/mode/guozhan/src/patch/content.js @@ -1,9 +1,11 @@ import { lib, game as _game, ui, get as _get, ai, _status } from "../../../../noname.js"; -import { GameEvent, Dialog, Player, Control, Button, Character } from "../../../../noname/library/element/index.js"; +import { GameEvent, Dialog, Player as _Player, Control, Button, Character } from "../../../../noname/library/element/index.js"; import { GameGuozhan, broadcast, broadcastAll } from "./game.js"; import { GetGuozhan } from "./get.js"; import { delay } from "../../../../noname/util/index.js"; +import { PlayerGuozhan as Player } from "./player.js"; + /** @type {GameGuozhan} */ // @ts-expect-error 类型就是这么定的 const game = _game; @@ -1032,6 +1034,7 @@ export async function showYexingsContent(event, _trigger, player) { export async function hideCharacter(event, _trigger, player) { const { num } = event; + // @ts-expect-error 类型就是这么写的 game.addVideo("hideCharacter", player, num); const log = Reflect.get(event, "log"); @@ -1095,7 +1098,7 @@ export async function hideCharacter(event, _trigger, player) { player.skills.remove(skills[i]); } - + player.checkConflict(); } @@ -1114,6 +1117,7 @@ export async function chooseJunlingFor(event, _trigger, player) { const junlings = junlingNames.map(name => ["军令", "", name]); if (target != undefined && !prompt) { + // @ts-expect-error 类型就是这么写的 const selfPrompt = target == player ? "(你)" : ""; prompt = `选择一张军令牌,令${get.translation(target)}${selfPrompt}选择是否执行`; } @@ -1134,7 +1138,7 @@ export async function chooseJunlingFor(event, _trigger, player) { if (result.junling == "junling1") { /** @type {Player[]} */ - // @ts-expect-error 祖宗之法就是这么写的 + // @ts-expect-error 祖宗之法就是这么做的 const targets = await player .chooseTarget("选择一名角色,做为若该军令被执行,受到伤害的角色", true) .set("ai", other => get.damageEffect(other, target, player)) @@ -1149,7 +1153,325 @@ export async function chooseJunlingFor(event, _trigger, player) { Reflect.set(event, "result", result); } +/** + * @param {GameEvent} event + * @param {GameEvent} _trigger + * @param {Player} player + */ +export async function chooseJunlingControl(event, _trigger, player) { + const dialog = []; + // @ts-expect-error 类型就是这么写的 + const str1 = event.source == player ? "(你)" : ""; + const str2 = event.targets ? `(被指定的角色为${get.translation(event.targets)})` : ""; + + const prompt = Reflect.get(event, "prompt"); + if (prompt) { + dialog.add(prompt); + } + dialog.add(`${get.translation(event.source)}${str1}选择的军令${str2}为`); + dialog.add([[Reflect.get(event, "junling")], "vcard"]); + + let controls = []; + + const choiceList = Reflect.get(event, "choiceList"); + if (choiceList) { + for (let i = 0; i < choiceList.length; i++) { + dialog.add('"); + controls.push("选项" + get.cnNumber(i + 1, true)); + } + } else if (Reflect.has(event, "controls")) { + controls = Reflect.get(event, "controls"); + } else { + controls = ["执行该军令", "不执行该军令"]; + } + + if (!event.ai) { + event.ai = () => { + return Math.floor(controls.length * Math.random()); + }; + } + + const result = await player.chooseControl(controls).set("dialog", dialog).set("ai", event.ai).forResult(); + const result2 = { + index: result.index, + control: result.control, + }; + Reflect.set(event, "result", result2); +} + +/** + * @param {GameEvent & { junling: string }} event + * @param {GameEvent} _trigger + * @param {Player} player + */ +export async function carryOutJunling(event, _trigger, player) { + const { source, targets } = event; + + switch (event.junling) { + case "junling1": { + if (targets[0].isAlive()) { + player.line(targets, "green"); + await targets[0].damage(player); + } + break; + } + case "junling2": + await player.draw(); + + // @ts-expect-error 类型就是这么写的 + if (source == player) { + break; + } + + for (let i = 0; i < 2 && player.countCards("he") > 0; i++) { + const { result } = await player.chooseCard("交给" + get.translation(source) + "第" + get.cnNumber(i + 1) + "张牌(共两张)", "he", true); + if (result.cards.length) { + await player.give(result.cards, source); + } + } + + break; + case "junling3": + await player.loseHp(); + break; + case "junling4": + player.addTempSkill("junling4_eff"); + player.addTempSkill("fengyin_vice"); + player.addTempSkill("fengyin_main"); + break; + case "junling5": + await player.turnOver(); + player.addTempSkill("junling5_eff"); + break; + case "junling6": { + let position = ""; + let num0 = 0; + if (player.countCards("h")) { + position += "h"; + num0++; + } + if (player.countCards("e")) { + position += "e"; + num0++; + } + const { result } = await player + .chooseCard( + "选择一张手牌和一张装备区内牌(若有),然后弃置其余的牌", + position, + num0, + card => { + if (ui.selected.cards.length) return get.position(card) != get.position(ui.selected.cards[0]); + return true; + }, + true + ) + .set("complexCard", true) + .set("ai", function (card) { + return get.value(card); + }); + + const cards = player.getCards("he"); + for (const card of result.cards) { + cards.remove(card); + } + player.discard(cards); + } + } +} + +/** + * @param {GameEvent} _event + * @param {GameEvent} _trigger + * @param {Player} player + */ +export async function doubleDraw(_event, _trigger, player) { + if (!player.hasMark("yinyang_mark")) { + player.addMark("yinyang_mark", 1); + } +} + +/** + * @param {GameEvent & { hidden: boolean }} event + * @param {GameEvent} _trigger + * @param {Player} player + */ +export async function changeViceOnline(event, _trigger, player) { + await player.showCharacter(2); + const group = lib.character[player.name1].group; + const characterlist = Reflect.get(_status, "characterlist"); + characterlist?.randomSort(); + let name; + for (let i = 0; i < characterlist.length; i++) { + let goon = false; + const group2 = lib.character[characterlist[i]].group; + if (game.hasPlayer2(current => get.nameList(current).includes(characterlist[i]))) { + continue; + } + if (group == "ye") { + if (group2 != "ye") goon = true; + } else { + if (group == group2) { + goon = true; + } else { + const double = get.is.double(characterlist[i], ["true"]); + if (double && (typeof double == "boolean" || double.includes(group))) { + goon = true; + } + } + } + if (goon) { + name = characterlist[i]; + break; + } + } + if (!name) { + return; + } + characterlist.remove(name); + + let change = false; + if (player.hasViceCharacter()) { + change = true; + characterlist.add(player.name2); + } + + if (change) { + event.trigger("removeCharacterBefore"); + } + if (event.hidden) { + if (!player.isUnseen(1)) { + await player.hideCharacter(1); + } + } + + if (event.hidden) { + game.log(player, "替换了副将", "#g" + get.translation(player.name2)); + } else { + game.log(player, "将副将从", "#g" + get.translation(player.name2), "变更为", "#g" + get.translation(name)); + } + // @ts-expect-error 类型就是这么写的 + player.viceChanged = true; + await player.reinitCharacter(player.name2, name, false); +} + +export const changeVice = [ + async (event, _trigger, player) => { + player.showCharacter(2); + if (!event.num) event.num = 3; + var group = player.identity; + if (!lib.group.includes(group)) group = lib.character[player.name1][1]; + // @ts-expect-error 类型就是这么写的 + _status.characterlist.randomSort(); + event.tochange = []; + // @ts-expect-error 类型就是这么写的 + for (var i = 0; i < _status.characterlist.length; i++) { + // @ts-expect-error 类型就是这么写的 + if (_status.characterlist[i].indexOf("gz_jun_") == 0) continue; + // @ts-expect-error 类型就是这么写的 + if (game.hasPlayer2(current => get.nameList(current).includes(_status.characterlist[i]))) continue; + var goon = false, + // @ts-expect-error 类型就是这么写的 + group2 = lib.character[_status.characterlist[i]][1]; + if (group == "ye") { + if (group2 != "ye") goon = true; + } else { + if (group == group2) goon = true; + else { + // @ts-expect-error 类型就是这么写的 + var double = get.is.double(_status.characterlist[i], true); + // @ts-expect-error 类型就是这么写的 + if (double && double.includes(group)) goon = true; + } + } + if (goon) { + // @ts-expect-error 类型就是这么写的 + event.tochange.push(_status.characterlist[i]); + if (event.tochange.length == event.num) break; + } + } + if (!event.tochange.length) event.finish(); + else { + if (event.tochange.length == 1) + event._result = { + bool: true, + links: event.tochange, + }; + else + player.chooseButton(true, ["选择要变更的武将牌", [event.tochange, "character"]]).ai = function (button) { + // @ts-expect-error 类型就是这么写的 + return get.guozhanRank(button.link); + }; + } + }, + async (event, _trigger, player, result) => { + var name = result.links[0]; + // @ts-expect-error 类型就是这么写的 + _status.characterlist.remove(name); + if (player.hasViceCharacter()) { + event.change = true; + // @ts-expect-error 类型就是这么写的 + _status.characterlist.add(player.name2); + } + event.toRemove = player.name2; + event.toChange = name; + if (event.change) event.trigger("removeCharacterBefore"); + if (event.hidden) { + if (!player.isUnseen(1)) player.hideCharacter(1); + } + }, + async (event, _trigger, player) => { + var name = event.toChange; + if (event.hidden) game.log(player, "替换了副将", "#g" + get.translation(player.name2)); + else game.log(player, "将副将从", "#g" + get.translation(player.name2), "变更为", "#g" + get.translation(name)); + player.viceChanged = true; + player.reinitCharacter(player.name2, name, false); + }, +]; + +/** + * @param {GameEvent} event + * @param {GameEvent} _trigger + * @param {Player} player + */ +export async function mayChangeVice(event, _trigger, player) { + const result = await player.chooseBool("是否变更副将?").set("ai", function () { + const player = get.player(); + // @ts-expect-error 祖宗之法就是这么写的 + return get.guozhanRank(player.name2, player) <= 3; + }).forResult(); + if (result.bool) { + // @ts-expect-error 祖宗之法就是这么做的 + if (!event.repeat) { + // @ts-expect-error 祖宗之法就是这么做的 + if (!_status.changedSkills[player.playerid]) _status.changedSkills[player.playerid] = []; + // @ts-expect-error 祖宗之法就是这么做的 + _status.changedSkills[player.playerid].add(event.skill); + } + // @ts-expect-error 祖宗之法就是这么做的 + await player.changeVice(event.hidden); + } +} + +/** + * + * @param {GameEvent} _event + * @param {GameEvent} _trigger + * @param {Player} player + */ +export async function zhulian(_event, _trigger, player) { + player.popup("珠联璧合"); + if (!player.hasMark("zhulianbihe_mark")) { + player.addMark("zhulianbihe_mark", 1); + } +} + export default Object.freeze({ hideCharacter, chooseJunlingFor, + chooseJunlingControl, + carryOutJunling, + doubleDraw, + changeViceOnline, + changeVice, + mayChangeVice, }); diff --git a/mode/guozhan/src/patch/player.js b/mode/guozhan/src/patch/player.js index 58a692680b..ab735a4740 100644 --- a/mode/guozhan/src/patch/player.js +++ b/mode/guozhan/src/patch/player.js @@ -31,9 +31,9 @@ export class PlayerGuozhan extends Player { /** * 选择军令 - * - * @param {Player} target - * @returns + * + * @param {Player} target + * @returns */ chooseJunlingFor(target) { const next = game.createEvent("chooseJunlingFor"); @@ -45,7 +45,650 @@ export class PlayerGuozhan extends Player { // @ts-expect-error 类型就是这么写的 next.setContent("chooseJunlingFor"); - + return next; } + + /** + * 选择军令 + * + * @param {Player} source + * @param {string} junling + * @param {Player[]} targets + */ + chooseJunlingControl(source, junling, targets) { + const next = game.createEvent("chooseJunlingControl"); + // @ts-expect-error 类型就是这么写的 + next.player = this; + next.source = source; + // @ts-expect-error 类型就是这么写的 + next.junling = junling; + if (targets.length) next.targets = targets; + // @ts-expect-error 类型就是这么写的 + next.setContent("chooseJunlingControl"); + return next; + } + + /** + * 执行军令 + * + * @param {Player} source + * @param {string} junling + * @param {Player[]} targets + * @returns + */ + carryOutJunling(source, junling, targets) { + const next = game.createEvent("carryOutJunling"); + next.source = source; + // @ts-expect-error 类型就是这么写的 + next.player = this; + if (targets.length) next.targets = targets; + // @ts-expect-error 类型就是这么写的 + next.junling = junling; + // @ts-expect-error 类型就是这么写的 + next.setContent("carryOutJunling"); + return next; + } + + /** + * + * @param {*} repeat + * @param {*} hidden + * @returns + */ + mayChangeVice(repeat, hidden) { + if (!this.playerid) { + return; + } + const changedSkills = Reflect.get(_status, "changedSkills") ?? {}; + Reflect.set(_status, "changedSkills", changedSkills); + const skill = _status.event?.name; + if (repeat || !changedSkills[this.playerid] || !changedSkills[this.playerid].includes(skill)) { + var next = game.createEvent("mayChangeVice"); + // @ts-expect-error 类型就是这么写的 + next.setContent("mayChangeVice"); + // @ts-expect-error 类型就是这么写的 + next.player = this; + // @ts-expect-error 类型就是这么写的 + next.skill = skill; + // @ts-expect-error 类型就是这么写的 + if (repeat || (!_status.connectMode && get.config("changeViceType") == "online")) next.repeat = true; + // @ts-expect-error 类型就是这么写的 + if (hidden == "hidden") next.hidden = true; + return next; + } + } + + // 后面摆了,相信后人的智慧 + + differentIdentityFrom(target, self) { + if (this == target) return false; + if (this.getStorage("yexinjia_friend").includes(target)) return false; + if (target.getStorage("yexinjia_friend").includes(this)) return false; + if (self) { + if (target.identity == "unknown") return false; + if (target.identity == "ye" || this.identity == "ye") return true; + if (this.identity == "unknown") { + var identity = lib.character[this.name1][1]; + if (this.wontYe()) return identity != target.identity; + return true; + } + } else { + if (this.identity == "unknown" || target.identity == "unknown") return false; + if (this.identity == "ye" || target.identity == "ye") return true; + } + return this.identity != target.identity; + } + sameIdentityAs(target, shown) { + if (this.getStorage("yexinjia_friend").includes(target)) return true; + if (target.getStorage("yexinjia_friend").includes(this)) return true; + if (shown) { + if (this.identity == "ye" || this.identity == "unknown") return false; + } else { + if (this == target) return true; + if (target.identity == "unknown" || target.identity == "ye" || this.identity == "ye") return false; + if (this.identity == "unknown") { + var identity = lib.character[this.name1][1]; + if (this.wontYe()) return identity == target.identity; + return false; + } + } + return this.identity == target.identity; + } + getModeState() { + return { + unseen: this.isUnseen(0), + unseen2: this.isUnseen(1), + }; + } + setModeState(info) { + if (info.mode.unseen) this.classList.add("unseen"); + if (info.mode.unseen2) this.classList.add("unseen2"); + if (!info.name) return; + // if(info.name.indexOf('unknown')==0){ + // if(this==game.me){ + // lib.translate[info.name]+='(你)'; + // } + // } + this.init(info.name1, info.name2, false); + this.name1 = info.name1; + this.name = info.name; + this.node.name_seat = ui.create.div(".name.name_seat", get.verticalStr(lib.translate[this.name].slice(0, 3)), this); + if (info.identityShown) { + this.setIdentity(info.identity); + this.node.identity.classList.remove("guessing"); + // @ts-expect-error 类型就是这么写的 + } else if (this != game.me) { + // @ts-expect-error 类型就是这么写的 + this.node.identity.firstChild.innerHTML = "猜"; + this.node.identity.dataset.color = "unknown"; + this.node.identity.classList.add("guessing"); + } + } + dieAfter2(source) { + var that = this; + if (that.hasSkillTag("noDieAfter", null, source)) return; + if (source && source.hasSkillTag("noDieAfter2", null, that)) return; + if (source && source.shijun) { + source.discard(source.getCards("he")); + delete source.shijun; + } else if (source && source.identity != "unknown") { + if (source.identity == "ye" && !source.getStorage("yexinjia_friend").length) source.draw(3); + else if (source.shijun2) { + delete source.shijun2; + source.draw( + 1 + + game.countPlayer(function (current) { + return current.group == that.group; + }) + ); + } else if (that.identity == "ye") { + if (that.getStorage("yexinjia_friend").includes(source) || source.getStorage("yexinjia_friend").includes(that)) source.discard(source.getCards("he")); + else + source.draw( + 1 + + game.countPlayer(function (current) { + // @ts-expect-error 类型就是这么写的 + if (current == that) return false; + if (current.getStorage("yexinjia_friend").includes(that)) return true; + if (that.getStorage("yexinjia_friend").includes(current)) return true; + return false; + }) + ); + } else if (that.identity != source.identity) source.draw(get.population(that.identity) + 1); + else source.discard(source.getCards("he")); + } + } + dieAfter(source) { + this.showCharacter(2); + if (get.is.jun(this.name1)) { + if (source && source.identity == this.identity) source.shijun = true; + else if (source && source.identity != "ye") source.shijun2 = true; + var yelist = []; + for (var i = 0; i < game.players.length; i++) { + if (game.players[i].identity == this.identity) { + yelist.push(game.players[i]); + } + } + // @ts-expect-error 类型就是这么写的 + game.broadcastAll(function (list) { + for (var i = 0; i < list.length; i++) { + list[i].identity = "ye"; + list[i].setIdentity(); + } + }, yelist); + // @ts-expect-error 类型就是这么写的 + _status.yeidentity.add(this.identity); + } + // @ts-expect-error 类型就是这么写的 + game.tryResult(); + } + viewCharacter(target, num) { + if (num != 0 && num != 1) { + num = 2; + } + if (!target.isUnseen(num)) { + return; + } + var next = game.createEvent("viewCharacter"); + // @ts-expect-error 类型就是这么写的 + next.player = this; + next.target = target; + next.num = num; + next.setContent(function () { + // @ts-expect-error 类型就是这么写的 + if (!player.storage.zhibi) { + // @ts-expect-error 类型就是这么写的 + player.storage.zhibi = []; + } + // @ts-expect-error 类型就是这么写的 + player.storage.zhibi.add(target); + var content, + str = get.translation(target) + "的"; + // @ts-expect-error 类型就是这么写的 + if (event.num == 0 || !target.isUnseen(1)) { + content = [str + "主将", [[target.name1], "character"]]; + // @ts-expect-error 类型就是这么写的 + game.log(player, "观看了", target, "的主将"); + // @ts-expect-error 类型就是这么写的 + } else if (event.num == 1 || !target.isUnseen(0)) { + content = [str + "副将", [[target.name2], "character"]]; + // @ts-expect-error 类型就是这么写的 + game.log(player, "观看了", target, "的副将"); + } else { + content = [str + "主将和副将", [[target.name1, target.name2], "character"]]; + // @ts-expect-error 类型就是这么写的 + game.log(player, "观看了", target, "的主将和副将"); + } + // @ts-expect-error 类型就是这么写的 + player.chooseControl("ok").set("dialog", content); + }); + } + checkViceSkill(skill, disable) { + if (game.expandSkills(lib.character[this.name2][3].slice(0)).includes(skill)) { + return true; + } else { + if (disable !== false) { + this.awakenSkill(skill); + } + return false; + } + } + checkMainSkill(skill, disable) { + if (game.expandSkills(lib.character[this.name1][3].slice(0)).includes(skill)) { + return true; + } else { + if (disable !== false) { + this.awakenSkill(skill); + } + return false; + } + } + removeMaxHp(num) { + if (game.online) return; + if (!num) num = 1; + while (num > 0) { + num--; + if (typeof this.singleHp == "boolean") { + if (this.singleHp) { + this.singleHp = false; + } else { + this.singleHp = true; + this.maxHp--; + } + } else { + this.maxHp--; + } + } + this.update(); + } + hideCharacter(num, log) { + if (this.isUnseen(2)) return; + var name = this["name" + (num + 1)]; + var next = game.createEvent("hideCharacter"); + // @ts-expect-error 类型就是这么写的 + next.player = this; + // @ts-expect-error 类型就是这么写的 + next.toHide = name; + next.num = num; + // @ts-expect-error 类型就是这么写的 + next.log = log; + // @ts-expect-error 类型就是这么写的 + next.setContent("hideCharacter"); + return next; + } + removeCharacter(num) { + var name = this["name" + (num + 1)]; + var next = game.createEvent("removeCharacter"); + // @ts-expect-error 类型就是这么写的 + next.player = this; + // @ts-expect-error 类型就是这么写的 + next.toRemove = name; + next.num = num; + next.setContent("removeCharacter"); + return next; + } + $removeCharacter(num) { + var name = this["name" + (num + 1)]; + var info = lib.character[name]; + if (!info) return; + var to = "gz_shibing" + (info[0] == "male" ? 1 : 2) + info[1]; + game.log(this, "移除了" + (num ? "副将" : "主将"), "#b" + name); + this.reinit(name, to, false); + this.showCharacter(num, false); + // @ts-expect-error 类型就是这么写的 + _status.characterlist.add(name); + } + changeVice(hidden) { + var next = game.createEvent("changeVice"); + // @ts-expect-error 类型就是这么写的 + next.player = this; + // @ts-expect-error 类型就是这么写的 + next.setContent("changeVice"); + next.num = !_status.connectMode && get.config("changeViceType") == "online" ? 1 : 3; + // @ts-expect-error 类型就是这么写的 + if (hidden) next.hidden = true; + return next; + } + hasMainCharacter() { + return this.name1.indexOf("gz_shibing") != 0; + } + hasViceCharacter() { + return this.name2.indexOf("gz_shibing") != 0; + } + $showCharacter(num, log) { + var showYe = false; + if (num == 0 && !this.isUnseen(0)) { + return; + } + if (num == 1 && !this.isUnseen(1)) { + return; + } + if (!this.isUnseen(2)) { + return; + } + // @ts-expect-error 类型就是这么写的 + game.addVideo("showCharacter", this, num); + if (this.identity == "unknown" || ((num == 0 || num == 2) && lib.character[this.name1][1] == "ye")) { + this.group = this.getGuozhanGroup(num); + if ((num == 0 || num == 2) && lib.character[this.name1][1] == "ye") { + this.identity = "ye"; + if (!this._ye) { + this._ye = true; + showYe = true; + } + } else if (get.is.jun(this.name1) && this.isAlive()) { + this.identity = this.group; + } else if (this.wontYe(this.group)) { + this.identity = this.group; + } else { + this.identity = "ye"; + } + this.setIdentity(this.identity); + this.ai.shown = 1; + this.node.identity.classList.remove("guessing"); + + // @ts-expect-error 类型就是这么写的 + if (_status.clickingidentity && _status.clickingidentity[0] == this) { + // @ts-expect-error 类型就是这么写的 + for (var i = 0; i < _status.clickingidentity[1].length; i++) { + // @ts-expect-error 类型就是这么写的 + _status.clickingidentity[1][i].delete(); + // @ts-expect-error 类型就是这么写的 + _status.clickingidentity[1][i].style.transform = ""; + } + // @ts-expect-error 类型就是这么写的 + delete _status.clickingidentity; + } + // @ts-expect-error 类型就是这么写的 + game.addVideo("setIdentity", this, this.identity); + } + var skills; + switch (num) { + case 0: + if (log !== false) game.log(this, "展示了主将", "#b" + this.name1); + this.name = this.name1; + skills = lib.character[this.name][3]; + this.sex = lib.character[this.name][0]; + this.classList.remove("unseen"); + break; + case 1: + if (log !== false) game.log(this, "展示了副将", "#b" + this.name2); + skills = lib.character[this.name2][3]; + if (this.sex == "unknown") this.sex = lib.character[this.name2][0]; + if (this.name.indexOf("unknown") == 0) this.name = this.name2; + this.classList.remove("unseen2"); + break; + case 2: + if (log !== false) game.log(this, "展示了主将", "#b" + this.name1, "、副将", "#b" + this.name2); + this.name = this.name1; + skills = lib.character[this.name][3].concat(lib.character[this.name2][3]); + this.sex = lib.character[this.name][0]; + this.classList.remove("unseen"); + this.classList.remove("unseen2"); + break; + } + game.broadcast( + // @ts-expect-error 类型就是这么写的 + function (player, name, sex, num, identity, group) { + player.identityShown = true; + player.group = group; + player.name = name; + player.sex = sex; + player.node.identity.classList.remove("guessing"); + switch (num) { + case 0: + player.classList.remove("unseen"); + break; + case 1: + player.classList.remove("unseen2"); + break; + case 2: + player.classList.remove("unseen"); + player.classList.remove("unseen2"); + break; + } + player.ai.shown = 1; + player.identity = identity; + player.setIdentity(identity); + // @ts-expect-error 类型就是这么写的 + if (_status.clickingidentity && _status.clickingidentity[0] == player) { + // @ts-expect-error 类型就是这么写的 + for (var i = 0; i < _status.clickingidentity[1].length; i++) { + // @ts-expect-error 类型就是这么写的 + _status.clickingidentity[1][i].delete(); + // @ts-expect-error 类型就是这么写的 + _status.clickingidentity[1][i].style.transform = ""; + } + // @ts-expect-error 类型就是这么写的 + delete _status.clickingidentity; + } + }, + this, + this.name, + this.sex, + num, + this.identity, + this.group + ); + this.identityShown = true; + // @ts-expect-error 类型就是这么写的 + for (var i = 0; i < skills.length; i++) { + // @ts-expect-error 类型就是这么写的 + this.hiddenSkills.remove(skills[i]); + // @ts-expect-error 类型就是这么写的 + this.addSkill(skills[i]); + } + this.checkConflict(); + // @ts-expect-error 类型就是这么写的 + if (!this.viceChanged) { + var initdraw = get.config("initshow_draw"); + if (_status.connectMode) initdraw = lib.configOL.initshow_draw; + // @ts-expect-error 类型就是这么写的 + if (!_status.initshown && !_status.overing && initdraw != "off" && this.isAlive() && _status.mode != "mingjiang") { + this.popup("首亮"); + if (initdraw == "draw") { + game.log(this, "首先明置武将,得到奖励"); + game.log(this, "摸了两张牌"); + // @ts-expect-error 类型就是这么写的 + this.draw(2).log = false; + } else { + this.addMark("xianqu_mark", 1); + } + // @ts-expect-error 类型就是这么写的 + _status.initshown = true; + } + if (!this.isUnseen(2) && !this._mingzhied) { + this._mingzhied = true; + if (this.singleHp) { + this.doubleDraw(); + } + if (this.perfectPair()) { + var next = game.createEvent("guozhanDraw"); + // @ts-expect-error 类型就是这么写的 + next.player = this; + // @ts-expect-error 类型就是这么写的 + next.setContent("zhulian"); + } + } + if (showYe) { + this.addMark("yexinjia_mark", 1); + } + } + // @ts-expect-error 类型就是这么写的 + game.tryResult(); + } + wontYe(group, numOfReadyToShow) { + if (!group) { + if (this.trueIdentity) group = this.trueIdentity; + else group = lib.character[this.name1][1]; + } + // @ts-expect-error 类型就是这么写的 + if (_status.yeidentity && _status.yeidentity.includes(group)) return false; + if (get.zhu(this, null, group)) return true; + if (!numOfReadyToShow) numOfReadyToShow = 1; + // @ts-expect-error 类型就是这么写的 + return get.totalPopulation(group) + numOfReadyToShow <= (_status.separatism ? Math.max(get.population() / 2 - 1, 1) : get.population() / 2); + } + perfectPair(choosing) { + if (_status.connectMode) { + if (!lib.configOL.zhulian) return false; + } else { + if (!get.config("zhulian")) return false; + } + var name1 = this.name1; + var name2 = this.name2; + if (name1.indexOf("gz_shibing") == 0) return false; + if (name2.indexOf("gz_shibing") == 0) return false; + if (get.is.jun(this.name1)) return true; + if (choosing && lib.character[name1][1] != "ye" && lib.character[name2][1] != "ye" && lib.character[name1][1] != lib.character[name2][1]) return false; + if (name1.indexOf("gz_") == 0) { + name1 = name1.slice(name1.indexOf("_") + 1); + } else { + while (name1.indexOf("_") != -1 && !lib.perfectPair[name1]) { + name1 = name1.slice(name1.indexOf("_") + 1); + } + } + if (name2.indexOf("gz_") == 0) { + name2 = name2.slice(name2.indexOf("_") + 1); + } else { + while (name2.indexOf("_") != -1 && !lib.perfectPair[name2]) { + name2 = name2.slice(name2.indexOf("_") + 1); + } + } + var list = Object.keys(lib.perfectPair).concat(Object.values(lib.perfectPair)).flat(); + if (!list.includes(name1) || !list.includes(name2)) return false; + return (lib.perfectPair[name1] && lib.perfectPair[name1].flat(Infinity).includes(name2)) || (lib.perfectPair[name2] && lib.perfectPair[name2].flat(Infinity).includes(name1)); + } + siege(player) { + if (this.identity == "unknown" || this.hasSkill("undist")) return false; + if (!player) { + var next = this.getNext(); + // @ts-expect-error 类型就是这么写的 + if (next && next.sieged()) return true; + var previous = this.getPrevious(); + // @ts-expect-error 类型就是这么写的 + if (previous && previous.sieged()) return true; + return false; + } else { + return player.sieged() && (player.getNext() == this || player.getPrevious() == this); + } + } + sieged(player) { + if (this.identity == "unknown") return false; + if (player) { + return player.siege(this); + } else { + var next = this.getNext(); + var previous = this.getPrevious(); + if (next && previous && next != previous) { + if (next.identity == "unknown" || next.isFriendOf(this)) return false; + return next.isFriendOf(previous); + } + return false; + } + } + inline() { + if (this.identity == "unknown" || this.identity == "ye" || this.hasSkill("undist")) return false; + var next = this, + previous = this; + var list = []; + for (var i = 0; next || previous; i++) { + if (next) { + // @ts-expect-error 类型就是这么写的 + next = next.getNext(); + if (!next.isFriendOf(this) || next == this) { + // @ts-expect-error 类型就是这么写的 + next = null; + } else { + list.add(next); + } + } + if (previous) { + // @ts-expect-error 类型就是这么写的 + previous = previous.getPrevious(); + if (!previous.isFriendOf(this) || previous == this) { + // @ts-expect-error 类型就是这么写的 + previous = null; + } else { + list.add(previous); + } + } + } + if (!list.length) return false; + for (var i = 0; i < arguments.length; i++) { + if (!list.includes(arguments[i]) && arguments[i] != this) return false; + } + return true; + } + logAi(targets, card) { + if (this.ai.shown == 1 || this.isMad()) return; + if (typeof targets == "number") { + // @ts-expect-error 类型就是这么写的 + this.ai.shown += targets; + } else { + var effect = 0, + c, + shown; + var info = get.info(card); + if (info.ai && info.ai.expose) { + // @ts-expect-error 类型就是这么写的 + if (_status.event.name == "_wuxie") { + // @ts-expect-error 类型就是这么写的 + if (_status.event.source && _status.event.source.ai.shown) { + // @ts-expect-error 类型就是这么写的 + this.ai.shown += 0.2; + } + } else { + // @ts-expect-error 类型就是这么写的 + this.ai.shown += info.ai.expose; + } + } + if (targets.length > 0) { + for (var i = 0; i < targets.length; i++) { + shown = Math.abs(targets[i].ai.shown); + if (shown < 0.2 || targets[i].identity == "nei") c = 0; + else if (shown < 0.4) c = 0.5; + else if (shown < 0.6) c = 0.8; + else c = 1; + effect += get.effect(targets[i], card, this) * c; + } + } + if (effect > 0) { + if (effect < 1) c = 0.5; + else c = 1; + // @ts-expect-error 类型就是这么写的 + if (targets.length == 1 && targets[0] == this); + else if (targets.length == 1) + // @ts-expect-error 类型就是这么写的 + this.ai.shown += 0.2 * c; + // @ts-expect-error 类型就是这么写的 + else this.ai.shown += 0.1 * c; + } + } + // @ts-expect-error 类型就是这么写的 + if (this.ai.shown > 0.95) this.ai.shown = 0.95; + // @ts-expect-error 类型就是这么写的 + if (this.ai.shown < -0.5) this.ai.shown = -0.5; + } } diff --git a/mode/guozhan/src/skill/index.js b/mode/guozhan/src/skill/index.js new file mode 100644 index 0000000000..e69de29bb2 From e271c2b8f14bca289e0665aa31a74a267191e231 Mon Sep 17 00:00:00 2001 From: Rintim Date: Tue, 8 Apr 2025 09:27:01 +0800 Subject: [PATCH 23/48] feat: try to make the first format. --- mode/guozhan.js | 16 +-- mode/guozhan/src/character/index.js | 131 +++++++++++++++++++++ mode/guozhan/src/character/normal.js | 0 mode/guozhan/src/patch/content.js | 2 +- mode/guozhan/src/skill/card/.gitkeep | 0 mode/guozhan/src/skill/character/normal.js | 0 mode/guozhan/src/skill/index.js | 1 + 7 files changed, 135 insertions(+), 15 deletions(-) create mode 100644 mode/guozhan/src/character/index.js create mode 100644 mode/guozhan/src/character/normal.js create mode 100644 mode/guozhan/src/skill/card/.gitkeep create mode 100644 mode/guozhan/src/skill/character/normal.js diff --git a/mode/guozhan.js b/mode/guozhan.js index 7bed7c5a1e..634315a53e 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -1,6 +1,7 @@ import { lib, game, ui, get, ai, _status } from "../noname.js"; import { start, startBefore, onreinit } from "./guozhan/src/main.js"; import { gamePatch, getPatch, contentPatch, playerPatch } from "./guozhan/src/patch/index.js"; +import { pack } from "./guozhan/src/character/index.js"; import * as info from "./guozhan/src/info/index.js"; import card from "./guozhan/src/card/index.js"; import help from "./guozhan/src/help/index.js"; @@ -48,20 +49,7 @@ export default () => { }, characterPack: { mode_guozhan: { - gz_shibing1wei: ["male", "wei", 0, [], ["unseen"]], - gz_shibing2wei: ["female", "wei", 0, [], ["unseen"]], - gz_shibing1shu: ["male", "shu", 0, [], ["unseen"]], - gz_shibing2shu: ["female", "shu", 0, [], ["unseen"]], - gz_shibing1wu: ["male", "wu", 0, [], ["unseen"]], - gz_shibing2wu: ["female", "wu", 0, [], ["unseen"]], - gz_shibing1qun: ["male", "qun", 0, [], ["unseen"]], - gz_shibing2qun: ["female", "qun", 0, [], ["unseen"]], - gz_shibing1jin: ["male", "jin", 0, [], ["unseen"]], - gz_shibing2jin: ["female", "jin", 0, [], ["unseen"]], - gz_shibing1ye: ["male", "ye", 0, [], ["unseen"]], - gz_shibing2ye: ["female", "ye", 0, [], ["unseen"]], - gz_shibing1key: ["male", "key", 0, [], ["unseen"]], - gz_shibing2key: ["female", "key", 0, [], ["unseen"]], + ...pack, gz_zhonghui: ["male", "ye", 4, ["fakequanji", "fakepaiyi"], ["gzskin"]], gz_simazhao: ["male", "ye", 3, ["gzzhaoxin", "gzsuzhi"], ["gzskin"]], diff --git a/mode/guozhan/src/character/index.js b/mode/guozhan/src/character/index.js new file mode 100644 index 0000000000..f3d0b3ba72 --- /dev/null +++ b/mode/guozhan/src/character/index.js @@ -0,0 +1,131 @@ +import { Character } from "../../../../noname/library/element/index.js"; + +/** @type {Record} */ +export const pack = { + gz_shibing1wei: new Character({ + sex: "male", + group: "wei", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), + gz_shibing2wei: new Character({ + sex: "female", + group: "wei", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), + gz_shibing1shu: new Character({ + sex: "male", + group: "shu", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), + gz_shibing2shu: new Character({ + sex: "female", + group: "shu", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), + gz_shibing1wu: new Character({ + sex: "male", + group: "wu", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), + gz_shibing2wu: new Character({ + sex: "female", + group: "wu", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), + gz_shibing1qun: new Character({ + sex: "male", + group: "qun", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), + gz_shibing2qun: new Character({ + sex: "female", + group: "qun", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), + gz_shibing1jin: new Character({ + sex: "male", + group: "jin", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), + gz_shibing2jin: new Character({ + sex: "female", + group: "jin", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), + gz_shibing1ye: new Character({ + sex: "male", + group: "ye", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), + gz_shibing2ye: new Character({ + sex: "female", + group: "ye", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), + gz_shibing1key: new Character({ + sex: "male", + group: "key", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), + gz_shibing2key: new Character({ + sex: "female", + group: "key", + hp: 0, + maxHp: 0, + hujia: 0, + skills: [], + isUnseen: true, + }), +}; diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mode/guozhan/src/patch/content.js b/mode/guozhan/src/patch/content.js index 1eeeb660ab..117a201cbd 100644 --- a/mode/guozhan/src/patch/content.js +++ b/mode/guozhan/src/patch/content.js @@ -87,7 +87,7 @@ export async function chooseCharacterContent(event, _trigger, _player) { Reflect.deleteProperty(ui, name); } - if (result.buttons) { + if (result?.buttons) { /** @type {string} */ // @ts-expect-error 祖宗之法就是这么写的 const name1 = result.buttons[0].link; diff --git a/mode/guozhan/src/skill/card/.gitkeep b/mode/guozhan/src/skill/card/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mode/guozhan/src/skill/index.js b/mode/guozhan/src/skill/index.js index e69de29bb2..21f2c30d13 100644 --- a/mode/guozhan/src/skill/index.js +++ b/mode/guozhan/src/skill/index.js @@ -0,0 +1 @@ +export default Object.freeze({}); From 13d6b740c536c6edfc00770202bafe458a809a8c Mon Sep 17 00:00:00 2001 From: Rintim Date: Tue, 8 Apr 2025 10:02:36 +0800 Subject: [PATCH 24/48] feat: write the first normal character. --- mode/guozhan.js | 37 ++------------ mode/guozhan/src/character/index.js | 4 ++ mode/guozhan/src/character/normal.js | 12 +++++ mode/guozhan/src/skill/character/index.js | 5 ++ mode/guozhan/src/skill/character/normal.js | 51 +++++++++++++++++++ mode/guozhan/src/skill/index.js | 6 ++- mode/guozhan/src/translate/card/index.js | 23 +++++++++ mode/guozhan/src/translate/character/index.js | 5 ++ .../guozhan/src/translate/character/normal.js | 3 ++ mode/guozhan/src/translate/index.js | 19 +++++++ .../guozhan/src/translate/skill/card/.gitkeep | 0 .../src/translate/skill/character/index.js | 5 ++ .../src/translate/skill/character/normal.js | 4 ++ mode/guozhan/src/translate/skill/index.js | 5 ++ 14 files changed, 146 insertions(+), 33 deletions(-) create mode 100644 mode/guozhan/src/skill/character/index.js create mode 100644 mode/guozhan/src/translate/card/index.js create mode 100644 mode/guozhan/src/translate/character/index.js create mode 100644 mode/guozhan/src/translate/character/normal.js create mode 100644 mode/guozhan/src/translate/index.js create mode 100644 mode/guozhan/src/translate/skill/card/.gitkeep create mode 100644 mode/guozhan/src/translate/skill/character/index.js create mode 100644 mode/guozhan/src/translate/skill/character/normal.js create mode 100644 mode/guozhan/src/translate/skill/index.js diff --git a/mode/guozhan.js b/mode/guozhan.js index 634315a53e..9f418fdc92 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -3,6 +3,8 @@ import { start, startBefore, onreinit } from "./guozhan/src/main.js"; import { gamePatch, getPatch, contentPatch, playerPatch } from "./guozhan/src/patch/index.js"; import { pack } from "./guozhan/src/character/index.js"; import * as info from "./guozhan/src/info/index.js"; +import skill from "./guozhan/src/skill/index.js"; +import translate from "./guozhan/src/translate/index.js"; import card from "./guozhan/src/card/index.js"; import help from "./guozhan/src/help/index.js"; @@ -88,7 +90,6 @@ export default () => { gz_mazhong: ["male", "shu", 4, ["twfuman"]], gz_ol_lisu: ["male", "qun", 3, ["qiaoyan", "xianzhu"]], - gz_caocao: ["male", "wei", 4, ["rejianxiong_old"]], gz_simayi: ["male", "wei", 3, ["fankui", "guicai"]], gz_xiahoudun: ["male", "wei", 4, ["reganglie"]], gz_zhangliao: ["male", "wei", 4, ["new_retuxi"]], @@ -263,6 +264,8 @@ export default () => { }, }, skill: { + ...skill, + //国战典藏2024-2025,启动! //国战限定 //卑弥呼 @@ -19255,37 +19258,7 @@ export default () => { }, }, translate: { - yexinjia_mark: "野心家", - - bumingzhi: "不明置", - mingzhizhujiang: "明置主将", - mingzhifujiang: "明置副将", - tongshimingzhi: "同时明置", - mode_guozhan_character_config: "国战武将", - _zhenfazhaohuan: "阵法召唤", - _zhenfazhaohuan_info: "由拥有阵法技的角色发起,满足此阵法技条件的未确定势力角色均可按逆时针顺序依次明置其一张武将牌(响应阵法召唤),以发挥阵法技的效果。", - - junling: "军令", - junling1: "军令一", - junling1_bg: "令", - junling1_info: "若被执行,执行者对发起者指定的一名角色造成1点伤害。", - junling2: "军令二", - junling2_bg: "令", - junling2_info: "若被执行,执行者摸一张牌,然后依次交给发起者两张牌。", - junling3: "军令三", - junling3_bg: "令", - junling3_info: "若被执行,执行者失去1点体力。", - junling4: "军令四", - junling4_bg: "令", - junling4_info: "若被执行,直到回合结束,执行者不能使用或打出手牌且非锁定技全部失效。", - junling4_eff: "军令四", - junling5: "军令五", - junling5_bg: "令", - junling5_info: "若被执行,执行者将武将牌叠置,且不能回复体力直到回合结束。", - junling5_eff: "军令五", - junling6: "军令六", - junling6_bg: "令", - junling6_info: "若被执行,执行者选择一张手牌和一张装备区内牌(若有),然后弃置其余的牌。", + ...translate, gz_miheng: "祢衡", gzshensu: "神速", diff --git a/mode/guozhan/src/character/index.js b/mode/guozhan/src/character/index.js index f3d0b3ba72..663680c8d1 100644 --- a/mode/guozhan/src/character/index.js +++ b/mode/guozhan/src/character/index.js @@ -1,5 +1,7 @@ import { Character } from "../../../../noname/library/element/index.js"; +import normal from "./normal.js"; + /** @type {Record} */ export const pack = { gz_shibing1wei: new Character({ @@ -128,4 +130,6 @@ export const pack = { skills: [], isUnseen: true, }), + + ...normal, }; diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index e69de29bb2..d9e53c720b 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -0,0 +1,12 @@ +import { Character } from "../../../../noname/library/element/index.js"; + +export default Object.freeze({ + gz_caocao: new Character({ + sex: "male", + group: "wei", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_jianxiong"], + }), +}); diff --git a/mode/guozhan/src/skill/character/index.js b/mode/guozhan/src/skill/character/index.js new file mode 100644 index 0000000000..ed0399629e --- /dev/null +++ b/mode/guozhan/src/skill/character/index.js @@ -0,0 +1,5 @@ +import normal from "./normal.js"; + +export default Object.freeze({ + ...normal, +}); diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index e69de29bb2..5a1901ad2d 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -0,0 +1,51 @@ +import { lib, game, ui, get, ai, _status } from "../../../../../noname.js"; + +export default Object.freeze({ + gz_jianxiong: { + audio: "jianxiong", + trigger: { player: "damageEnd" }, + async cost(event, trigger, player) { + let list = ["摸牌"]; + if (get.itemtype(trigger.cards) == "cards" && trigger.cards.filterInD().length) { + list.push("拿牌"); + } + list.push("cancel2"); + const { + result: { control }, + } = await player + .chooseControl(list) + .set("prompt", get.prompt2("rejianxiong_old")) + .set("ai", () => { + const player = get.event("player"), + trigger = get.event().getTrigger(); + const cards = trigger.cards ? trigger.cards.filterInD() : []; + // @ts-expect-error 类型就是这么写的 + if (get.event().controls.includes("拿牌")) { + if ( + cards.reduce((sum, card) => { + return sum + (card.name == "du" ? -1 : 1); + }, 0) > 1 || + player.getUseValue(cards[0]) > 6 + ) + return "拿牌"; + } + return "摸牌"; + }); + event.result = { bool: control != "cancel2", cost_data: control }; + }, + async content(event, trigger, player) { + if (event.cost_data == "摸牌") await player.draw(); + else await player.gain(trigger.cards.filterInD(), "gain2"); + }, + ai: { + maixie: true, + maixie_hp: true, + effect: { + target(card, player, target) { + if (player.hasSkillTag("jueqing", false, target)) return [1, -1]; + if (get.tag(card, "damage") && player != target) return [1, 0.6]; + }, + }, + }, + }, +}); diff --git a/mode/guozhan/src/skill/index.js b/mode/guozhan/src/skill/index.js index 21f2c30d13..68f1446c6f 100644 --- a/mode/guozhan/src/skill/index.js +++ b/mode/guozhan/src/skill/index.js @@ -1 +1,5 @@ -export default Object.freeze({}); +import character from "./character/index.js"; + +export default Object.freeze({ + ...character, +}); diff --git a/mode/guozhan/src/translate/card/index.js b/mode/guozhan/src/translate/card/index.js new file mode 100644 index 0000000000..50df485164 --- /dev/null +++ b/mode/guozhan/src/translate/card/index.js @@ -0,0 +1,23 @@ +export default Object.freeze({ + junling: "军令", + junling1: "军令一", + junling1_bg: "令", + junling1_info: "若被执行,执行者对发起者指定的一名角色造成1点伤害。", + junling2: "军令二", + junling2_bg: "令", + junling2_info: "若被执行,执行者摸一张牌,然后依次交给发起者两张牌。", + junling3: "军令三", + junling3_bg: "令", + junling3_info: "若被执行,执行者失去1点体力。", + junling4: "军令四", + junling4_bg: "令", + junling4_info: "若被执行,直到回合结束,执行者不能使用或打出手牌且非锁定技全部失效。", + junling4_eff: "军令四", + junling5: "军令五", + junling5_bg: "令", + junling5_info: "若被执行,执行者将武将牌叠置,且不能回复体力直到回合结束。", + junling5_eff: "军令五", + junling6: "军令六", + junling6_bg: "令", + junling6_info: "若被执行,执行者选择一张手牌和一张装备区内牌(若有),然后弃置其余的牌。", +}); diff --git a/mode/guozhan/src/translate/character/index.js b/mode/guozhan/src/translate/character/index.js new file mode 100644 index 0000000000..ed0399629e --- /dev/null +++ b/mode/guozhan/src/translate/character/index.js @@ -0,0 +1,5 @@ +import normal from "./normal.js"; + +export default Object.freeze({ + ...normal, +}); diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js new file mode 100644 index 0000000000..792ec46865 --- /dev/null +++ b/mode/guozhan/src/translate/character/normal.js @@ -0,0 +1,3 @@ +export default Object.freeze({ + gz_caocao: "曹操", +}); diff --git a/mode/guozhan/src/translate/index.js b/mode/guozhan/src/translate/index.js new file mode 100644 index 0000000000..a63c7b31c9 --- /dev/null +++ b/mode/guozhan/src/translate/index.js @@ -0,0 +1,19 @@ +import card from "./card/index.js"; +import character from "./character/index.js"; +import skill from "./skill/index.js"; + +export default Object.freeze({ + yexinjia_mark: "野心家", + + bumingzhi: "不明置", + mingzhizhujiang: "明置主将", + mingzhifujiang: "明置副将", + tongshimingzhi: "同时明置", + mode_guozhan_character_config: "国战武将", + _zhenfazhaohuan: "阵法召唤", + _zhenfazhaohuan_info: "由拥有阵法技的角色发起,满足此阵法技条件的未确定势力角色均可按逆时针顺序依次明置其一张武将牌(响应阵法召唤),以发挥阵法技的效果。", + + ...card, + ...character, + ...skill, +}); diff --git a/mode/guozhan/src/translate/skill/card/.gitkeep b/mode/guozhan/src/translate/skill/card/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mode/guozhan/src/translate/skill/character/index.js b/mode/guozhan/src/translate/skill/character/index.js new file mode 100644 index 0000000000..ed0399629e --- /dev/null +++ b/mode/guozhan/src/translate/skill/character/index.js @@ -0,0 +1,5 @@ +import normal from "./normal.js"; + +export default Object.freeze({ + ...normal, +}); diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js new file mode 100644 index 0000000000..14930e1c51 --- /dev/null +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -0,0 +1,4 @@ +export default Object.freeze({ + gz_jianxiong: "奸雄", + gz_jianxiong_info: "当你受到伤害后,你可以摸一张牌或获得对你造成伤害的牌。", +}); diff --git a/mode/guozhan/src/translate/skill/index.js b/mode/guozhan/src/translate/skill/index.js new file mode 100644 index 0000000000..68f1446c6f --- /dev/null +++ b/mode/guozhan/src/translate/skill/index.js @@ -0,0 +1,5 @@ +import character from "./character/index.js"; + +export default Object.freeze({ + ...character, +}); From 3061c645c6e824ebb26208cf79d744f434b46e3c Mon Sep 17 00:00:00 2001 From: Rintim Date: Tue, 8 Apr 2025 14:03:14 +0800 Subject: [PATCH 25/48] refactor: remove freeze in export. --- mode/guozhan/src/card/index.js | 4 ++-- mode/guozhan/src/character/normal.js | 4 ++-- mode/guozhan/src/patch/content.js | 4 ++-- mode/guozhan/src/skill/character/index.js | 4 ++-- mode/guozhan/src/skill/character/normal.js | 4 ++-- mode/guozhan/src/skill/index.js | 4 ++-- mode/guozhan/src/translate/card/index.js | 4 ++-- mode/guozhan/src/translate/character/index.js | 4 ++-- mode/guozhan/src/translate/character/normal.js | 4 ++-- mode/guozhan/src/translate/index.js | 4 ++-- mode/guozhan/src/translate/skill/character/index.js | 4 ++-- mode/guozhan/src/translate/skill/character/normal.js | 4 ++-- mode/guozhan/src/translate/skill/index.js | 4 ++-- 13 files changed, 26 insertions(+), 26 deletions(-) diff --git a/mode/guozhan/src/card/index.js b/mode/guozhan/src/card/index.js index 54002ccb60..bedc797b48 100644 --- a/mode/guozhan/src/card/index.js +++ b/mode/guozhan/src/card/index.js @@ -1,5 +1,5 @@ -export default Object.freeze({ +export default { junling1: { type: "junling", vanish: true, @@ -33,4 +33,4 @@ export default Object.freeze({ zhulian_card: { cardimage: "wuzhong", }, -}); +} ; diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index d9e53c720b..b20597c0b0 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -1,6 +1,6 @@ import { Character } from "../../../../noname/library/element/index.js"; -export default Object.freeze({ +export default { gz_caocao: new Character({ sex: "male", group: "wei", @@ -9,4 +9,4 @@ export default Object.freeze({ hujia: 0, skills: ["gz_jianxiong"], }), -}); +}; diff --git a/mode/guozhan/src/patch/content.js b/mode/guozhan/src/patch/content.js index 117a201cbd..1c4d02be66 100644 --- a/mode/guozhan/src/patch/content.js +++ b/mode/guozhan/src/patch/content.js @@ -1465,7 +1465,7 @@ export async function zhulian(_event, _trigger, player) { } } -export default Object.freeze({ +export default { hideCharacter, chooseJunlingFor, chooseJunlingControl, @@ -1474,4 +1474,4 @@ export default Object.freeze({ changeViceOnline, changeVice, mayChangeVice, -}); +}; diff --git a/mode/guozhan/src/skill/character/index.js b/mode/guozhan/src/skill/character/index.js index ed0399629e..87a7fae07b 100644 --- a/mode/guozhan/src/skill/character/index.js +++ b/mode/guozhan/src/skill/character/index.js @@ -1,5 +1,5 @@ import normal from "./normal.js"; -export default Object.freeze({ +export default { ...normal, -}); +}; diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index 5a1901ad2d..fea2b6a690 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -1,6 +1,6 @@ import { lib, game, ui, get, ai, _status } from "../../../../../noname.js"; -export default Object.freeze({ +export default { gz_jianxiong: { audio: "jianxiong", trigger: { player: "damageEnd" }, @@ -48,4 +48,4 @@ export default Object.freeze({ }, }, }, -}); +}; diff --git a/mode/guozhan/src/skill/index.js b/mode/guozhan/src/skill/index.js index 68f1446c6f..ae82ff8398 100644 --- a/mode/guozhan/src/skill/index.js +++ b/mode/guozhan/src/skill/index.js @@ -1,5 +1,5 @@ import character from "./character/index.js"; -export default Object.freeze({ +export default { ...character, -}); +}; diff --git a/mode/guozhan/src/translate/card/index.js b/mode/guozhan/src/translate/card/index.js index 50df485164..5f2a4edcfb 100644 --- a/mode/guozhan/src/translate/card/index.js +++ b/mode/guozhan/src/translate/card/index.js @@ -1,4 +1,4 @@ -export default Object.freeze({ +export default { junling: "军令", junling1: "军令一", junling1_bg: "令", @@ -20,4 +20,4 @@ export default Object.freeze({ junling6: "军令六", junling6_bg: "令", junling6_info: "若被执行,执行者选择一张手牌和一张装备区内牌(若有),然后弃置其余的牌。", -}); +}; diff --git a/mode/guozhan/src/translate/character/index.js b/mode/guozhan/src/translate/character/index.js index ed0399629e..87a7fae07b 100644 --- a/mode/guozhan/src/translate/character/index.js +++ b/mode/guozhan/src/translate/character/index.js @@ -1,5 +1,5 @@ import normal from "./normal.js"; -export default Object.freeze({ +export default { ...normal, -}); +}; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index 792ec46865..be9f888a4a 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -1,3 +1,3 @@ -export default Object.freeze({ +export default { gz_caocao: "曹操", -}); +}; diff --git a/mode/guozhan/src/translate/index.js b/mode/guozhan/src/translate/index.js index a63c7b31c9..c201e47d12 100644 --- a/mode/guozhan/src/translate/index.js +++ b/mode/guozhan/src/translate/index.js @@ -2,7 +2,7 @@ import card from "./card/index.js"; import character from "./character/index.js"; import skill from "./skill/index.js"; -export default Object.freeze({ +export default { yexinjia_mark: "野心家", bumingzhi: "不明置", @@ -16,4 +16,4 @@ export default Object.freeze({ ...card, ...character, ...skill, -}); +}; diff --git a/mode/guozhan/src/translate/skill/character/index.js b/mode/guozhan/src/translate/skill/character/index.js index ed0399629e..87a7fae07b 100644 --- a/mode/guozhan/src/translate/skill/character/index.js +++ b/mode/guozhan/src/translate/skill/character/index.js @@ -1,5 +1,5 @@ import normal from "./normal.js"; -export default Object.freeze({ +export default { ...normal, -}); +}; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index 14930e1c51..cb6d660f33 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -1,4 +1,4 @@ -export default Object.freeze({ +export default { gz_jianxiong: "奸雄", gz_jianxiong_info: "当你受到伤害后,你可以摸一张牌或获得对你造成伤害的牌。", -}); +}; diff --git a/mode/guozhan/src/translate/skill/index.js b/mode/guozhan/src/translate/skill/index.js index 68f1446c6f..ae82ff8398 100644 --- a/mode/guozhan/src/translate/skill/index.js +++ b/mode/guozhan/src/translate/skill/index.js @@ -1,5 +1,5 @@ import character from "./character/index.js"; -export default Object.freeze({ +export default { ...character, -}); +}; From 5bd39dd1f3f0498ba281db32d4e9f678a6a7213a Mon Sep 17 00:00:00 2001 From: Rintim Date: Tue, 8 Apr 2025 14:19:56 +0800 Subject: [PATCH 26/48] fix: add missing method to export. --- mode/guozhan/src/patch/content.js | 1 + 1 file changed, 1 insertion(+) diff --git a/mode/guozhan/src/patch/content.js b/mode/guozhan/src/patch/content.js index 1c4d02be66..d5b0387023 100644 --- a/mode/guozhan/src/patch/content.js +++ b/mode/guozhan/src/patch/content.js @@ -1474,4 +1474,5 @@ export default { changeViceOnline, changeVice, mayChangeVice, + zhulian, }; From 98c0ca98e5a1cff140e99e66d9e98f44e1156e4d Mon Sep 17 00:00:00 2001 From: Rintim Date: Tue, 8 Apr 2025 14:27:29 +0800 Subject: [PATCH 27/48] fix: type hint of `Character`. --- noname/library/element/character.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noname/library/element/character.js b/noname/library/element/character.js index 648de03e63..4a9ed298f6 100644 --- a/noname/library/element/character.js +++ b/noname/library/element/character.js @@ -176,7 +176,7 @@ export class Character { */ isNull = false; /** - * @param { Object|[string, string, string|number, string[], any[]|undefined, any[]|undefined] } [data] + * @param { [Sex | "", string, string|number, string[], any[]|undefined, any[]|undefined] | Partial<{ [key in keyof Character]: Character[key] }> } [data] */ constructor(data) { if (Array.isArray(data)) { From b6f3b57d52d1714fea1976743806e462d39370e9 Mon Sep 17 00:00:00 2001 From: Rintim Date: Tue, 8 Apr 2025 14:39:24 +0800 Subject: [PATCH 28/48] pref: make result parital to avoid some problem (and cost more problems) --- noname/library/element/gameEvent.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/noname/library/element/gameEvent.js b/noname/library/element/gameEvent.js index 811edbb8c4..2023596f0a 100644 --- a/noname/library/element/gameEvent.js +++ b/noname/library/element/gameEvent.js @@ -36,7 +36,7 @@ export class GameEvent { return "GameEvent"; } /** - * @type { Result } + * @type { Partial } */ result; /** @@ -1164,7 +1164,7 @@ export class GameEvent { * @template {keyof Result} T * @this GameEvent * @overload - * @returns {Promise} + * @returns {Promise>} * * @overload * @param {T} param0 From 7bccee64d46755fa369b5fa73056635570e73f3a Mon Sep 17 00:00:00 2001 From: Rintim Date: Tue, 8 Apr 2025 14:42:33 +0800 Subject: [PATCH 29/48] feat: rewrite `gz_xiahoudun` to new format. --- mode/guozhan.js | 2 - mode/guozhan/src/character/normal.js | 18 ++++- mode/guozhan/src/skill/character/normal.js | 80 ++++++++++++++++++- .../guozhan/src/translate/character/normal.js | 2 + .../src/translate/skill/character/normal.js | 3 + 5 files changed, 98 insertions(+), 7 deletions(-) diff --git a/mode/guozhan.js b/mode/guozhan.js index 9f418fdc92..24e8edc829 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -90,8 +90,6 @@ export default () => { gz_mazhong: ["male", "shu", 4, ["twfuman"]], gz_ol_lisu: ["male", "qun", 3, ["qiaoyan", "xianzhu"]], - gz_simayi: ["male", "wei", 3, ["fankui", "guicai"]], - gz_xiahoudun: ["male", "wei", 4, ["reganglie"]], gz_zhangliao: ["male", "wei", 4, ["new_retuxi"]], gz_xuzhu: ["male", "wei", 4, ["gzluoyi"]], gz_guojia: ["male", "wei", 3, ["tiandu", "gzyiji"], ["gzskin"]], diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index b20597c0b0..88b60dc201 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -9,4 +9,20 @@ export default { hujia: 0, skills: ["gz_jianxiong"], }), -}; + gz_simayi: new Character({ + sex: "male", + group: "wei", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["guicai", "fankui"], + }), + gz_xiahoudun: new Character({ + sex: "male", + group: "wei", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_ganglie"], + }), +} diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index fea2b6a690..ce13aad80c 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -1,9 +1,19 @@ import { lib, game, ui, get, ai, _status } from "../../../../../noname.js"; +import { GameEvent } from "../../../../../noname/library/element/gameEvent.js"; +import { PlayerGuozhan } from "../../patch/player.js"; export default { + // gz_caocao gz_jianxiong: { audio: "jianxiong", - trigger: { player: "damageEnd" }, + trigger: { + player: "damageEnd", + }, + /** + * @param {GameEvent} event + * @param {GameEvent} trigger + * @param {PlayerGuozhan} player + */ async cost(event, trigger, player) { let list = ["摸牌"]; if (get.itemtype(trigger.cards) == "cards" && trigger.cards.filterInD().length) { @@ -31,11 +41,19 @@ export default { } return "摸牌"; }); - event.result = { bool: control != "cancel2", cost_data: control }; + event.result = { bool: control != "cancel2", cost_data: { result: control } }; }, + /** + * @param {GameEvent} event + * @param {GameEvent} trigger + * @param {PlayerGuozhan} player + */ async content(event, trigger, player) { - if (event.cost_data == "摸牌") await player.draw(); - else await player.gain(trigger.cards.filterInD(), "gain2"); + if (event.cost_data.result == "摸牌") { + await player.draw(); + } else { + await player.gain(trigger.cards.filterInD(), "gain2"); + } }, ai: { maixie: true, @@ -48,4 +66,58 @@ export default { }, }, }, + + // gz_xiahoudun + gz_ganglie: { + audio: "ganglie", // TODO: 改成独立的配音 + trigger: { + player: "damageEnd", + }, + /** + * @param {GameEvent} event + * @param {PlayerGuozhan} _player + * @returns {boolean} + */ + filter(event, _player) { + return event.source != undefined && event.num > 0; + }, + /** + * @param {GameEvent} event + * @param {PlayerGuozhan} player + * @returns {boolean} + */ + check(event, player) { + return get.attitude(player, event.source) <= 0; + }, + logTarget: "source", + preHidden: true, + /** + * @param {GameEvent} event + * @param {GameEvent} trigger + * @param {PlayerGuozhan} player + */ + async content(event, trigger, player) { + const result = await player.judge(card => (get.color(card) == "red" ? 1 : 0)).forResult(); + + switch (result.color) { + case "black": + if (trigger.source.countCards("he")) { + player.discardPlayerCard(trigger.source, "he", true); + } + break; + + case "red": + if (trigger.source.isIn()) { + trigger.source.damage(); + } + break; + default: + break; + } + }, + ai: { + maixie_defend: true, + expose: 0.4, + }, + }, }; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index be9f888a4a..0d20d51718 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -1,3 +1,5 @@ export default { gz_caocao: "曹操", + gz_simayi: "司马懿", + gz_xiahoudun: "夏侯惇", }; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index cb6d660f33..8f2b45a4e5 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -1,4 +1,7 @@ export default { gz_jianxiong: "奸雄", gz_jianxiong_info: "当你受到伤害后,你可以摸一张牌或获得对你造成伤害的牌。", + + gz_ganglie: "刚烈", + gz_ganglie_info: "当你受到伤害后,你可进行判定,若结果为:红色,你对伤害来源造成1点伤害;黑色,你弃置伤害来源一张牌。", }; From c246353b10b3df0d471297f4c53f7895018652ba Mon Sep 17 00:00:00 2001 From: Rintim Date: Tue, 8 Apr 2025 16:15:52 +0800 Subject: [PATCH 30/48] feat: rewrite `gz_zhangliao` in new format of mode character. --- mode/guozhan.js | 1 - mode/guozhan/src/character/normal.js | 10 ++- mode/guozhan/src/skill/character/normal.js | 67 ++++++++++++++++++- .../guozhan/src/translate/character/normal.js | 1 + .../src/translate/skill/character/normal.js | 3 + 5 files changed, 79 insertions(+), 3 deletions(-) diff --git a/mode/guozhan.js b/mode/guozhan.js index 24e8edc829..03f62d162a 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -90,7 +90,6 @@ export default () => { gz_mazhong: ["male", "shu", 4, ["twfuman"]], gz_ol_lisu: ["male", "qun", 3, ["qiaoyan", "xianzhu"]], - gz_zhangliao: ["male", "wei", 4, ["new_retuxi"]], gz_xuzhu: ["male", "wei", 4, ["gzluoyi"]], gz_guojia: ["male", "wei", 3, ["tiandu", "gzyiji"], ["gzskin"]], gz_zhenji: ["female", "wei", 3, ["luoshen", "qingguo"], ["gzskin"]], diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index 88b60dc201..6d9b5d1130 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -25,4 +25,12 @@ export default { hujia: 0, skills: ["gz_ganglie"], }), -} + gz_zhangliao: new Character({ + sex: "male", + group: "wei", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_tuxi"], + }), // ["male", "wei", 4, ["new_retuxi"]] +}; diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index ce13aad80c..c45379a26f 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -1,5 +1,5 @@ import { lib, game, ui, get, ai, _status } from "../../../../../noname.js"; -import { GameEvent } from "../../../../../noname/library/element/gameEvent.js"; +import { GameEvent, Player } from "../../../../../noname/library/element/index.js"; import { PlayerGuozhan } from "../../patch/player.js"; export default { @@ -120,4 +120,69 @@ export default { expose: 0.4, }, }, + + // gz_zhangliao + gz_tuxi: { + audio: "tuxi", // TODO: 改成独立的配音 + audioname2: { + gz_jun_caocao: "jianan_tuxi", + }, + trigger: { + player: "phaseDrawBegin2", + }, + preHidden: true, + /** + * @param {GameEvent} event + * @param {PlayerGuozhan | Player} player + * @returns {boolean} + */ + filter(event, player) { + // @ts-expect-error 类型就是这么写的 + return event.num > 0 && !event.numFixed && game.hasPlayer(target => target.countCards("h") > 0 && player != target); + }, + /** + * @param {GameEvent} event + * @param {GameEvent} trigger + * @param {PlayerGuozhan} player + */ + async cost(event, trigger, player) { + const num = Math.min(trigger.num, 2); + + const next = player.chooseTarget( + get.prompt("gz_tuxi"), + `获得至多${get.translation(num)}名角色的各一张手牌,然后少摸等量的牌`, + [1, num], + (_card, player, target) => target.countCards("h") > 0 && player != target, + target => { + const att = get.attitude(_status.event?.player, target); + if (target.hasSkill("tuntian")) { + return att / 10; + } + return 1 - att; + } + ); + next.setHiddenSkill("gz_tuxi"); + + event.result = await next.forResult(); + }, + logTarget: "targets", + /** + * @param {GameEvent} event + * @param {GameEvent} trigger + * @param {PlayerGuozhan} player + */ + async content(event, trigger, player) { + const { targets } = event; + targets.sortBySeat(); + await player.gainMultiple(targets); + trigger.num -= targets.length; + if (trigger.num <= 0) { + await game.delay(); + } + }, + ai: { + threaten: 1.6, + expose: 0.2, + }, + }, }; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index 0d20d51718..cfb8c96efc 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -2,4 +2,5 @@ export default { gz_caocao: "曹操", gz_simayi: "司马懿", gz_xiahoudun: "夏侯惇", + gz_zhangliao: "张辽", }; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index 8f2b45a4e5..803de210a0 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -4,4 +4,7 @@ export default { gz_ganglie: "刚烈", gz_ganglie_info: "当你受到伤害后,你可进行判定,若结果为:红色,你对伤害来源造成1点伤害;黑色,你弃置伤害来源一张牌。", + + gz_tuxi: "突袭", + gz_tuxi_info: "摸牌阶段摸牌时,你可以少摸至多两张牌,然后获得等量的角色的各一张手牌。", }; From c9c88fd3aa7bdb54c3018afb2820bd8ca9b3e15f Mon Sep 17 00:00:00 2001 From: Rintim Date: Tue, 8 Apr 2025 16:37:58 +0800 Subject: [PATCH 31/48] feat: rewrite `gz_xuzhu` in new format of mode character. --- mode/guozhan.js | 46 ---------- mode/guozhan/src/character/normal.js | 10 ++- mode/guozhan/src/skill/character/normal.js | 86 ++++++++++++++++++- .../guozhan/src/translate/character/normal.js | 1 + .../src/translate/skill/character/normal.js | 3 + 5 files changed, 98 insertions(+), 48 deletions(-) diff --git a/mode/guozhan.js b/mode/guozhan.js index 03f62d162a..c152c87c13 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -90,7 +90,6 @@ export default () => { gz_mazhong: ["male", "shu", 4, ["twfuman"]], gz_ol_lisu: ["male", "qun", 3, ["qiaoyan", "xianzhu"]], - gz_xuzhu: ["male", "wei", 4, ["gzluoyi"]], gz_guojia: ["male", "wei", 3, ["tiandu", "gzyiji"], ["gzskin"]], gz_zhenji: ["female", "wei", 3, ["luoshen", "qingguo"], ["gzskin"]], gz_xiahouyuan: ["male", "wei", 4, ["gzshensu"], ["gzskin"]], @@ -8480,49 +8479,6 @@ export default () => { }, }, //新国标2022 - //许褚 - gzluoyi: { - audio: "luoyi", - trigger: { player: "phaseDrawEnd" }, - direct: true, - preHidden: true, - filter(event, player) { - return player.countCards("he") > 0; - }, - content() { - "step 0"; - player - .chooseToDiscard("he", get.prompt2("gzluoyi")) - .setHiddenSkill("gzluoyi") - .set("ai", function (card) { - var player = _status.event.player; - if ( - player.hasCard(function (cardx) { - if (cardx == card) return false; - return (cardx.name == "sha" || cardx.name == "juedou") && player.hasValueTarget(cardx, null, true); - }, "hs") - ) - return 5 - get.value(card); - return -get.value(card); - }).logSkill = "gzluoyi"; - "step 1"; - if (result.bool) player.addTempSkill("gzluoyi_buff"); - }, - subSkill: { - buff: { - audio: "luoyi", - charlotte: true, - forced: true, - trigger: { source: "damageBegin1" }, - filter(event, player) { - return event.card && (event.card.name == "sha" || event.card.name == "juedou") && event.getParent().type == "card"; - }, - content() { - trigger.num++; - }, - }, - }, - }, //典韦 gzqiangxi: { audio: "qiangxi", @@ -19270,8 +19226,6 @@ export default () => { gzhongyan_info: "锁定技。①你区域内的黑桃牌和黑桃判定牌的花色视为红桃。②若你的装备区内有红桃牌,则你的手牌上限+1。", gztianxiang: "天香", gztianxiang_info: "每回合限一次。当你受到伤害时,你可以弃置一张红桃手牌,防止此次伤害并选择一名其他角色,然后你选择一项:1.令其受到伤害来源对其造成的1点伤害,然后摸X张牌(X为其已损失体力值且至多为5);2.令其失去1点体力,然后获得你弃置的牌。", - gzluoyi: "裸衣", - gzluoyi_info: "摸牌阶段结束时,你可弃置一张牌,然后你于本回合内造成渠道为【杀】或【决斗】的伤害+1。", gzqiangxi: "强袭", gzqiangxi_info: "出牌阶段限一次,你可以弃置一张武器牌或失去1点体力,然后对一名其他角色造成1点伤害。", diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index 6d9b5d1130..4dc3b911f2 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -32,5 +32,13 @@ export default { maxHp: 4, hujia: 0, skills: ["gz_tuxi"], - }), // ["male", "wei", 4, ["new_retuxi"]] + }), + gz_xuzhu: new Character({ + sex: "male", + group: "wei", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_luoyi"] + }), }; diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index c45379a26f..bf63ecf8d8 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -1,5 +1,5 @@ import { lib, game, ui, get, ai, _status } from "../../../../../noname.js"; -import { GameEvent, Player } from "../../../../../noname/library/element/index.js"; +import { GameEvent, Player, Card } from "../../../../../noname/library/element/index.js"; import { PlayerGuozhan } from "../../patch/player.js"; export default { @@ -185,4 +185,88 @@ export default { expose: 0.2, }, }, + + // gz_xuzhu + gz_luoyi: { + audio: "luoyi", + trigger: { + player: "phaseDrawEnd", + }, + preHidden: true, + /** + * @param {GameEvent} _event + * @param {PlayerGuozhan} player + * @returns {boolean} + */ + filter(_event, player) { + return player.countCards("he") > 0; + }, + /** + * @param {GameEvent} event + * @param {GameEvent} _trigger + * @param {PlayerGuozhan} player + */ + async cost(event, _trigger, player) { + const next = player.chooseToDiscard("he", get.prompt2("gz_luoyi")); + + next.setHiddenSkill("gz_luoyi"); + next.set("ai", check); + + event.result = await next.forResult(); + + return; + + /** + * @param {Card} card + * @returns {number} + */ + function check(card) { + const player = get.player(); + + if (player.hasCard(cardx => cardx != card && (cardx.name == "sha" || cardx.name == "juedou") && player.hasValueTarget(cardx, undefined, true), "hs")) { + return 5 - get.value(card); + } + + return -get.value(card); + } + }, + /** + * @param {GameEvent} _event + * @param {GameEvent} _trigger + * @param {PlayerGuozhan} player + */ + async content(_event, _trigger, player) { + player.addTempSkill("gz_luoyi_buff"); + }, + subSkill: { + buff: { + audio: "luoyi", + charlotte: true, + forced: true, + trigger: { + source: "damageBegin1", + }, + /** + * @param {GameEvent} event + * @param {PlayerGuozhan} _player + * @returns {boolean} + */ + filter(event, _player) { + const parent = event.getParent(); + if (parent == null || !("type" in parent)) { + return false; + } + return event.card && (event.card.name == "sha" || event.card.name == "juedou") && parent.type == "card"; + }, + /** + * @param {GameEvent} _event + * @param {GameEvent} trigger + * @param {PlayerGuozhan} _player + */ + async content(_event, trigger, _player) { + trigger.num++; + }, + }, + }, + }, }; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index cfb8c96efc..28e9307790 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -3,4 +3,5 @@ export default { gz_simayi: "司马懿", gz_xiahoudun: "夏侯惇", gz_zhangliao: "张辽", + gz_xuzhu: "许褚" }; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index 803de210a0..cf5d68c8e1 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -7,4 +7,7 @@ export default { gz_tuxi: "突袭", gz_tuxi_info: "摸牌阶段摸牌时,你可以少摸至多两张牌,然后获得等量的角色的各一张手牌。", + + gz_luoyi: "裸衣", + gz_luoyi_info: "摸牌阶段结束时,你可弃置一张牌,然后你于本回合内造成渠道为【杀】或【决斗】的伤害+1。", }; From 3493f552f05c6cda9092ca66169703ce47ef897e Mon Sep 17 00:00:00 2001 From: Rintim Date: Wed, 9 Apr 2025 16:17:56 +0800 Subject: [PATCH 32/48] feat: add `util.cast` to provide a function for transforming type. --- noname/util/index.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/noname/util/index.js b/noname/util/index.js index 3a0c5fed4e..df7711e925 100644 --- a/noname/util/index.js +++ b/noname/util/index.js @@ -90,3 +90,25 @@ export function isClass(func) { const fnStr = Function.prototype.toString.call(func); return /^class\s/.test(fnStr); } + +/** + * 一个申必的类型转换函数,用于在Javascript中实现`const a = b as unknown as ...`的功能 + * + * @template T - 目标类型,可通过目标变量自动覆盖,故只需要为目标变量提供类型即可 + * @template U - 原类型,无需单独填写,仅用于消除any + * @param {U} obj - 需要转换类型的对象 + * @returns {T} 返回原对象,仅类型转换 + * + * @example + * ```js + * // 从某个事件中获取结果 + * const result = await ... + * // 将结果转换为指定类型 + * // 由于JSDoc中无法重新使用JSDoc注释,故以Typescript说明 + * const card: Card[] = cast(result.links); + * ``` + */ +export function cast(obj) { + // @ts-expect-error Type Translate + return /** @type {unknown} */ obj; +} From 17f952d37ca0729d67c2159796bed27ccf98d9f4 Mon Sep 17 00:00:00 2001 From: Rintim Date: Wed, 9 Apr 2025 16:30:49 +0800 Subject: [PATCH 33/48] feat: rewrite `gz_guojia` in new format of mode character. --- mode/guozhan.js | 99 ------------ mode/guozhan/src/character/normal.js | 11 +- mode/guozhan/src/skill/character/normal.js | 146 +++++++++++++++++- .../guozhan/src/translate/character/normal.js | 3 +- .../src/translate/skill/character/normal.js | 3 + 5 files changed, 160 insertions(+), 102 deletions(-) diff --git a/mode/guozhan.js b/mode/guozhan.js index c152c87c13..49dc52077f 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -90,7 +90,6 @@ export default () => { gz_mazhong: ["male", "shu", 4, ["twfuman"]], gz_ol_lisu: ["male", "qun", 3, ["qiaoyan", "xianzhu"]], - gz_guojia: ["male", "wei", 3, ["tiandu", "gzyiji"], ["gzskin"]], gz_zhenji: ["female", "wei", 3, ["luoshen", "qingguo"], ["gzskin"]], gz_xiahouyuan: ["male", "wei", 4, ["gzshensu"], ["gzskin"]], gz_zhanghe: ["male", "wei", 4, ["qiaobian"]], @@ -15457,102 +15456,6 @@ export default () => { threaten: 1.3, }, }, - gzyiji: { - audio: "yiji", - trigger: { - player: "damageEnd", - }, - frequent: true, - preHidden: true, - content() { - "step 0"; - event.cards = game.cardsGotoOrdering(get.cards(2)).cards; - "step 1"; - if (_status.connectMode) - game.broadcastAll(function () { - _status.noclearcountdown = true; - }); - event.given_map = {}; - "step 2"; - if (event.cards.length > 1) { - player.chooseCardButton("遗计:请选择要分配的牌", true, event.cards, [1, event.cards.length]).set("ai", function (button) { - if (ui.selected.buttons.length == 0) return 1; - return 0; - }); - } else if (event.cards.length == 1) { - event._result = { links: event.cards.slice(0), bool: true }; - } else { - event.finish(); - } - "step 3"; - if (result.bool) { - event.cards.removeArray(result.links); - event.togive = result.links.slice(0); - player - .chooseTarget("选择一名角色获得" + get.translation(result.links), true) - .set("ai", function (target) { - var att = get.attitude(_status.event.player, target); - if (_status.event.enemy) { - return -att; - } else if (att > 0) { - return att / (1 + target.countCards("h")); - } else { - return att / 100; - } - }) - .set("enemy", get.value(event.togive[0], player, "raw") < 0); - } - "step 4"; - if (result.targets.length) { - var id = result.targets[0].playerid, - map = event.given_map; - if (!map[id]) map[id] = []; - map[id].addArray(event.togive); - } - if (cards.length > 0) event.goto(2); - "step 5"; - if (_status.connectMode) { - game.broadcastAll(function () { - delete _status.noclearcountdown; - game.stopCountChoose(); - }); - } - var list = []; - for (var i in event.given_map) { - var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; - player.line(source, "green"); - list.push([source, event.given_map[i]]); - } - game.loseAsync({ - gain_list: list, - giver: player, - animate: "draw", - }).setContent("gaincardMultiple"); - }, - ai: { - maixie: true, - maixie_hp: true, - effect: { - target(card, player, target) { - if (get.tag(card, "damage")) { - if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; - if (!target.hasFriend()) return; - var num = 1; - if (get.attitude(player, target) > 0) { - if (player.needsToDiscard()) { - num = 0.7; - } else { - num = 0.5; - } - } - if (target.hp >= 4) return [1, num * 2]; - if (target.hp == 3) return [1, num * 1.5]; - if (target.hp == 2) return [1, num * 0.5]; - } - }, - }, - }, - }, gzjieming: { audio: "jieming", trigger: { @@ -19487,8 +19390,6 @@ export default () => { baka_yinghun_info: "准备阶段,你可令一名其他角色执行一项:摸X张牌,然后弃置一张牌;或摸一张牌,然后弃置X张牌(X为你已损失的体力值)。", baka_yingzi: "英姿", baka_yingzi_info: "锁定技,摸牌阶段摸,你多摸一张牌;你的手牌上限+X(X为你已损失的体力值)。", - gzyiji: "遗计", - gzyiji_info: "当你受到伤害后,你可以观看牌堆顶的两张牌,并将其交给任意角色。", gzjieming: "节命", gzjieming_info: "当你受到伤害后,你可以令一名角色将手牌摸至X张(X为其体力上限且最多为5)。", gzfangzhu: "放逐", diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index 4dc3b911f2..7add101c98 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -39,6 +39,15 @@ export default { hp: 4, maxHp: 4, hujia: 0, - skills: ["gz_luoyi"] + skills: ["gz_luoyi"], + }), + gz_guojia: new Character({ + sex: "male", + group: "wei", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["tiandu", "gz_yiji"], + hasSkinInGuozhan: true, }), }; diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index bf63ecf8d8..e58d10f0b6 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -1,6 +1,8 @@ import { lib, game, ui, get, ai, _status } from "../../../../../noname.js"; import { GameEvent, Player, Card } from "../../../../../noname/library/element/index.js"; +import { cast } from "../../../../../noname/util/index.js"; import { PlayerGuozhan } from "../../patch/player.js"; +import { broadcastAll } from "../../patch/game.js"; export default { // gz_caocao @@ -217,7 +219,7 @@ export default { return; /** - * @param {Card} card + * @param {Card} card * @returns {number} */ function check(card) { @@ -269,4 +271,146 @@ export default { }, }, }, + + // gz_guojia + gz_yiji: { + audio: "yiji", + trigger: { + player: "damageEnd", + }, + frequent: true, + preHidden: true, + + /** + * @param {GameEvent} event + * @param {GameEvent} trigger + * @param {PlayerGuozhan} player + */ + async content(event, trigger, player) { + const cards = game.cardsGotoOrdering(get.cards(2)).cards; + /** @type {Map} */ + const givenMap = new Map(); + + if (_status.connectMode) { + broadcastAll(() => { + Reflect.set(_status, "noclearcountdown", true); + }); + } + + while (cards.length > 0) { + /** @type {Partial} */ + let result; + + if (cards.length > 1) { + result = await player + .chooseCardButton("遗计:请选择要分配的牌", true, cards, [1, cards.length]) + .set("ai", () => { + if (ui.selected.buttons.length == 0) return 1; + return 0; + }) + .forResult(); + } else { + result = { bool: true, links: cards.slice(0) }; + } + + if (!result.bool) { + break; + } + + /** @type {Card[]} */ + const links = cast(result.links); + cards.removeArray(links); + const toGive = links.slice(0); + + result = await player + .chooseTarget("选择一名角色获得" + get.translation(result.links), true) + .set("ai", (/** @type {PlayerGuozhan} */ target) => { + /** @type {GameEvent & { enemy: boolean }} */ + const event = cast(get.event()); + var att = get.attitude(event.player, target); + if (event.enemy) { + return -att; + } else if (att > 0) { + return att / (1 + target.countCards("h")); + } else { + return att / 100; + } + }) + .set("enemy", get.value(toGive[0], player, "raw") < 0) + .forResult(); + + if (!result.bool) { + break; + } + + /** @type {PlayerGuozhan[]} */ + const targets = cast(result.targets); + if (targets.length) { + const id = targets[0].playerid ?? ""; + + if (!givenMap.has(id)) { + givenMap.set(id, []); + } + const current = givenMap.get(id); + current?.addArray(toGive); + } + } + + if (_status.connectMode) { + broadcastAll(() => { + Reflect.deleteProperty(_status, "noclearcountdown"); + game.stopCountChoose(); + }); + } + + const list = []; + for (const [id, cards] of givenMap) { + const source = (_status.connectMode ? lib.playerOL : game.playerMap)[id]; + player.line(source, "green"); + list.push([source, cards]); + } + await game + .loseAsync({ + gain_list: list, + giver: player, + animate: "draw", + }) + .setContent("gaincardMultiple"); + }, + ai: { + maixie: true, + maixie_hp: true, + effect: { + target(card, player, target) { + if (get.tag(card, "damage")) { + if (player.hasSkillTag("jueqing", false, target)) { + return [1, -2]; + } + if (!target.hasFriend()) { + return; + } + + let num = 1; + if (get.attitude(player, target) > 0) { + if (player.needsToDiscard()) { + num = 0.7; + } else { + num = 0.5; + } + } + + if (target.hp >= 4) { + return [1, num * 2]; + } + if (target.hp == 3) { + return [1, num * 1.5]; + } + if (target.hp == 2) { + return [1, num * 0.5]; + } + } + }, + }, + }, + }, }; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index 28e9307790..137780e1ed 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -3,5 +3,6 @@ export default { gz_simayi: "司马懿", gz_xiahoudun: "夏侯惇", gz_zhangliao: "张辽", - gz_xuzhu: "许褚" + gz_xuzhu: "许褚", + gz_guojia: "郭嘉", }; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index cf5d68c8e1..eb3f5f47ca 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -10,4 +10,7 @@ export default { gz_luoyi: "裸衣", gz_luoyi_info: "摸牌阶段结束时,你可弃置一张牌,然后你于本回合内造成渠道为【杀】或【决斗】的伤害+1。", + + gz_yiji: "遗计", + gz_yiji_info: "当你受到伤害后,你可以观看牌堆顶的两张牌,并将其交给任意角色。", }; From 1043cfae313e3f9e546026ae9ae96c1ec2445f38 Mon Sep 17 00:00:00 2001 From: Rintim Date: Wed, 9 Apr 2025 17:21:00 +0800 Subject: [PATCH 34/48] feat: add root url to provide relative path. --- mode/guozhan/meta.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 mode/guozhan/meta.js diff --git a/mode/guozhan/meta.js b/mode/guozhan/meta.js new file mode 100644 index 0000000000..d289646a24 --- /dev/null +++ b/mode/guozhan/meta.js @@ -0,0 +1 @@ +export const rootURL = new URL("./", import.meta.url); From 9a1b265e4c59c7f6d8a6543d0893e810aafa4dbe Mon Sep 17 00:00:00 2001 From: Rintim Date: Wed, 9 Apr 2025 17:21:58 +0800 Subject: [PATCH 35/48] chore: add empty resource path. --- mode/guozhan/res/audio/card/.gitkeep | 0 mode/guozhan/res/audio/character/.gitkeep | 0 mode/guozhan/res/audio/skill/.gitkeep | 0 mode/guozhan/res/image/card/.gitkeep | 0 mode/guozhan/res/image/character/.gitkeep | 0 mode/guozhan/res/image/skill/.gitkeep | 0 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 mode/guozhan/res/audio/card/.gitkeep create mode 100644 mode/guozhan/res/audio/character/.gitkeep create mode 100644 mode/guozhan/res/audio/skill/.gitkeep create mode 100644 mode/guozhan/res/image/card/.gitkeep create mode 100644 mode/guozhan/res/image/character/.gitkeep create mode 100644 mode/guozhan/res/image/skill/.gitkeep diff --git a/mode/guozhan/res/audio/card/.gitkeep b/mode/guozhan/res/audio/card/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mode/guozhan/res/audio/character/.gitkeep b/mode/guozhan/res/audio/character/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mode/guozhan/res/audio/skill/.gitkeep b/mode/guozhan/res/audio/skill/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mode/guozhan/res/image/card/.gitkeep b/mode/guozhan/res/image/card/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mode/guozhan/res/image/character/.gitkeep b/mode/guozhan/res/image/character/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mode/guozhan/res/image/skill/.gitkeep b/mode/guozhan/res/image/skill/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 From b836681b5e3fc1ece11f8c6b21e06f4f98ea0a5e Mon Sep 17 00:00:00 2001 From: Rintim Date: Wed, 9 Apr 2025 17:22:37 +0800 Subject: [PATCH 36/48] feat: rewrite `gz_xiahouyuan` in new format of mode character. --- mode/guozhan.js | 690 ++++++++---------- mode/guozhan/src/character/index.js | 6 +- mode/guozhan/src/character/intro.js | 0 mode/guozhan/src/character/normal.js | 22 + mode/guozhan/src/skill/character/normal.js | 63 ++ .../guozhan/src/translate/character/normal.js | 2 + mode/guozhan/src/translate/index.js | 2 + .../src/translate/skill/character/normal.js | 3 + mode/guozhan/src/translate/voices/index.js | 1 + 9 files changed, 419 insertions(+), 370 deletions(-) create mode 100644 mode/guozhan/src/character/intro.js create mode 100644 mode/guozhan/src/translate/voices/index.js diff --git a/mode/guozhan.js b/mode/guozhan.js index 49dc52077f..0d5355331c 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -1,7 +1,7 @@ import { lib, game, ui, get, ai, _status } from "../noname.js"; import { start, startBefore, onreinit } from "./guozhan/src/main.js"; import { gamePatch, getPatch, contentPatch, playerPatch } from "./guozhan/src/patch/index.js"; -import { pack } from "./guozhan/src/character/index.js"; +import { pack, intro } from "./guozhan/src/character/index.js"; import * as info from "./guozhan/src/info/index.js"; import skill from "./guozhan/src/skill/index.js"; import translate from "./guozhan/src/translate/index.js"; @@ -90,8 +90,6 @@ export default () => { gz_mazhong: ["male", "shu", 4, ["twfuman"]], gz_ol_lisu: ["male", "qun", 3, ["qiaoyan", "xianzhu"]], - gz_zhenji: ["female", "wei", 3, ["luoshen", "qingguo"], ["gzskin"]], - gz_xiahouyuan: ["male", "wei", 4, ["gzshensu"], ["gzskin"]], gz_zhanghe: ["male", "wei", 4, ["qiaobian"]], gz_xuhuang: ["male", "wei", 4, ["new_duanliang"]], gz_caoren: ["male", "wei", 4, ["gzjushou"]], @@ -258,6 +256,7 @@ export default () => { gz_jin_yanghu: ["male", "jin", 4, ["fakechongxin", "fakeweirong"]], }, }, + characterIntro: intro, skill: { ...skill, @@ -369,7 +368,7 @@ export default () => { .set("choiceList", ["摸一张牌", "弃置" + get.translation(trigger.target) + "的一张牌", "背水!依次执行以上两项。然后若此【杀】未令其进入濒死状态,则其弃置你的一张牌。"]) .set("prompt", get.prompt(event.name, trigger.target)) .setHiddenSkill(event.name); - "step 1"; + ("step 1"); if (result.control != "cancel2") { var target = trigger.target; player.logSkill(event.name, target); @@ -665,7 +664,7 @@ export default () => { var cards = get.cards(3); event.cards = cards; player.showCards(cards, get.translation(player) + "发动了【陈见】"); - "step 1"; + ("step 1"); var list = []; if ( player.countCards("he", i => { @@ -697,11 +696,11 @@ export default () => { return "选项一"; }); else event.finish(); - "step 2"; + ("step 2"); event.choosed = result.control; if (result.control === "cancel2") event.finish(); else if (result.control === "选项二") event.goto(6); - "step 3"; + ("step 3"); if ( player.countCards("he", i => { return lib.filter.cardDiscardable(i, player, "chenjian"); @@ -721,7 +720,7 @@ export default () => { .set("prompt", "陈见:请弃置一张牌,然后令一名角色获得" + get.translation(event.cards) + "中花色与之相同的牌" + (event.goon ? "?" : "")); else if (event.choosed === "选项一") event.goto(6); else event.finish(); - "step 4"; + ("step 4"); if (result.bool) { var suit = get.suit(result.cards[0], player); var cards2 = event.cards.filter(function (i) { @@ -738,14 +737,14 @@ export default () => { }); } else event.finish(); } else event.finish(); - "step 5"; + ("step 5"); if (result.bool) { var target = result.targets[0]; player.line(target, "green"); target.gain(event.cards2, "gain2"); } event.finish(); - "step 6"; + ("step 6"); var cards2 = cards.filter(function (i) { return player.hasUseTarget(i); }); @@ -754,7 +753,7 @@ export default () => { return player.getUseValue(button.link); }); else event.finish(); - "step 7"; + ("step 7"); if (result.bool) { player.chooseUseTarget(true, result.links[0], false); } @@ -1445,10 +1444,10 @@ export default () => { content() { "step 0"; player.removeCharacter(1); - "step 1"; + ("step 1"); player.gainMaxHp(3); player.recover(3); - "step 2"; + ("step 2"); player.addSkills("fakebenghuai"); }, derivation: "fakebenghuai", @@ -1888,13 +1887,13 @@ export default () => { const num = Math.max(1, Math.min(player.maxHp, player.getExpansions("fakequanji").length)); event.num = num; player.draw(num); - "step 1"; + ("step 1"); var hs = player.getCards("he"); if (hs.length > 0) { if (hs.length <= event.num) event._result = { bool: true, cards: hs }; else player.chooseCard("he", true, "选择" + get.cnNumber(event.num) + "张牌作为“权”", event.num); } else event.finish(); - "step 2"; + ("step 2"); if (result.bool) { var cs = result.cards; player.addToExpansion(cs, player, "give").gaintag.add("fakequanji"); @@ -2071,7 +2070,7 @@ export default () => { return get.guozhanRank(button.link); }; } - "step 1"; + ("step 1"); var name = result.links[0]; _status.characterlist.remove(name); if (player.hasViceCharacter()) event.change = true; @@ -2081,13 +2080,13 @@ export default () => { if (event.hidden) { if (!player.isUnseen(1)) player.hideCharacter(1); } - "step 2"; + ("step 2"); var name = event.toChange; if (event.hidden) game.log(player, "替换了副将", "#g" + get.translation(player.name2)); else game.log(player, "将副将从", "#g" + get.translation(player.name2), "变更为", "#g" + get.translation(name)); player.viceChanged = true; player.reinitCharacter(player.name2, name, false); - "step 3"; + ("step 3"); if (event.change && event.toRemove) { const list = [event.toRemove]; player.markAuto("fakeshilu", list); @@ -2427,10 +2426,10 @@ export default () => { "step 0"; var num = trigger.player.hp - trigger.player.countCards("h"); if (num > 0) trigger.player.draw(num); - "step 1"; + ("step 1"); trigger.player.addTempSkill("fakexibing_banned"); if (get.mode() != "guozhan" || player.isUnseen(2) || trigger.player.isUnseen(2)) event.finish(); - "step 2"; + ("step 2"); var target = trigger.player; var players1 = [player.name1, player.name2]; var players2 = [target.name1, target.name2]; @@ -2441,7 +2440,7 @@ export default () => { .set("filterButton", function (button) { return !get.is.jun(button.link) && (ui.selected.buttons.length == 0) == _status.event.players.includes(button.link); }); - "step 3"; + ("step 3"); if (result.bool) { var target = trigger.player; player.hideCharacter(player.name1 == result.links[0] ? 0 : 1); @@ -2589,7 +2588,7 @@ export default () => { return Math.random(); }) .set("prompt2", lib.translate.fakezhiwei_info); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; player.logSkill("fakezhiwei", target); @@ -2679,7 +2678,7 @@ export default () => { "step 0"; player.removeSkill("fakezhiwei_effect"); if (trigger.name != "die") event.finish(); - "step 1"; + ("step 1"); if (get.character(player.name1, 3).includes("fakezhiwei")) player.hideCharacter(0); if (get.character(player.name2, 3).includes("fakezhiwei")) player.hideCharacter(1); }, @@ -3310,7 +3309,7 @@ export default () => { content() { "step 0"; player.draw(2); - "step 1"; + ("step 1"); var dh = player.countCards("h") - player.getHistory("useSkill", evt => { @@ -4294,7 +4293,7 @@ export default () => { return get.attitude(player, target) / (Math.abs(player.countCards("h") + 2 - target.countCards("h")) + 1); }) .setHiddenSkill("fakeqimei"); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; player.logSkill("fakeqimei", target); @@ -4328,7 +4327,7 @@ export default () => { content() { "step 0"; if (trigger.delay === false) game.delayx(); - "step 1"; + ("step 1"); var target = player.storage.fakeqimei_draw; player.logSkill("fakeqimei_draw", target); var drawer = []; @@ -5059,22 +5058,22 @@ export default () => { _status.event._resultid = id; game.resume(); }; - "step 1"; + ("step 1"); var type = get.type2(card); event.list = game.filterPlayer(current => current.countCards("h") && (_status.connectMode || current.hasCard(cardx => get.type2(cardx) == type, "h"))).sortBySeat(_status.currentPhase || player); event.id = get.id(); - "step 2"; + ("step 2"); if (!event.list.length) event.finish(); else if (_status.connectMode && (event.list[0].isOnline() || event.list[0] == game.me)) event.goto(4); else event.send((event.current = event.list.shift()), event.card, player, trigger.targets, event.id, trigger.parent.id, trigger.yingbianZhuzhanAI); - "step 3"; + ("step 3"); if (result.bool) { event.zhuzhanresult = event.current; event.zhuzhanresult2 = result; if (event.current != game.me) game.delayx(); event.goto(8); } else event.goto(2); - "step 4"; + ("step 4"); var id = event.id, sendback = (result, player) => { if (result && result.id == id && !event.zhuzhanresult && result.bool) { @@ -5111,16 +5110,16 @@ export default () => { if (value != player) value.showTimer(); }); event.withol = withol; - "step 5"; + ("step 5"); if (!result || !result.bool || event.zhuzhanresult) return; game.broadcast("cancel", event.id); event.zhuzhanresult = game.me; event.zhuzhanresult2 = result; - "step 6"; + ("step 6"); if (event.withol && !event.resultOL) game.pause(); - "step 7"; + ("step 7"); game.players.forEach(value => value.hideTimer()); - "step 8"; + ("step 8"); if (event.zhuzhanresult) { var target = event.zhuzhanresult; if (target == player && player.hasSkill("fakecaiwang")) player.logSkill("fakecaiwang"); @@ -5225,7 +5224,7 @@ export default () => { }; lib.yingbian.condition.complex.get("zhuzhan")(trigger); } - "step 1"; + ("step 1"); if (!result.bool) return; var yingbianEffectExecuted = false; lib.yingbian.effect.forEach((value, key) => { @@ -5639,7 +5638,7 @@ export default () => { return 0; }) .set("aim", trigger.player); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; event.target = target; @@ -5662,7 +5661,7 @@ export default () => { .set("sourcex", trigger.player) .set("addCount", false); } else event.finish(); - "step 2"; + ("step 2"); if (result.bool) { if (target.hasHistory("sourceDamage", evt => evt.getParent(4).name == "gztongling")) { player.draw(2, "nodelay"); @@ -5702,7 +5701,7 @@ export default () => { return get.distance(player, current) <= 1; }) .sortBySeat(player); - "step 1"; + ("step 1"); var target = event.targets.shift(); event.target = target; if (!target.isUnseen(2)) { @@ -5731,9 +5730,9 @@ export default () => { target.chooseToDiscard(2, "he", true); event.goto(3); } - "step 2"; + ("step 2"); if (result.control) target.hideCharacter(result.control == "主将" ? 0 : 1); - "step 3"; + ("step 3"); if (event.targets.length) event.goto(1); }, }, @@ -5760,7 +5759,7 @@ export default () => { ) { event.finish(); } - "step 1"; + ("step 1"); const list = [], bannedList = [], indexs = Object.keys(lib.color); @@ -5782,12 +5781,12 @@ export default () => { return 0; }) .set("prompt", "请选择弃置一种颜色的所有手牌"); - "step 2"; + ("step 2"); event.control = result.control.slice(0, result.control.length - 1); var cards = player.getCards("h", { color: event.control }); player.discard(cards); event.num = cards.length; - "step 3"; + ("step 3"); player .chooseTarget("请选择至多" + get.cnNumber(event.num) + "名有牌的其他角色,获得这些角色的各一张牌。", [1, event.num], function (card, player, target) { return target != player && target.countCards("he") > 0; @@ -5795,21 +5794,21 @@ export default () => { .set("ai", function (target) { return -get.attitude(_status.event.player, target) + 0.5; }); - "step 4"; + ("step 4"); if (result.bool && result.targets) { player.line(result.targets, "green"); event.targets = result.targets; event.targets.sort(lib.sort.seat); event.cards = []; } else event.finish(); - "step 5"; + ("step 5"); if (player.isIn() && event.targets.length) { player.gainPlayerCard(event.targets.shift(), "he", true); } else event.finish(); - "step 6"; + ("step 6"); if (result.bool && result.cards && result.cards.length) event.cards.addArray(result.cards); if (event.targets.length) event.goto(5); - "step 7"; + ("step 7"); var hs = player.getCards("h"); cards = cards.filter(function (card) { return get.type(card) == "equip" && hs.includes(card); @@ -5819,7 +5818,7 @@ export default () => { game.log(player, "将", cards, "置于了武将牌上"); player.loseToSpecial(cards, "gzrehuaiyi").visible = true; } else event.finish(); - "step 8"; + ("step 8"); player.addSkill("gzrehuaiyi_unmark"); player.markSkill("gzrehuaiyi"); game.delayx(); @@ -6016,7 +6015,7 @@ export default () => { game.createCard(cardname, " ", " ") ); game.delay(3); - "step 1"; + ("step 1"); game.broadcastAll("closeDialog", event.videoId); var targets = game.filterPlayer(current => !current.hasSkill(event.skill)); if (!targets.length) { @@ -6036,7 +6035,7 @@ export default () => { return get.attitude(player, target); }) .set("targets", targets); - "step 2"; + ("step 2"); if (result.bool) { var target = result.targets[0], skill = event.skill; @@ -6105,7 +6104,7 @@ export default () => { player.addMark("gzrebushi", player.hp); event.finish(); } - "step 1"; + ("step 1"); player.removeMark("gzrebushi", player.countMark("gzrebushi")); if (!player.hasMark("gzrebushi")) player.unmarkSkill("gzrebushi"); }, @@ -6133,7 +6132,7 @@ export default () => { if (num >= player.countMark("gzrebushi") && !target.isFriendOf(player)) return -1; return 6 - get.value(card); }); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("gzrebushi", trigger.player); player.removeMark("gzrebushi", 1); @@ -6155,12 +6154,12 @@ export default () => { content() { "step 0"; player.draw(2); - "step 1"; + ("step 1"); var cards = player.getCards("he"); if (!cards.length) event.finish(); else if (cards.length <= 2) event._result = { bool: true, cards: cards }; else player.chooseCard(2, "he", true, "选择两张牌作为“米”"); - "step 2"; + ("step 2"); if (result.bool) player.addToExpansion(result.cards, player, "give").gaintag.add("gzremidao"); }, marktext: "米", @@ -6203,7 +6202,7 @@ export default () => { if (mod != "unchanged") return mod; return true; }); - "step 1"; + ("step 1"); if (result.bool) { event.forceDie = true; player.respond(result.links, "gzremidao", "highlight", "noOrdering"); @@ -6211,7 +6210,7 @@ export default () => { var card = result.cards[0]; event.card = card; } else event.finish(); - "step 2"; + ("step 2"); if (result.bool) { if (trigger.player.judging[0].clone) { trigger.player.judging[0].clone.classList.remove("thrownhighlight"); @@ -6264,11 +6263,11 @@ export default () => { content() { "step 0"; player.useCard({ name: "zhibi", isCard: true }, targets[0]); - "step 1"; + ("step 1"); if (player.countCards("he") > 0 && targets[1].isAlive()) { player.chooseCard("he", true, "交给" + get.translation(targets[1]) + "一张牌"); } else event.finish(); - "step 2"; + ("step 2"); player.give(result.cards, targets[1]); player.draw(); }, @@ -6308,7 +6307,7 @@ export default () => { .set("oncard", function () { _status.event.directHit.addArray(game.filterPlayer()); }); - "step 1"; + ("step 1"); player.addTempSkill("gzyechou_unequip"); if (!target.isIn() || !player.canUse("sha", target, false)) { player.removeSkill("gzyechou_unequip"); @@ -6325,7 +6324,7 @@ export default () => { ) .set("forceDie", true); } - "step 2"; + ("step 2"); player.removeSkill("gzyechou_unequip"); if (!target.isIn() || !player.canUse("sha", target, false)) { event.goto(3); @@ -6336,7 +6335,7 @@ export default () => { .set("oncard", function () { _status.event.baseDamage++; }); - "step 3"; + ("step 3"); target.removeSkill("gzyechou_unsavable"); }, ai: { @@ -6374,7 +6373,7 @@ export default () => { return current != target && current.isEnemyOf(target); }) .sortBySeat(); - "step 1"; + ("step 1"); if (!event.target.isIn()) { event.finish(); return; @@ -6399,7 +6398,7 @@ export default () => { .set("sourcex", event.target); } if (targets.length > 0) event.redo(); - "step 2"; + ("step 2"); if (target.isIn()) { var dying = false; var num = target.getHistory("damage", function (evt) { @@ -6612,12 +6611,12 @@ export default () => { .sortBySeat(); game.delayx(); player.chooseJunlingFor(event.players[0]).set("prompt", "请选择一项“军令”"); - "step 1"; + ("step 1"); event.junling = result.junling; event.targets = result.targets; event.num = 0; player.carryOutJunling(player, event.junling, event.targets); - "step 2"; + ("step 2"); if (num < event.players.length) event.current = event.players[num]; if (event.current && event.current.isAlive()) { player.line(event.current); @@ -6630,13 +6629,13 @@ export default () => { return get.junlingEffect(evt.player, evt.junling, evt.current, evt.targets, evt.current) > 0 ? 0 : 1; }); } else event.goto(4); - "step 3"; + ("step 3"); if (result.index == 0) { event.current.carryOutJunling(player, event.junling, event.targets); } else { event.current.addTempSkill("diaohulishan"); } - "step 4"; + ("step 4"); game.delayx(); event.num++; if (event.num < event.players.length) event.goto(2); @@ -6747,7 +6746,7 @@ export default () => { }); return 10 / distance; }); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; player.logSkill("gzdianhu", target); @@ -6785,7 +6784,7 @@ export default () => { content() { "step 0"; target.draw("visible"); - "step 1"; + ("step 1"); var card = result[0]; if ( card && @@ -6873,13 +6872,13 @@ export default () => { .set("ai", function (target) { return get.attitude(_status.event.player, target); }); - "step 1"; + ("step 1"); if (result.bool) { var targets = result.targets.sortBySeat(); player.logSkill("gzzhuihuan", targets); event.targets = targets; } else event.finish(); - "step 2"; + ("step 2"); var next = player .chooseTarget("选择一名角色获得反伤效果", "被选择的目标角色下次受到伤害后,其对伤害来源造成1点伤害;未被选择的目标角色下次受到伤害后,伤害来源弃置两张牌。", function (card, player, target) { return _status.event.getParent().targets.includes(target); @@ -6888,7 +6887,7 @@ export default () => { return get.attitude(_status.event.player, target); }); if (targets.length > 1) next.set("forced", true); - "step 3"; + ("step 3"); for (var target of targets) { player.addTempSkill("gzzhuihuan_timeout", { player: "phaseZhunbeiBegin" }); var id = "gzzhuihuan_" + player.playerid; @@ -7012,7 +7011,7 @@ export default () => { }) .set("list", list) .setHiddenSkill("gzzhenxi"); - "step 1"; + ("step 1"); if (result.control == "cancel2") { event.finish(); return; @@ -7020,7 +7019,7 @@ export default () => { player.logSkill("gzzhenxi", target); event.choice = result.control; if (event.choice != "选项二" && target.countDiscardableCards(player, "he")) player.discardPlayerCard(target, "he", true); - "step 2"; + ("step 2"); if ( event.choice != "选项一" && (player.hasCard(function (card) { @@ -7050,7 +7049,7 @@ export default () => { return player.canUse(get.autoViewAs(cardx, [card]), _status.event.getParent().target, false); }, }); - "step 1"; + ("step 1"); if (result.bool) player.useCard({ name: get.suit(result.cards[0], player) == "diamond" ? "lebu" : "bingliang" }, target, result.cards); }, }, @@ -7134,7 +7133,7 @@ export default () => { }, }) .setHiddenSkill("gzjiansu_use"); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0], cards = result.cards; @@ -7167,12 +7166,12 @@ export default () => { return 8 - get.value(card); }); else event.goto(2); - "step 1"; + ("step 1"); if (result.bool) { event._result = { control: "我全都要!" }; event.goto(3); } - "step 2"; + ("step 2"); if (target.countCards("e") > 0) { target .chooseControl() @@ -7186,7 +7185,7 @@ export default () => { return 0; }); } else event._result = { control: "选项一" }; - "step 3"; + ("step 3"); player.line(target); if (result.control != "选项二") trigger.num++; if (result.control != "选项一") target.chooseToDiscard(target.countCards("e"), true, "e"); @@ -7231,7 +7230,7 @@ export default () => { event.goto(2); } else event.list = list; player.removeCharacter(1); - "step 1"; + ("step 1"); target .chooseControl(event.list, "cancel2") .set( @@ -7247,7 +7246,7 @@ export default () => { }) .set("prompt", get.translation(player) + "对你发动了【示恭】") .set("prompt2", "获得一个技能并令其将体力回复至体力上限;或点击“取消”,令其将体力值回复至1点。"); - "step 2"; + ("step 2"); if (result.control == "cancel2") { player.recover(1 - player.hp); event.finish(); @@ -7346,24 +7345,24 @@ export default () => { return get.effect(target, { name: "guohe" }, player, player); }) .setHiddenSkill(event.name); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; event.target = target; player.logSkill("gztanfeng", target); player.discardPlayerCard(target, "hej", true); } else event.finish(); - "step 2"; + ("step 2"); target .chooseBool("是否受到" + get.translation(player) + "造成的1点火焰伤害,令其跳过一个阶段?") .set("ai", () => _status.event.choice) .set("choice", get.damageEffect(target, player, target) >= -5); - "step 3"; + ("step 3"); if (result.bool) { player.line(target); target.damage(1, "fire"); } else event.finish(); - "step 4"; + ("step 4"); var list = []; var list2 = []; event.map = { @@ -7399,7 +7398,7 @@ export default () => { return list2.randomGet(); })() ); - "step 5"; + ("step 5"); for (var i in event.map) { if (event.map[i] == result.control) player.skip(i); } @@ -7511,7 +7510,7 @@ export default () => { player.unmarkAuto("gzmaihuo_effect", [target]); target.removeMark("gzmaihuo_mark", 1, false); target.useCard({ name: "sha", isCard: true }, player, "gzmaihuo_effect", false); - "step 1"; + ("step 1"); if (!player.getStorage("gzmaihuo_effect").length) player.removeSkill("gzmaihuo_effect"); }, group: "gzmaihuo_remove", @@ -7642,11 +7641,11 @@ export default () => { ) ) .setHiddenSkill("gzzhaosong_sha"); - "step 1"; + ("step 1"); if (result.bool) { if (!event.isMine() && !event.isOnline()) game.delayx(); } else event.finish(); - "step 2"; + ("step 2"); var targets = result.targets; player.markAuto("gzzhaosong", ["效果③"]); player.logSkill("gzzhaosong_sha", targets); @@ -7667,7 +7666,7 @@ export default () => { var list = player.getStorage("gzzhaosong").slice(0); list.push("cancel2"); player.chooseControl(list).set("prompt", get.prompt("gzlisi")).set("prompt2", "恢复〖诏颂〗的一个已发动的选项"); - "step 1"; + ("step 1"); if (result.control != "cancel2") { player.logSkill("gzlisi"); player.unmarkAuto("gzzhaosong", [result.control]); @@ -7702,7 +7701,7 @@ export default () => { } if (cards.length) player.gain(cards, "gain2"); if (cards.length < 2) player.draw(2 - cards.length); - "step 1"; + ("step 1"); player.addTempSkill("gzxuanbei_effect"); }, group: "gzxuanbei_change", @@ -7743,7 +7742,7 @@ export default () => { } return -(rank - 6) * att; }); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; player.logSkill("gzxuanbei_change", target); @@ -7792,11 +7791,11 @@ export default () => { list.push(i + "点"); } player.chooseControl(list).set("prompt", "###请先失去任意点体力###此回合结束时,你将恢复等量的体力"); - "step 1"; + ("step 1"); var num1 = result.index + num; event.num1 = num1; if (num1 > 0) player.loseHp(num1); - "step 2"; + ("step 2"); if ( player.isDamaged() && player.hasCard(function (card) { @@ -7808,7 +7807,7 @@ export default () => { }); if (event.num1 == 0) next.set("forced", true); } - "step 3"; + ("step 3"); var num2 = 0; if (result.bool) num2 = result.cards.length; var storage = [event.num1, num2]; @@ -7864,7 +7863,7 @@ export default () => { if (!stat.sanchen) stat.sanchen = []; stat.sanchen.push(target); target.draw(3); - "step 1"; + ("step 1"); if (!target.countCards("he")) event.finish(); else target.chooseToDiscard("he", true, 3).set("ai", function (card) { @@ -7874,7 +7873,7 @@ export default () => { if (!list.includes(get.type2(card))) return 7 - get.value(card); return -get.value(card); }); - "step 2"; + ("step 2"); if (result.bool && result.cards && result.cards.length) { var list = []; for (var i of result.cards) list.add(get.type2(i)); @@ -7953,7 +7952,7 @@ export default () => { character ); game.delay(3); - "step 1"; + ("step 1"); game.broadcastAll("closeDialog", event.videoId); var list1 = ["wei", "shu", "wu", "qun", "jin"], list2 = ["gzqice", "tiaoxin", "gzzhiheng", "new_chuli", "gzsanchen"]; @@ -7964,7 +7963,7 @@ export default () => { if (!skills.length) event.finish(); else if (skills.length == 1) event._result = { control: skills[0] }; else player.chooseControl(skills).set("prompt", "选择获得一个技能直到回合结束"); - "step 2"; + ("step 2"); var skill = result.control; player.addTempSkills(skill); player.popup(skill); @@ -8012,7 +8011,7 @@ export default () => { content() { "step 0"; player.choosePlayerCard(target, "h", true); - "step 1"; + ("step 1"); player.showCards(result.cards, get.translation(player) + "对" + get.translation(target) + "发动了【筹伐】"); var type = get.type2(result.cards[0], target), hs = target.getCards("h", function (card) { @@ -8071,7 +8070,7 @@ export default () => { }); return [cards, cards.splice(cards.length - _status.event.num)]; }); - "step 1"; + ("step 1"); if (result.bool) { var list = result.moved; if (list[0].length) player.gain(list[0], "gain2"); @@ -8100,7 +8099,7 @@ export default () => { return 6 - get.value(card); }) .setHiddenSkill(event.name); - "step 1"; + ("step 1"); if (result.bool) { player.useCard(get.autoViewAs({ name: "sha", nature: "ice" }, result.cards), result.cards, false, trigger.player, "gzqingleng"); if (trigger.player.isUnseen()) { @@ -8153,7 +8152,7 @@ export default () => { return val; return val + 8; }); - "step 1"; + ("step 1"); if (result.bool) { var card = result.links[0]; player.gain(card, "gain2"); @@ -8275,7 +8274,7 @@ export default () => { .set("prompt", get.prompt2("jilei", trigger.source)) .set("source", trigger.source) .setHiddenSkill("gzjilei"); - "step 1"; + ("step 1"); if (result.control != "cancel2") { player.logSkill("gzjilei", trigger.source); player.chat(get.translation(result.control) + "牌"); @@ -8322,13 +8321,13 @@ export default () => { }) .set("judging", trigger.player.judging[0]) .setHiddenSkill("gzhuanshi"); - "step 1"; + ("step 1"); if (result.bool) { player.respond(result.cards, "gzhuanshi", "highlight", "noOrdering"); } else { event.finish(); } - "step 2"; + ("step 2"); if (result.bool) { if (trigger.player.judging[0].clone) { trigger.player.judging[0].clone.classList.remove("thrownhighlight"); @@ -8405,7 +8404,7 @@ export default () => { }) .setHiddenSkill("gzhongyuan") .set("ai", () => -1); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; player.logSkill("gzhongyuan", target); @@ -8627,7 +8626,7 @@ export default () => { ? 1 : 0; }); - "step 1"; + ("step 1"); if (result.control != "cancel2") { var target = trigger.target; player.logSkill("gzliegong", target); @@ -8729,61 +8728,16 @@ export default () => { return get.effect(target, card, player, player); }) .setHiddenSkill("gzwushuang"); - "step 1"; + ("step 1"); if (result.bool) { if (player != game.me && !player.isOnline()) game.delayx(); } else event.finish(); - "step 2"; + ("step 2"); var targets = result.targets.sortBySeat(); player.logSkill("gzwushuang", targets); trigger.targets.addArray(targets); }, }, - //夏侯渊 - gzshensu: { - audio: "shensu1", - audioname: ["xiahouba", "re_xiahouyuan", "ol_xiahouyuan"], - group: ["gzshensu_1", "gzshensu_2"], - preHidden: ["gzshensu_1", "gzshensu_2", "gzshensu"], - trigger: { player: "phaseDiscardBegin" }, - direct: true, - filter(event, player) { - return player.hp > 0; - }, - content() { - "step 0"; - player - .chooseTarget(get.prompt("gzshensu"), "失去1点体力并跳过弃牌阶段,视为对一名其他角色使用一张无距离限制的【杀】", function (card, player, target) { - return player.canUse("sha", target, false); - }) - .setHiddenSkill("gzshensu") - .set("goon", player.needsToDiscard()) - .set("ai", function (target) { - var player = _status.event.player; - if (!_status.event.goon || player.hp <= target.hp) return false; - return get.effect(target, { name: "sha", isCard: true }, player, player); - }); - "step 1"; - if (result.bool) { - var target = result.targets[0]; - player.logSkill("gzshensu", target); - player.loseHp(); - trigger.cancel(); - player.useCard({ name: "sha", isCard: true }, target, false); - } - }, - subSkill: { - 1: { - audio: "shensu1", - inherit: "shensu1", - sourceSkill: "gzshensu", - }, - 2: { - inherit: "shensu2", - sourceSkill: "gzshensu", - }, - }, - }, //吕玲绮 gzshenwei: { audio: "llqshenwei", @@ -8847,7 +8801,7 @@ export default () => { content() { "step 0"; player.chooseToCompare(target); - "step 1"; + ("step 1"); if (result.bool) { if (!target.countCards("hej")) event.goto(3); else { @@ -8865,16 +8819,16 @@ export default () => { player.chooseCard(true, "he", "交给" + get.translation(target) + "一张牌"); } } - "step 2"; + ("step 2"); if (result.bool) event.giver.give(result.cards, event.gainner, "giveAuto"); - "step 3"; + ("step 3"); if (target.isIn()) player.chooseBool("纵横:是否令" + get.translation(target) + "获得【锋略】?").set("ai", function () { var evt = _status.event.getParent(); return get.attitude(evt.player, evt.target) > 0; }); else event.finish(); - "step 4"; + ("step 4"); if (result.bool) { target.addTempSkill("gzfenglve_zongheng", { player: "phaseEnd" }); game.log(player, "发起了", "#y纵横", ",令", target, "获得了技能", "#g【锋略】"); @@ -8909,7 +8863,7 @@ export default () => { content() { "step 0"; player.chooseToCompare(target); - "step 1"; + ("step 1"); if (result.bool) { if (!target.countCards("hej")) event.finish(); else { @@ -8927,7 +8881,7 @@ export default () => { player.chooseCard(true, "he", 2, "交给" + get.translation(target) + "两张牌"); } } - "step 2"; + ("step 2"); if (result.bool) event.giver.give(result.cards, event.gainner, "giveAuto"); }, ai: { @@ -9035,7 +8989,7 @@ export default () => { if (cards.length) { player.discard(cards); } else event.finish(); - "step 1"; + ("step 1"); player.drawTo(Math.min(5, player.maxHp)); }, }, @@ -9053,7 +9007,7 @@ export default () => { .set("ai", function (target) { return 10 + get.attitude(_status.event.player, target) * (target.hasSkillTag("fireAttack", null, null, true) ? 2 : 1); }); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; player.logSkill("gzlianyou", target); @@ -9097,7 +9051,7 @@ export default () => { if (typeof player.storage.gzgongxiu != "number") { player.chooseControl().set("choiceList", [str + "各摸一张牌", str + "各弃置一张牌"]); } else event._result = { index: 1 - player.storage.gzgongxiu }; - "step 1"; + ("step 1"); var num = result.index; event.index = num; player.storage.gzgongxiu = num; @@ -9108,7 +9062,7 @@ export default () => { var evt = _status.event; return evt.goon * get.attitude(evt.player, target); }); - "step 2"; + ("step 2"); if (result.bool) { var targets = result.targets.sortBySeat(); player.line(targets, "green"); @@ -9118,7 +9072,7 @@ export default () => { event.finish(); } } - "step 3"; + ("step 3"); game.delayx(); }, }, @@ -9172,7 +9126,7 @@ export default () => { player.addTempSkill("gzjinghe_clear", { player: "phaseBegin" }); event.targets.sortBySeat(); event.num = 0; - "step 1"; + ("step 1"); event.target = targets[num]; event.num++; event.target @@ -9185,7 +9139,7 @@ export default () => { ) .set("displayIndex", false) .set("prompt", "选择获得一个技能"); - "step 2"; + ("step 2"); var skill = result.control; if (skill != "cancel2") { event.skills.remove(skill); @@ -9284,7 +9238,7 @@ export default () => { "step 0"; var num = Math.min(player.getStorage("gzshilu").length, player.countCards("he")); player.chooseToDiscard("he", get.prompt("gzshilu"), "弃置至多" + get.cnNumber(num) + "张牌并摸等量的牌", [1, num]).logSkill = "gzshilu"; - "step 1"; + ("step 1"); if (result.bool && result.cards && result.cards.length) player.draw(result.cards.length); }, }, @@ -9322,7 +9276,7 @@ export default () => { return get.tag(card, "damage") && player.hasValueTarget(card); }) > 1 ); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("gzxiongnve"); lib.skill.gzxiongnve.throwCharacter(player, result.links); @@ -9346,7 +9300,7 @@ export default () => { return get.rand(1, 2); }); } else event.finish(); - "step 2"; + ("step 2"); var skill = "gzxiongnve_effect" + result.index; player.markAuto(skill, event.group); player.addTempSkill(skill); @@ -9477,7 +9431,7 @@ export default () => { } return 1; }); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("gzxiongnve"); lib.skill.gzxiongnve.throwCharacter(player, result.links); @@ -9520,7 +9474,7 @@ export default () => { list[0].draw(); event.finish(); } else game.asyncDraw(list); - "step 1"; + ("step 1"); game.delayx(); }, }, @@ -9534,7 +9488,7 @@ export default () => { content() { "step 0"; player.gainPlayerCard(target, "h", true, event.name == "gzweimeng" ? [1, player.hp] : 1); - "step 1"; + ("step 1"); if (result.bool && target.isIn()) { var num = result.cards.length, hs = player.getCards("he"); @@ -9542,16 +9496,16 @@ export default () => { else if (hs.length <= num) event._result = { bool: true, cards: hs }; else player.chooseCard("he", true, "选择交给" + get.translation(target) + get.cnNumber(num) + "张牌", num); } else event.goto(3); - "step 2"; + ("step 2"); player.give(result.cards, target); - "step 3"; + ("step 3"); if (target.isIn() && event.name == "gzweimeng") player.chooseBool("纵横:是否令" + get.translation(target) + "获得【危盟】?").set("ai", function () { var evt = _status.event.getParent(); return get.attitude(evt.player, evt.target) > 0; }); else event.finish(); - "step 4"; + ("step 4"); if (result.bool) { target.addTempSkill("gzweimeng_zongheng", { player: "phaseEnd" }); game.log(player, "发起了", "#y纵横", ",令", target, "获得了技能", "#g【危盟】"); @@ -9697,7 +9651,7 @@ export default () => { }) .sortBySeat(); player.line(event.targets, "green"); - "step 1"; + ("step 1"); var target = targets.shift(); event.target = target; if (target.isIn()) { @@ -9709,13 +9663,13 @@ export default () => { }); } else if (targets.length) event.redo(); else event.finish(); - "step 2"; + ("step 2"); if (result.bool) { target.lose(result.cards, ui.discardPile, "visible"); target.$throw(result.cards, 1000); game.log(target, "将", result.cards, "置入了弃牌堆"); } else target.damage(); - "step 3"; + ("step 3"); game.delayx(); if (targets.length) event.goto(1); }, @@ -9776,7 +9730,7 @@ export default () => { return get.effect(target, { name: "sha", isCard: true }, player, player); }); } - "step 1"; + ("step 1"); if (result.bool) { player.useCard({ name: "sha", isCard: true }, result.targets[0], "gzfangyuan", false); } @@ -9869,16 +9823,16 @@ export default () => { }, }) .setHiddenSkill("daming"); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; event.target = target; player.logSkill("daming", target); player.discard(result.cards); } else event.finish(); - "step 2"; + ("step 2"); if (!target.isLinked()) target.link(); - "step 3"; + ("step 3"); var map = {}, sides = [], pmap = _status.connectMode ? lib.playerOL : game.playerMap, @@ -9910,7 +9864,7 @@ export default () => { num++; } if (num > 0) player.draw(num); - "step 4"; + ("step 4"); if (trigger.player.isIn()) { var target = trigger.player, sha = game.filterPlayer(function (current) { @@ -9930,7 +9884,7 @@ export default () => { } else if (target.isDamaged()) event._result = { bool: false }; else event.finish(); } else event.finish(); - "step 5"; + ("step 5"); if (result.bool) { var target = result.targets[0]; if (player == trigger.player) player.line(target); @@ -10051,7 +10005,7 @@ export default () => { event.num = num; var next = trigger.player.chooseBool("是否发动【统度】摸" + get.cnNumber(num) + "张牌?"); if (player == trigger.player) next.setHiddenSkill("gztongduo"); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("gztongduo", trigger.player); trigger.player.draw(num); @@ -10099,13 +10053,13 @@ export default () => { "step 0"; player.awakenSkill("qingyin"); event.num = 0; - "step 1"; + ("step 1"); if (targets[num].isDamaged()) { targets[num].recover(targets[num].maxHp - targets[num].hp); } event.num++; if (event.num < targets.length) event.redo(); - "step 2"; + ("step 2"); if (lib.character[player.name1][3].includes("qingyin")) player.removeCharacter(0); if (lib.character[player.name2][3].includes("qingyin")) player.removeCharacter(1); }, @@ -10194,14 +10148,14 @@ export default () => { }) .set("prompt", "是否对" + str + "发动【连翩】?"); } - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; player.logSkill("gzlianpian", target); target.draw(Math.min(5, target.maxHp - target.countCards("h"))); } event.finish(); - "step 2"; + ("step 2"); if (result.control == "cancel2") { event.finish(); return; @@ -10212,7 +10166,7 @@ export default () => { target.discardPlayerCard("he", player, true); event.finish(); } else player.recover(); - "step 3"; + ("step 3"); game.delayx(); }, }, @@ -10237,7 +10191,7 @@ export default () => { "step 0"; player.loseHp(); event.target = trigger.player; - "step 1"; + ("step 1"); event.addIndex = 0; var list = []; if (target.maxHp > 0 && target.countCards("h") > 0) list.push("令其弃置" + get.cnNumber(target.maxHp) + "张手牌"); @@ -10255,7 +10209,7 @@ export default () => { target = _status.event.getParent().target; return target.hp - player.hp > Math.min(target.maxHp, target.countCards("h")) / 2 ? 1 : 0; }); - "step 2"; + ("step 2"); if (result.index + event.addIndex == 0) target.chooseToDiscard(target.maxHp, true, "h"); else target.loseHp(target.hp - player.hp); }, @@ -10273,16 +10227,16 @@ export default () => { content() { "step 0"; target.draw(Math.min(5, target.maxHp - target.countCards("h"))); - "step 1"; + ("step 1"); target.addTempSkill("gzboyan_block"); - "step 2"; + ("step 2"); if (target.isIn()) player.chooseBool("纵横:是否令" + get.translation(target) + "获得【驳言】?").set("ai", function () { var evt = _status.event.getParent(); return get.attitude(evt.player, evt.target) > 0; }); else event.finish(); - "step 3"; + ("step 3"); if (result.bool) { target.addTempSkill("gzboyan_zongheng", { player: "phaseEnd" }); game.log(player, "发起了", "#y纵横", ",令", target, "获得了技能", "#g【驳言】"); @@ -10382,12 +10336,12 @@ export default () => { return 5 - get.value(card); }) .set("goon", target.canUse("sha", player, false) && get.effect(player, { name: "sha" }, target, target) > 0); - "step 1"; + ("step 1"); if (!result.bool) { player.gainPlayerCard(target, "he", true); event.finish(); } else target.give(result.cards, player); - "step 2"; + ("step 2"); if (result.bool && result.cards && result.cards.length && target.isIn() && player.isIn() && get.suit(result.cards[0], target) == "spade" && target.canUse("sha", player, false)) target.useCard({ name: "sha", isCard: true }, false, player); }, ai: { @@ -10459,11 +10413,11 @@ export default () => { event.players = targets.slice(0); game.delayx(); player.chooseJunlingFor(event.players[0]).set("prompt", "为所有目标角色选择军令牌"); - "step 1"; + ("step 1"); event.junling = result.junling; event.targets = result.targets; event.num = 0; - "step 2"; + ("step 2"); if (num < event.players.length) event.current = event.players[num]; if (event.current && event.current.isAlive()) { event.current @@ -10475,18 +10429,18 @@ export default () => { return get.junlingEffect(evt.player, evt.junling, evt.current, evt.targets, evt.current) > get.damageEffect(evt.current, evt.player, evt.current) / get.attitude(evt.current, evt.current) ? 0 : 1; }); } else event.goto(4); - "step 3"; + ("step 3"); if (result.index == 0) { event.current.carryOutJunling(player, event.junling, targets); } else { player.draw(); event.current.damage(); } - "step 4"; + ("step 4"); game.delayx(); event.num++; if (event.num < event.players.length) event.goto(2); - "step 5"; + ("step 5"); var list = player.getStorage("gzduwu_count").filter(function (target) { return target.isAlive(); }); @@ -10564,7 +10518,7 @@ export default () => { return eff - val; }) .setHiddenSkill(event.name); - "step 1"; + ("step 1"); if (result.bool) { var next = player.useCard({ name: "sha" }, result.cards, "gzxishe", trigger.player, false); if (player.hp > trigger.player.hp) @@ -10572,7 +10526,7 @@ export default () => { _status.event.directHit.add(trigger.player); }; } else event.finish(); - "step 2"; + ("step 2"); if (trigger.player.isDead()) { player.mayChangeVice(null, "hidden"); } else if (lib.skill.gzxishe.filter(trigger, player)) event.goto(0); @@ -10597,7 +10551,7 @@ export default () => { content() { "step 0"; player.showHandcards(); - "step 1"; + ("step 1"); if (!player.countCards("h", { color: "red" })) event._result = { control: "黑色" }; else if (!player.countCards("h", { color: "black" })) event._result = { control: "红色" }; else @@ -10607,7 +10561,7 @@ export default () => { if (player.countCards("h", { color: "red" }) <= num && player.countCards("h", { color: "black" }) > num) return "红色"; return "黑色"; }); - "step 2"; + ("step 2"); event.control = result.control; var cards; if (event.control == "红色") { @@ -10617,7 +10571,7 @@ export default () => { } player.discard(cards); event.num = cards.length; - "step 3"; + ("step 3"); player .chooseTarget("请选择至多" + get.cnNumber(event.num) + "名有牌的其他角色,获得这些角色的各一张牌。", [1, event.num], function (card, player, target) { return target != player && target.countCards("he") > 0; @@ -10625,7 +10579,7 @@ export default () => { .set("ai", function (target) { return -get.attitude(_status.event.player, target) + 0.5; }); - "step 4"; + ("step 4"); if (result.bool && result.targets) { player.line(result.targets, "green"); event.targets = result.targets; @@ -10634,14 +10588,14 @@ export default () => { } else { event.finish(); } - "step 5"; + ("step 5"); if (player.isAlive() && event.targets.length) { player.gainPlayerCard(event.targets.shift(), "he", true); } else event.finish(); - "step 6"; + ("step 6"); if (result.bool && result.cards && result.cards.length) event.cards.addArray(result.cards); if (event.targets.length) event.goto(5); - "step 7"; + ("step 7"); var hs = player.getCards("h"); cards = cards.filter(function (card) { return get.type(card) == "equip" && hs.includes(card); @@ -10715,7 +10669,7 @@ export default () => { if (get.attitude(_status.event.player, target) > 0) return Math.random() + Math.sqrt(target.hp); return Math.random() + Math.sqrt(Math.max(1, 4 - target.hp)); }); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; player.logSkill("gzcongcha", target); @@ -10788,7 +10742,7 @@ export default () => { trigger.player.removeSkill("gzcongcha_ai"); if (player.isFriendOf(trigger.player)) game.asyncDraw([player, trigger.player].sortBySeat(_status.currentPhase), 2); else trigger.player.loseHp(); - "step 1"; + ("step 1"); game.delayx(); }, mark: "character", @@ -10806,7 +10760,7 @@ export default () => { content() { "step 0"; player.showHandcards(); - "step 1"; + ("step 1"); var hs = player.countCards("h"); if ( game.hasPlayer(function (current) { @@ -10817,7 +10771,7 @@ export default () => { return target != player && target.countCards("h") <= player.countCards("h"); }); } else event.finish(); - "step 2"; + ("step 2"); if (result.bool) { var target = result.targets[0]; player.line(target, "green"); @@ -10884,7 +10838,7 @@ export default () => { player.addTempSkill("gzsuzhi_count"); player.addMark("gzsuzhi_count", 1, false); if (trigger.delay == false) game.delay(); - "step 1"; + ("step 1"); player.gainPlayerCard(trigger.player, "he", true); }, }, @@ -10929,7 +10883,7 @@ export default () => { return current.isEnemyOf(player) && player.inRangeOf(current); }) .sortBySeat(); - "step 1"; + ("step 1"); var target = event.targets.shift(); if (target.isIn()) { event.target = target; @@ -10950,7 +10904,7 @@ export default () => { .set("sourcex", player); } else if (targets.length) event.redo(); else event.finish(); - "step 2"; + ("step 2"); if (result.bool == false && target.countCards("he") > 0) { player.discardPlayerCard(target, "he", true); } @@ -11000,7 +10954,7 @@ export default () => { return get.attitude(_status.event.player, target) * Math.sqrt(1 + target.needsToDiscard()); }); } else event.finish(); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; player.line(target, "green"); @@ -11109,14 +11063,14 @@ export default () => { }) .set("targets", trigger.targets) .set("card", trigger.card); - "step 1"; + ("step 1"); if (result.bool) { if (!event.isMine() && !event.isOnline()) game.delayx(); event.targets = result.targets; } else { event.finish(); } - "step 2"; + ("step 2"); if (event.targets) { player.logSkill("gzzhuosheng2", event.targets); if (trigger.targets.includes(event.targets[0])) trigger.targets.removeArray(event.targets); @@ -11263,9 +11217,9 @@ export default () => { content() { "step 0"; player.give(cards, target); - "step 1"; + ("step 1"); player.chooseJunlingFor(target); - "step 2"; + ("step 2"); event.junling = result.junling; event.targets = result.targets; var str = get.translation(player); @@ -11292,7 +11246,7 @@ export default () => { if (get.attitude(player, target) > 0) return get.junlingEffect(source, junling, player, targets, player) > 0; return get.junlingEffect(source, junling, player, targets, player) > 1; }); - "step 3"; + ("step 3"); if (result.index == 0) { target.carryOutJunling(player, event.junling, targets); player.draw(); @@ -11403,7 +11357,7 @@ export default () => { var player = _status.event.player; return (1 - get.sgn(get.attitude(player, target))) * Math.max(1, get.distance(player, target)); }); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; player.line(target, "green"); @@ -11539,7 +11493,7 @@ export default () => { player.chooseButton(["暗置" + get.translation(target) + "的一张武将牌", [[target.name1, target.name2], "character"]], true).set("filterButton", function (button) { return !get.is.jun(button.link); }); - "step 1"; + ("step 1"); var target1 = target.getNext(); var target2 = target.getPrevious(); if (target1 == target2 || target.inline(target1) || target.inline(target2) || target1.inline(target2)) event.finish(); @@ -11550,7 +11504,7 @@ export default () => { target.hideCharacter(result.links[0] == target.name1 ? 0 : 1); target.addTempSkill("donggui2"); player.useCard({ name: "diaohulishan", isCard: true }, target); - "step 2"; + ("step 2"); if (event.target1.inline(event.target2)) { player.draw( game.countPlayer(function (current) { @@ -11599,7 +11553,7 @@ export default () => { return current.inline(player); }) .sortBySeat(); - "step 1"; + ("step 1"); var target = event.list.shift(); if ((target == player || player.hasSkill("fengyang")) && target.countCards("e")) { event.target = target; @@ -11609,11 +11563,11 @@ export default () => { next.logSkill = "fengyang"; if (player == target) next.setHiddenSkill("fengyang"); } else event.goto(3); - "step 2"; + ("step 2"); if (result.bool) { target.draw(2); } - "step 3"; + ("step 3"); if (event.list.length) event.goto(1); }, }, @@ -11798,7 +11752,7 @@ export default () => { var cards = player.getCards("h"); event.num = cards.length; player.discard(cards); - "step 1"; + ("step 1"); var target = trigger.player, str = get.translation(target); event.target = target; @@ -11810,7 +11764,7 @@ export default () => { .chooseControl() .set("choiceList", ["弃置" + str + "的" + get.cnNumber(num) + "张牌", "对" + str + "造成1点伤害"]) .set("ai", () => 1); - "step 2"; + ("step 2"); if (result.index == 0) player.discardPlayerCard(target, num, true, "he"); else target.damage(); }, @@ -11861,7 +11815,7 @@ export default () => { list.sortBySeat(target); event.targets = list; } else event.finish(); - "step 1"; + ("step 1"); var target = targets.shift(); if (target.countDiscardableCards(player, "he") > 0) player.discardPlayerCard(target, "he", true).boolline = true; if (targets.length) event.redo(); @@ -11986,7 +11940,7 @@ export default () => { }); return [cards, cards.splice(2)]; }); - "step 1"; + ("step 1"); var top = result.moved[0]; var bottom = result.moved[1]; top.reverse(); @@ -12095,7 +12049,7 @@ export default () => { if (att > 0) return Math.sqrt(att) / 10; return 5 - att; }); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; event.target = target; @@ -12104,12 +12058,12 @@ export default () => { } else { event.finish(); } - "step 2"; + ("step 2"); if (result.bool) { event.card = result.cards[0]; target.give(result.cards, player).gaintag.add("gzwenji"); } - "step 3"; + ("step 3"); if (target.identity == "unknown" || target.isFriendOf(player)) { player.addTempSkill("gzwenji_respond"); event.finish(); @@ -12127,7 +12081,7 @@ export default () => { return 5 - get.value(card); }); } else event.finish(); - "step 4"; + ("step 4"); if (result.bool) { player.give(result.cards, target); player.removeGaintag("gzwenji"); @@ -12225,14 +12179,14 @@ export default () => { content() { "step 0"; event.count = trigger.num; - "step 1"; + ("step 1"); event.count--; player.draw(); - "step 2"; + ("step 2"); if (event.count > 0) { player.chooseBool(get.prompt2("gzbushi")).set("frequentSkill", "gzbushi"); } else event.finish(); - "step 3"; + ("step 3"); if (result.bool) event.goto(1); }, group: "gzbushi_draw", @@ -12247,12 +12201,12 @@ export default () => { content() { "step 0"; trigger.player.chooseBool("是否对" + get.translation(player) + "发动【布施】?", "你摸一张牌,然后其摸一张牌"); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("gzbushi", trigger.player); game.asyncDraw([trigger.player, player]); } else event.finish(); - "step 2"; + ("step 2"); game.delayx(); }, }, @@ -12278,7 +12232,7 @@ export default () => { "step 0"; event.count = trigger.num; if (event.triggername == "damageSource") event.count = 1; - "step 1"; + ("step 1"); event.count--; var target = trigger.player; var list = game.filterPlayer(function (current) { @@ -12293,7 +12247,7 @@ export default () => { }) .set("target", target); } else event.finish(); - "step 2"; + ("step 2"); if (result.bool) { var target = result.targets[0]; player.line(target, "green"); @@ -12317,7 +12271,7 @@ export default () => { var next = trigger.player.chooseBool("是否对" + get.translation(player) + "发动【米道】?", "令该角色修改" + get.translation(trigger.card) + "的花色和伤害属性"); next.set("ai", () => false); if (player == next.player) next.setHiddenSkill(event.name); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("gzmidao"); trigger.player.addTempSkill("gzmidao2"); @@ -12326,7 +12280,7 @@ export default () => { //player.gain(result.cards,trigger.player,'giveAuto'); } } else event.finish(); - "step 2"; + ("step 2"); if (player.isUnderControl()) { game.swapPlayerAuto(player); } @@ -12447,7 +12401,7 @@ export default () => { } else { switchToAuto(); } - "step 3"; + ("step 3"); var map = event.result || result; if (map.bool) { game.log(player, "将", trigger.card, "的花色属性修改为了", "#g" + get.translation(map.suit + 2), "#y" + get.translation(map.nature)); @@ -12520,7 +12474,7 @@ export default () => { if (dist > 1 && dist - target.countCards("e") <= 1) return true; return 0; }); - "step 1"; + ("step 1"); if (result.index == 0) player.draw(); else { target.discardPlayerCard(player, "e", true); @@ -12557,7 +12511,7 @@ export default () => { if (dist > 1 && dist - target.countCards("e") <= 1) return true; return false; }); - "step 1"; + ("step 1"); if (result.bool) { var target = trigger.player; event.target = target; @@ -12565,7 +12519,7 @@ export default () => { target.line(player, "green"); target.discardPlayerCard(player, "e", true); } else event.finish(); - "step 2"; + ("step 2"); var list = ["失去1点体力", "令" + get.translation(player) + "摸两张牌"]; event.addIndex = 0; if ( @@ -12592,7 +12546,7 @@ export default () => { else if (player.hp + player.countCards("h", "tao") > 3 && !player.hasJudge("lebu")) num = 1; return num - _status.event.getParent().addIndex; }); - "step 3"; + ("step 3"); switch (result.index + event.addIndex) { case 0: target.chooseToDiscard(2, "h", true); @@ -13204,7 +13158,7 @@ export default () => { content() { "step 0"; player.chooseJunlingFor(trigger.source); - "step 1"; + ("step 1"); event.junling = result.junling; event.targets = result.targets; var choiceList = []; @@ -13218,7 +13172,7 @@ export default () => { if (get.recoverEffect(trigger.player, player, _status.event.player) > 0) return 1; return get.attitude(trigger.source, trigger.player) < 0 && get.junlingEffect(player, result.junling, trigger.source, result.targets, trigger.source) >= -2 ? 1 : 0; }); - "step 2"; + ("step 2"); if (result.index == 0) trigger.source.carryOutJunling(player, event.junling, targets); else trigger.player.recover(player); }, @@ -13258,7 +13212,7 @@ export default () => { }) .set("check", check) .setHiddenSkill(event.name); - "step 1"; + ("step 1"); var logged = false; if (result.cards) { logged = true; @@ -13278,7 +13232,7 @@ export default () => { return 0; }); } else event.finish(); - "step 2"; + ("step 2"); if (result.judge > 0) player.draw(); }, }, @@ -13299,7 +13253,7 @@ export default () => { player.chooseBool("是否令" + get.translation(_status.currentPhase) + "本回合的手牌上限和使用【杀】的次数上限+1?").ai = function () { return get.attitude(player, _status.currentPhase) > 0; }; - "step 1"; + ("step 1"); if (result.bool) { var target = _status.currentPhase; if (!target.hasSkill("zhuwei_eff")) { @@ -13345,7 +13299,7 @@ export default () => { content() { "step 0"; player.chooseJunlingFor(target); - "step 1"; + ("step 1"); event.junling = result.junling; event.targets = result.targets; var choiceList = ["执行该军令"]; @@ -13359,7 +13313,7 @@ export default () => { if (get.attitude(target, player) >= 0) return get.junlingEffect(player, result.junling, target, result.targets, target) >= 0 ? 0 : 1; return get.junlingEffect(player, result.junling, target, result.targets, target) >= -1 ? 0 : 1; }); - "step 2"; + ("step 2"); if (result.index == 0) target.carryOutJunling(player, event.junling, targets); else if (target != player && target.countCards("h")) { event.num = target.countCards("h"); @@ -13368,7 +13322,7 @@ export default () => { return -get.value(card); }); } else event.finish(); - "step 3"; + ("step 3"); if (result.cards) { player.give(result.cards, target); } @@ -13523,12 +13477,12 @@ export default () => { return 9 - get.value(card); }) .setHiddenSkill(event.name); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("gzfudi", trigger.source); player.give(result.cards, trigger.source); } else event.finish(); - "step 2"; + ("step 2"); var list = game.filterPlayer(function (current) { return ( current.hp >= player.hp && @@ -13550,7 +13504,7 @@ export default () => { return get.damageEffect(target, player, player); }); } else event.finish(); - "step 3"; + ("step 3"); if (result.bool && result.targets.length) { player.line(result.targets[0]); result.targets[0].damage(); @@ -13675,7 +13629,7 @@ export default () => { return -1; }; } - "step 1"; + ("step 1"); if (!result.bool) event.finish(); else { var list = ["主将", "副将"]; @@ -13689,13 +13643,13 @@ export default () => { }).prompt = "请选择暗置一张武将牌"; } } - "step 2"; + ("step 2"); if (!result.control) event.finish(); else { var num = result.control == "主将" ? 0 : 1; player.hideCharacter(num); } - "step 3"; + ("step 3"); player .chooseControl(event.skills) .set("ai", function () { @@ -13712,7 +13666,7 @@ export default () => { return skills.randomGet(); }) .set("prompt", "选择获得其中的一个技能直到君主的回合开始"); - "step 4"; + ("step 4"); var link = result.control; player.addTempSkill(link, "jiananUpdate"); player.addTempSkill("jianan_eff", "jiananUpdate"); @@ -13767,7 +13721,7 @@ export default () => { content() { "step 0"; targets[0].damage(player); - "step 1"; + ("step 1"); if (targets[0].isAlive()) targets[0].draw(2); targets[1].recover(); }, @@ -13810,7 +13764,7 @@ export default () => { content() { "step 0"; player.chooseBool("是否发动【总御】,与" + get.translation(trigger.player) + "交换装备区内坐骑牌?"); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("gzzongyu", trigger.player); event.cards = [player.getCards("e", { subtype: ["equip3", "equip4"] }), trigger.player.getCards("e", { name: "liulongcanjia" })]; @@ -13819,7 +13773,7 @@ export default () => { if (event.cards[0].length) player.$give(event.cards[0], trigger.player); if (event.cards[1].length) trigger.player.$give(event.cards[1], player); } else event.finish(); - "step 2"; + ("step 2"); for (var i = 0; i < event.cards[1].length; i++) player.equip(event.cards[1][i]); for (var i = 0; i < event.cards[0].length; i++) trigger.player.equip(event.cards[0][i]); }, @@ -13957,7 +13911,7 @@ export default () => { }) .set("prompt", "征辟:请选择一项") .set("choiceList", choices); - "step 1"; + ("step 1"); if (result.index == 0) player.chooseTarget( "请选择一名未确定势力的角色", @@ -13988,7 +13942,7 @@ export default () => { }, }) .set("forced", true); - "step 2"; + ("step 2"); event.target = result.targets[0]; player.line(result.targets, "green"); if (result.cards.length) { @@ -13999,7 +13953,7 @@ export default () => { player.addTempSkill("gzzhengbi_eff1", "phaseUseAfter"); event.finish(); } - "step 3"; + ("step 3"); var choices = []; if (target.countCards("he", { type: ["trick", "delay", "equip"] })) choices.push("一张非基本牌"); if (target.countCards("h", { type: "basic" }) > 1) choices.push("两张基本牌"); @@ -14026,10 +13980,10 @@ export default () => { event.finish(); } else event.finish(); } - "step 4"; + ("step 4"); var check = result.control == "一张非基本牌"; target.chooseCard("he", check ? 1 : 2, { type: check ? ["trick", "delay", "equip"] : "basic" }, true); - "step 5"; + ("step 5"); if (result.cards) { target.give(result.cards, player); } @@ -14087,7 +14041,7 @@ export default () => { player.awakenSkill("gzfengying"); player.storage.gzfengying = true; player.useCard({ name: "xietianzi" }, cards, target); - "step 1"; + ("step 1"); var list = game.filterPlayer(function (current) { return current.isFriendOf(player) && current.countCards("h") < current.maxHp; }); @@ -14192,14 +14146,14 @@ export default () => { }, }) .setHiddenSkill("gzjieyue"); - "step 1"; + ("step 1"); if (result.bool) { event.target = result.targets[0]; player.logSkill("gzjieyue", result.targets); player.give(result.cards[0], result.targets[0]); player.chooseJunlingFor(result.targets[0]); } else event.finish(); - "step 2"; + ("step 2"); event.junling = result.junling; event.targets = result.targets; var choiceList = []; @@ -14213,7 +14167,7 @@ export default () => { if (get.attitude(target, player) > 0) return get.junlingEffect(player, result.junling, target, result.targets, target) > 1 ? 0 : 1; return get.junlingEffect(player, result.junling, target, result.targets, target) >= -1 ? 0 : 1; }); - "step 3"; + ("step 3"); if (result.index == 0) { target.carryOutJunling(player, event.junling, targets); player.draw(); @@ -14253,7 +14207,7 @@ export default () => { player.awakenSkill("jianglue"); player.addTempSkill("jianglue_count"); player.chooseJunlingFor(player).set("prompt", "选择一张军令牌,令与你势力相同的其他角色选择是否执行"); - "step 1"; + ("step 1"); event.junling = result.junling; event.targets = result.targets; event.players = game @@ -14266,7 +14220,7 @@ export default () => { event.filterName = function (name) { return lib.character[name][1] == player.identity && !get.is.double(name); }; - "step 2"; + ("step 2"); if (num < event.players.length) event.current = event.players[num]; if (event.current && event.current.isAlive()) { event.showCharacter = false; @@ -14294,7 +14248,7 @@ export default () => { }); } else event.current.chooseJunlingControl(player, event.junling, targets).set("prompt", "将略").set("controls", ["ok"]); } else event.goto(4); - "step 3"; + ("step 3"); event.carry = false; if (result.index == 0 && result.control != "ok") { event.carry = true; @@ -14312,7 +14266,7 @@ export default () => { else event._result = { index: list[0] == "主将" ? 0 : 1 }; } } - "step 4"; + ("step 4"); if (!event.list) event.list = [player]; if (event.carry) { if (event.showCharacter) event.current.showCharacter(result.index); @@ -14321,16 +14275,16 @@ export default () => { } event.num++; if (event.num < event.players.length) event.goto(2); - "step 5"; + ("step 5"); event.num = 0; player.storage.jianglue_count = 0; - "step 6"; + ("step 6"); if (event.list[num].isAlive()) { event.list[num].gainMaxHp(true); event.list[num].recover(); } event.num++; - "step 7"; + ("step 7"); if (event.num < event.list.length) event.goto(6); else if (player.storage.jianglue_count > 0) player.draw(player.storage.jianglue_count); }, @@ -14427,7 +14381,7 @@ export default () => { })() ) .set("prompt", "选择并获得一项技能直到回合结束"); - "step 1"; + ("step 1"); player.popup(result.control); var map = { new_rewusheng: "fz_wusheng", @@ -14497,7 +14451,7 @@ export default () => { return get.attitude(_status.event.player, target); }) .set("source", trigger.getParent(2).player); - "step 1"; + ("step 1"); if (result.bool && result.targets && result.targets.length) { player.logSkill("fz_new_longdan", result.targets[0]); result.targets[0].recover(); @@ -14524,7 +14478,7 @@ export default () => { return -get.attitude(_status.event.player, target); }) .set("target", trigger.target); - "step 1"; + ("step 1"); if (result.bool && result.targets && result.targets.length) { player.logSkill("fz_new_longdan", result.targets[0]); result.targets[0].damage(); @@ -14655,7 +14609,7 @@ export default () => { if (get.attitude(_status.event.player, _status.event.getParent().player) > 0) return 11 - get.value(card); return 7 - get.value(card); }); - "step 1"; + ("step 1"); if (result.bool) { trigger.source.give(result.cards[0], player, "giveAuto"); } else trigger.source.loseHp(); @@ -14688,7 +14642,7 @@ export default () => { event.num = list.length; player.draw(event.num); if (event.num > 2) player.turnOver(); - "step 1"; + ("step 1"); player .chooseCard("h", true, "弃置一张手牌,若以此法弃置的是装备牌,则你改为使用之") .set("ai", function (card) { @@ -14698,7 +14652,7 @@ export default () => { return -get.value(card); }) .set("filterCard", lib.filter.cardDiscardable); - "step 2"; + ("step 2"); if (result.bool && result.cards.length) { if (get.type(result.cards[0]) == "equip" && player.hasUseTarget(result.cards[0])) { player.chooseUseTarget(result.cards[0], true, "nopopup"); @@ -14772,7 +14726,7 @@ export default () => { content() { "step 0"; event.num = trigger.num || 1; - "step 1"; + ("step 1"); player .chooseTarget(get.prompt2("new_shushen"), function (card, player, target) { return target != player; @@ -14781,7 +14735,7 @@ export default () => { return get.attitude(_status.event.player, target); }) .setHiddenSkill("new_shushen"); - "step 2"; + ("step 2"); if (result.bool) { player.logSkill("new_shushen", result.targets); result.targets[0].draw(); @@ -14918,7 +14872,7 @@ export default () => { "step 0"; event.target = target; event.done = false; - "step 1"; + ("step 1"); if (get.is.jun(event.target)) { event._result = { control: "副将" }; } else { @@ -14943,7 +14897,7 @@ export default () => { .set("prompt", "暗置" + get.translation(event.target) + "的一张武将牌") .set("choice", choice); } - "step 2"; + ("step 2"); if (result.control == "主将") { event.target.hideCharacter(0); } else { @@ -14959,7 +14913,7 @@ export default () => { return -get.attitude(_status.event.player, target); }); } else event.finish(); - "step 3"; + ("step 3"); if (result.bool && result.targets && result.targets.length) { player.line(result.targets[0], "green"); event.done = true; @@ -15153,7 +15107,7 @@ export default () => { return get.attitude(_status.event.player, target); }) .set("source", trigger.getParent(2).player); - "step 1"; + ("step 1"); if (result.bool && result.targets && result.targets.length) { player.logSkill("new_longdan", result.targets[0]); result.targets[0].recover(); @@ -15181,7 +15135,7 @@ export default () => { return -get.attitude(_status.event.player, target); }) .set("target", trigger.target); - "step 1"; + ("step 1"); if (result.bool && result.targets && result.targets.length) { player.logSkill("new_longdan", result.targets[0]); result.targets[0].damage(); @@ -15367,7 +15321,7 @@ export default () => { content() { "step 0"; player.discardPlayerCard(target, "he", true); - "step 1"; + ("step 1"); if (result.bool) { if (get.suit(result.cards[0]) == "spade") event.getParent().draw.push(target); } @@ -15377,7 +15331,7 @@ export default () => { var list = event.getParent().draw; if (!list.length) event.finish(); else game.asyncDraw(list); - "step 1"; + ("step 1"); game.delay(); }, ai: { @@ -15477,7 +15431,7 @@ export default () => { return att / 3; }) .setHiddenSkill("gzjieming"); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("gzjieming", result.targets); for (var i = 0; i < result.targets.length; i++) { @@ -15543,7 +15497,7 @@ export default () => { return target.countCards("h") + 1; } }; - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; event.target = target; @@ -15560,7 +15514,7 @@ export default () => { event.finish(); } } else event.finish(); - "step 2"; + ("step 2"); if (result.bool) { target.loseHp(); } else { @@ -15687,18 +15641,18 @@ export default () => { .set("prompt", "请选择一个武将牌,令" + get.translation(target) + "该武将牌上的非锁定技全部失效。"); } } else event.goto(2); - "step 1"; + ("step 1"); if (result.control) { player.popup(result.control, "fire"); var target = trigger.target; if (result.control == "主将") target.addTempSkill("fengyin_main"); else target.addTempSkill("fengyin_vice"); } - "step 2"; + ("step 2"); player.judge(function () { return 0; }); - "step 3"; + ("step 3"); var suit = get.suit(result.card); var target = trigger.target; var num = target.countCards("h", "shan"); @@ -15714,7 +15668,7 @@ export default () => { }) .set("num", num) .set("suit", suit); - "step 4"; + ("step 4"); if (!result.bool) { trigger.getParent().directHit.add(trigger.target); } @@ -15862,7 +15816,7 @@ export default () => { } if (choice.length == 2) choice.push("全部明置"); player.chooseControl(choice); - "step 1"; + ("step 1"); if (result.control) { switch (result.control) { case "取消": @@ -16040,7 +15994,7 @@ export default () => { player.removeMark(player.hasMark("xianqu_mark") ? "xianqu_mark" : "yexinjia_mark", 1); var num = 4 - player.countCards("h"); if (num) player.draw(num); - "step 1"; + ("step 1"); if ( game.hasPlayer(function (current) { return current != player && current.isUnseen(2); @@ -16059,7 +16013,7 @@ export default () => { return -get.attitude(_status.event.player, target); }); else event.finish(); - "step 2"; + ("step 2"); if (result.bool) { event.target = result.targets[0]; player.line(event.target, "green"); @@ -16074,7 +16028,7 @@ export default () => { player.removeSkill("xianqu_mark"); event.finish(); } - "step 3"; + ("step 3"); if (result.control) { if (result.control == "主将") { player.viewCharacter(event.target, 0); @@ -16184,7 +16138,7 @@ export default () => { content() { "step 0"; player.give(cards, target); - "step 1"; + ("step 1"); if (!target.isUnseen()) { player.draw(cards.length); } @@ -16268,7 +16222,7 @@ export default () => { }) .set("suits", suits) .setHiddenSkill("qianhuan"); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("qianhuan"); var card = result.cards[0]; @@ -16322,7 +16276,7 @@ export default () => { return 0; }) .set("createDialog", [get.prompt("qianhuan"), '
          移去一张“千幻”牌令' + get.translation(trigger.player) + "对" + get.translation(trigger.target) + "的" + get.translation(trigger.card) + "失效
          ", player.getExpansions("qianhuan")]); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("qianhuan", trigger.player); trigger.getParent().targets.remove(trigger.target); @@ -16350,7 +16304,7 @@ export default () => { player.gainPlayerCard(trigger.player, "ej", true); } trigger.cancel(); - "step 1"; + ("step 1"); if (player.isFriendOf(trigger.player)) { trigger.player.mayChangeVice(); } @@ -16404,7 +16358,7 @@ export default () => { return get.effect(target, { name: "guohe_copy2" }, player, player); }) .setHiddenSkill(event.name); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("xuanlve", result.targets); player.discardPlayerCard(result.targets[0], "he", true); @@ -16461,7 +16415,7 @@ export default () => { event.finish(); return; } - "step 1"; + ("step 1"); var list = []; var discards = []; var type = get.type(cards[0], "trick"); @@ -16518,7 +16472,7 @@ export default () => { content() { "step 0"; player.draw(); - "step 1"; + ("step 1"); var target = game.findPlayer(function (current) { return current != player && current.countCards("e", "dinglanyemingzhu"); }); @@ -16557,7 +16511,7 @@ export default () => { content() { "step 0"; player.chooseCardButton("将一张“烽火”置入弃牌堆", player.getExpansions("yuanjiangfenghuotu"), true); - "step 1"; + ("step 1"); if (result.bool) { var card = result.links[0]; player.loseToDiscardpile(card); @@ -16646,7 +16600,7 @@ export default () => { "step 0"; var zhu = get.zhu(player, "jiahe"); event.num = zhu.getExpansions("yuanjiangfenghuotu").length; - "step 1"; + ("step 1"); var list = []; if (event.num >= 1 && !(player.hasSkill("reyingzi") || player.hasSkill("jiahe_reyingzi"))) list.push("reyingzi"); if (event.num >= 2 && !(player.hasSkill("haoshi") || player.hasSkill("jiahe_haoshi"))) list.push("haoshi"); @@ -16691,7 +16645,7 @@ export default () => { } return controls.randomGet(); }); - "step 2"; + ("step 2"); if (result.control != "cancel2") { var map = { reyingzi: "jiahe_reyingzi", @@ -17076,7 +17030,7 @@ export default () => { return get.rank(button.link, true); }) .set("createDialog", ["选择至多两张武将牌作为“化身”", [list, "character"]]); - "step 1"; + ("step 1"); if (result.bool) { for (var i = 0; i < result.links.length; i++) { lib.skill.gzhuashen.addCharacter(player, result.links[i]); @@ -17108,7 +17062,7 @@ export default () => { return Math.random() - 0.3; }) .set("createDialog", ["是否替换一张“化身”?", [list, "character"]]); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("gzhuashen"); game.log(player, "替换了一张", "#g化身"); @@ -17184,7 +17138,7 @@ export default () => { } else { player.chooseButton(true).set("createDialog", ["移除一张“化身”牌", [sources, "character"]]); } - "step 1"; + ("step 1"); if (!event.directresult && result && result.links[0]) { event.directresult = result.links[0]; } @@ -17224,7 +17178,7 @@ export default () => { "step 0"; player.awakenSkill("gzxiongsuan"); target.damage("nocard"); - "step 1"; + ("step 1"); player.draw(3); var list = []; var skills = target.getOriginalSkills(); @@ -17242,7 +17196,7 @@ export default () => { } else { event.finish(); } - "step 2"; + ("step 2"); target.storage.gzxiongsuan_restore = result.control; target.addTempSkill("gzxiongsuan_restore"); }, @@ -17341,7 +17295,7 @@ export default () => { return 0; }) .set("goon", player.countCards("h", "sha") == 0); - "step 1"; + ("step 1"); if (result.bool) { var card = result.links[0]; trigger.untrigger(); @@ -17445,7 +17399,7 @@ export default () => { player.chooseCardButton(get.prompt("hongfa"), player.getExpansions("huangjintianbingfu")).set("ai", function () { return 1; }); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("hongfa_hp"); player.loseToDiscardpile(result.links); @@ -17564,7 +17518,7 @@ export default () => { }); return [cards]; }); - "step 1"; + ("step 1"); if (result.bool) { var list = result.moved[0].slice(0); while (list.length) { @@ -17668,7 +17622,7 @@ export default () => { ui.cardPile.appendChild(i); } } - "step 1"; + ("step 1"); player.draw(2); }, }, @@ -17727,11 +17681,11 @@ export default () => { if (num > 0) { player.draw(num); } - "step 1"; + ("step 1"); if (player.hp < 2) { player.recover(2 - player.hp); } - "step 2"; + ("step 2"); player.removeSkill("wuhujiangdaqi"); player.changeSkills(["rerende"], ["shouyue"]); }, @@ -17769,7 +17723,7 @@ export default () => { return evt && evt.hs && evt.hs.length; }) .sortBySeat(_status.currentPhase); - "step 1"; + ("step 1"); var target = event.list.shift(); event.target = target; if (target.isAlive() && target.countCards("h") == 0) { @@ -17780,12 +17734,12 @@ export default () => { }) .setHiddenSkill(event.name); } else event.goto(3); - "step 2"; + ("step 2"); if (result.bool) { player.logSkill(event.name, target); target.draw(); } - "step 3"; + ("step 3"); if (event.list.length) event.goto(1); }, }, @@ -17812,7 +17766,7 @@ export default () => { var target = lib.skill.gzyicheng.logTarget(trigger, player); event.target = target; target.chooseBool(get.prompt("gzyicheng"), "摸一张牌,然后弃置一张牌").set("frequentSkill", "gzyicheng"); - "step 1"; + ("step 1"); if (result.bool) { player.logSkill("gzyicheng", target); target.draw(); @@ -17831,7 +17785,7 @@ export default () => { content() { "step 0"; event.targets[0].draw(); - "step 1"; + ("step 1"); event.targets[0].chooseToDiscard("he", true); }, }, @@ -17861,7 +17815,7 @@ export default () => { player.chooseCardButton(get.prompt("ziliang", trigger.player), player.getExpansions("tuntian")).set("ai", function (button) { return get.value(button.link); }); - "step 1"; + ("step 1"); if (result.bool) { var card = result.links[0]; player.logSkill("ziliang", trigger.player); @@ -17908,7 +17862,7 @@ export default () => { }), }) .setHiddenSkill("gzhuyuan"); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0], card = result.cards[0]; @@ -17922,7 +17876,7 @@ export default () => { event.finish(); } } else event.finish(); - "step 2"; + ("step 2"); if ( game.hasPlayer(function (current) { return current.hasCard(function (card) { @@ -17941,7 +17895,7 @@ export default () => { return get.effect(target, { name: "guohe_copy", position: "ej" }, player, player); }); } else event.finish(); - "step 3"; + ("step 3"); if (result.bool) { var target = result.targets[0]; player.line(target, "thunder"); @@ -17977,7 +17931,7 @@ export default () => { prompt: get.prompt2("huyuan"), }) .setHiddenSkill("huyuan"); - "step 1"; + ("step 1"); if (result.bool) { var target = result.targets[0]; player.logSkill("huyuan", target); @@ -18000,7 +17954,7 @@ export default () => { } else { event.finish(); } - "step 2"; + ("step 2"); if (result.bool && result.targets.length) { event.current.line(result.targets, "green"); player.discardPlayerCard(true, result.targets[0], "he"); @@ -18060,7 +18014,7 @@ export default () => { content() { "step 0"; target.viewHandcards(player); - "step 1"; + ("step 1"); if (!target.countCards("h")) { event._result = { index: 1 }; } else if (!target.isUnseen(2)) { @@ -18068,7 +18022,7 @@ export default () => { } else { player.chooseControl().set("choiceList", ["观看" + get.translation(target) + "的手牌并可以弃置其中的一张黑色牌", "观看" + get.translation(target) + "的所有暗置的武将牌"]); } - "step 2"; + ("step 2"); if (result.index == 0) { player .discardPlayerCard(target, "h") @@ -18166,7 +18120,7 @@ export default () => { } else { player.removeCharacter(1); } - "step 1"; + ("step 1"); target.addSkills("gzyongjue"); if (target != player) { target.draw(2); @@ -18252,10 +18206,10 @@ export default () => { content() { "step 0"; player.removeCharacter(1); - "step 1"; + ("step 1"); player.removeSkills("baoling"); player.gainMaxHp(3, true); - "step 2"; + ("step 2"); player.recover(3); player.addSkills("benghuai"); }, @@ -18329,7 +18283,7 @@ export default () => { else return 0; }) .set("small", trigger.small); - "step 1"; + ("step 1"); if (result.index != 2) { player.logSkill("yingyang"); if (result.index == 0) { @@ -18360,7 +18314,7 @@ export default () => { content() { "step 0"; player.judge(); - "step 1"; + ("step 1"); event.color = result.color; player .chooseTarget(function (card, player, target) { @@ -18369,7 +18323,7 @@ export default () => { .set("ai", function (target) { return -get.attitude(_status.event.player, target); }); - "step 2"; + ("step 2"); if (result.bool && result.targets.length) { result.targets[0].storage.qianxi2 = event.color; result.targets[0].addSkill("qianxi2"); @@ -18408,7 +18362,7 @@ export default () => { })() ); } - "step 1"; + ("step 1"); var skills; if (result.control == "主将") { trigger.source.showCharacter(0); @@ -18703,7 +18657,7 @@ export default () => { next.set("logSkill", ["gzxiaoguo", trigger.player]); next.set("nono", nono); next.setHiddenSkill("gzxiaoguo"); - "step 1"; + ("step 1"); if (result.bool) { var nono = get.damageEffect(trigger.player, player, trigger.player) >= 0; trigger.player @@ -18719,7 +18673,7 @@ export default () => { } else { event.finish(); } - "step 2"; + ("step 2"); if (!result.bool) { trigger.player.damage(); } @@ -18745,7 +18699,7 @@ export default () => { player.chooseBool("是否将主武将牌替换为“" + get.translation(event.junzhu_name) + "”?"); } } else event.goto(3); - "step 1"; + ("step 1"); if (result.bool) { var to = event.junzhu_name; event.maxHp = player.maxHp; @@ -18784,9 +18738,9 @@ export default () => { } game.tryResult(); } else event.goto(3); - "step 2"; + ("step 2"); if (player.maxHp > event.maxHp) player.recover(player.maxHp - event.maxHp); - "step 3"; + ("step 3"); var choice = 1; for (var i = 0; i < player.hiddenSkills.length; i++) { if (lib.skill[player.hiddenSkills[i]].ai) { @@ -18833,7 +18787,7 @@ export default () => { event.finish(); } } - "step 4"; + ("step 4"); switch (result.control) { case "明置" + get.translation(player.name1): player.showCharacter(0); @@ -18900,7 +18854,7 @@ export default () => { next.set("hsskill", trigger.skill); next.set("ai", nai); } - "step 1"; + ("step 1"); if (result.bool) { if (event.name == player.name1) player.showCharacter(0); else player.showCharacter(1); @@ -18918,7 +18872,7 @@ export default () => { trigger.untrigger(); trigger.cancelled = true; } - "step 2"; + ("step 2"); if (event.name2) { if (result.bool) { player.showCharacter(1); @@ -18973,7 +18927,7 @@ export default () => { return current.isUnseen(); }) .sortBySeat(); - "step 1"; + ("step 1"); var target = event.list.shift(); event.target = target; if (target.wontYe(player.identity) && lib.skill._zhenfazhaohuan.getConfig(player, target)) { @@ -18990,7 +18944,7 @@ export default () => { }); } else event.goto(3); } else event.goto(3); - "step 2"; + ("step 2"); if (result.control != "cancel2") { if (result.control == "明置" + get.translation(target.name1)) { target.showCharacter(0); @@ -18998,9 +18952,9 @@ export default () => { target.showCharacter(1); } } - "step 3"; + ("step 3"); if (event.list.length) event.goto(1); - "step 4"; + ("step 4"); game.delay(); }, ai: { @@ -19117,8 +19071,6 @@ export default () => { ...translate, gz_miheng: "祢衡", - gzshensu: "神速", - gzshensu_info: "①判定阶段开始时,你可跳过此阶段和摸牌阶段,视为使用一张【杀】(无距离限制)。②出牌阶段开始时,你可跳过此阶段并弃置一张装备牌,视为使用一张【杀】(无距离限制)。③弃牌开始时,你可跳过此阶段并失去1点体力,视为使用一张【杀】(无距离限制)。", gzwushuang: "无双", gzwushuang_info: "锁定技。①当你使用【杀】指定一名角色为目标后,其需使用两张【闪】才能抵消;②当你使用【决斗】指定其他角色为目标后,或成为其他角色使用【决斗】的目标后,其每次响应需打出两张【杀】。③当你使用非转化的【决斗】选择目标后,你可为此【决斗】增加两个目标。", gzkuangfu: "狂斧", diff --git a/mode/guozhan/src/character/index.js b/mode/guozhan/src/character/index.js index 663680c8d1..eb6884396f 100644 --- a/mode/guozhan/src/character/index.js +++ b/mode/guozhan/src/character/index.js @@ -1,6 +1,6 @@ import { Character } from "../../../../noname/library/element/index.js"; -import normal from "./normal.js"; +import normal, { intro as normalIntro } from "./normal.js"; /** @type {Record} */ export const pack = { @@ -133,3 +133,7 @@ export const pack = { ...normal, }; + +export const intro = { + ...normalIntro +} diff --git a/mode/guozhan/src/character/intro.js b/mode/guozhan/src/character/intro.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index 7add101c98..fbb74cc801 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -50,4 +50,26 @@ export default { skills: ["tiandu", "gz_yiji"], hasSkinInGuozhan: true, }), + gz_zhenji: new Character({ + sex: "female", + group: "wei", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["luoshen", "qingguo"], + hasSkinInGuozhan: true, + }), + gz_xiahouyuan: new Character({ + sex: "male", + group: "wei", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_shensu"], + hasSkinInGuozhan: true, + }), }; + +export const intro = { + gz_xiahouyuan: "字妙才,沛国谯人。东汉末年曹操部下名将,夏侯惇之族弟,八虎骑之一。群雄征讨董卓时随曹操一同起兵,后征战四方,屡立功勋。在平定马超叛乱后负责西北防线的镇守。公元219年刘备攻打汉中,被刘备部将黄忠所杀。" +} diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index e58d10f0b6..b3422a22b0 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -413,4 +413,67 @@ export default { }, }, }, + + // gz_xiahouyuan + gz_shensu: { + audio: "shensu1", // TODO: 独立素材,留给后来人 + audioname: ["xiahouba", "re_xiahouyuan", "ol_xiahouyuan"], + group: ["gz_shensu_1", "gz_shensu_2"], + preHidden: ["gz_hensu_1", "gz_shensu_2", "gz_shensu"], + trigger: { + player: "phaseDiscardBegin", + }, + /** + * @param {GameEvent} _event + * @param {PlayerGuozhan} player + * @returns {boolean} + */ + filter(_event, player) { + return player.hp > 0; + }, + /** + * @param {GameEvent} event + * @param {GameEvent} _trigger + * @param {PlayerGuozhan} player + */ + async cost(event, _trigger, player) { + event.result = await player + .chooseTarget(get.prompt("gz_shensu"), "失去1点体力并跳过弃牌阶段,视为对一名其他角色使用一张无距离限制的【杀】", (card, player, target) => player.canUse("sha", target, false)) + .setHiddenSkill("gz_shensu") + .set("goon", player.needsToDiscard()) + .set("ai", target => { + /** @type {GameEvent & { goon: number }} */ + const event = cast(get.event()); + const player = get.player(); + if (!event.goon || player.hp <= target.hp) return false; + return get.effect(target, { name: "sha", isCard: true }, player, player); + }) + .forResult(); + }, + logTarget: "targets", + /** + * @param {GameEvent} event + * @param {GameEvent} trigger + * @param {PlayerGuozhan} player + */ + async content(event, trigger, player) { + const { targets } = event; + const target = targets[0]; + await player.loseHp(); + trigger.cancel(); + await player.useCard({ name: "sha", isCard: true }, target, false); + }, + subSkill: { + // TODO: 后面或许将不存在shensu1,所以后来人需要重新填写技能信息 + 1: { + audio: "shensu1", + inherit: "shensu1", + sourceSkill: "gz_shensu", + }, + 2: { + inherit: "shensu2", + sourceSkill: "gz_shensu", + }, + }, + }, }; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index 137780e1ed..bc6e8d96f7 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -5,4 +5,6 @@ export default { gz_zhangliao: "张辽", gz_xuzhu: "许褚", gz_guojia: "郭嘉", + gz_zhenji: "甄宓", + gz_xiahouyuan: "夏侯渊", }; diff --git a/mode/guozhan/src/translate/index.js b/mode/guozhan/src/translate/index.js index c201e47d12..1bf083b948 100644 --- a/mode/guozhan/src/translate/index.js +++ b/mode/guozhan/src/translate/index.js @@ -1,6 +1,7 @@ import card from "./card/index.js"; import character from "./character/index.js"; import skill from "./skill/index.js"; +import voices from "./voices/index.js"; export default { yexinjia_mark: "野心家", @@ -16,4 +17,5 @@ export default { ...card, ...character, ...skill, + ...voices, }; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index eb3f5f47ca..aa74c1eec3 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -13,4 +13,7 @@ export default { gz_yiji: "遗计", gz_yiji_info: "当你受到伤害后,你可以观看牌堆顶的两张牌,并将其交给任意角色。", + + gz_shensu: "神速", + gz_shensu_info: "①判定阶段开始时,你可跳过此阶段和摸牌阶段,视为使用一张【杀】(无距离限制)。②出牌阶段开始时,你可跳过此阶段并弃置一张装备牌,视为使用一张【杀】(无距离限制)。③弃牌开始时,你可跳过此阶段并失去1点体力,视为使用一张【杀】(无距离限制)。", }; diff --git a/mode/guozhan/src/translate/voices/index.js b/mode/guozhan/src/translate/voices/index.js new file mode 100644 index 0000000000..ff8b4c5632 --- /dev/null +++ b/mode/guozhan/src/translate/voices/index.js @@ -0,0 +1 @@ +export default {}; From 864900905695ab28b5e6d8b4f227000590ef56d8 Mon Sep 17 00:00:00 2001 From: Rintim Date: Thu, 10 Apr 2025 23:45:58 +0800 Subject: [PATCH 37/48] feat: rewrite some characters in new format of mode character. --- mode/guozhan.js | 173 +------ mode/guozhan/src/character/index.js | 6 +- mode/guozhan/src/character/intro.js | 5 + mode/guozhan/src/character/normal.js | 52 +- mode/guozhan/src/patch/content.js | 29 +- mode/guozhan/src/skill/character/normal.js | 443 ++++++++++++++++++ .../guozhan/src/translate/character/normal.js | 5 + .../src/translate/skill/character/normal.js | 17 + mode/guozhan/src/translate/voices/normal.js | 8 + 9 files changed, 550 insertions(+), 188 deletions(-) create mode 100644 mode/guozhan/src/translate/voices/normal.js diff --git a/mode/guozhan.js b/mode/guozhan.js index 0d5355331c..57ce20f0bc 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -90,13 +90,6 @@ export default () => { gz_mazhong: ["male", "shu", 4, ["twfuman"]], gz_ol_lisu: ["male", "qun", 3, ["qiaoyan", "xianzhu"]], - gz_zhanghe: ["male", "wei", 4, ["qiaobian"]], - gz_xuhuang: ["male", "wei", 4, ["new_duanliang"]], - gz_caoren: ["male", "wei", 4, ["gzjushou"]], - gz_dianwei: ["male", "wei", 5, ["reqiangxi"], ["gzskin"]], - gz_xunyu: ["male", "wei", 3, ["quhu", "gzjieming"]], - gz_caopi: ["male", "wei", 3, ["xingshang", "gzfangzhu"], ["gzskin"]], - gz_yuejin: ["male", "wei", 4, ["fakexiaoguo"], ["gzskin"]], gz_liubei: ["male", "shu", 4, ["rerende"]], gz_guanyu: ["male", "shu", 5, ["new_rewusheng"], ["gzskin"]], @@ -14618,104 +14611,6 @@ export default () => { }, }, - gzjushou: { - audio: "xinjushou", - trigger: { - player: "phaseJieshuBegin", - }, - preHidden: true, - content() { - "step 0"; - var list = [], - players = game.filterPlayer(); - for (var target of players) { - if (target.isUnseen()) continue; - var add = true; - for (var i of list) { - if (i.isFriendOf(target)) { - add = false; - break; - } - } - if (add) list.add(target); - } - event.num = list.length; - player.draw(event.num); - if (event.num > 2) player.turnOver(); - ("step 1"); - player - .chooseCard("h", true, "弃置一张手牌,若以此法弃置的是装备牌,则你改为使用之") - .set("ai", function (card) { - if (get.type(card) == "equip") { - return 5 - get.value(card); - } - return -get.value(card); - }) - .set("filterCard", lib.filter.cardDiscardable); - ("step 2"); - if (result.bool && result.cards.length) { - if (get.type(result.cards[0]) == "equip" && player.hasUseTarget(result.cards[0])) { - player.chooseUseTarget(result.cards[0], true, "nopopup"); - } else { - player.discard(result.cards[0]); - } - } - }, - }, - new_duanliang: { - subSkill: { - off: { - sub: true, - }, - }, - mod: { - targetInRange(card, player, target) { - if (card.name == "bingliang") { - return true; - } - }, - }, - locked: false, - audio: "duanliang1", - audioname2: { gz_jun_caocao: "jianan_duanliang" }, - enable: "chooseToUse", - filterCard(card) { - if (get.type(card) != "basic" && get.type(card) != "equip") return false; - return get.color(card) == "black"; - }, - filter(event, player) { - if (player.hasSkill("new_duanliang_off")) return false; - return player.countCards("hes", { type: ["basic", "equip"], color: "black" }); - }, - position: "hes", - viewAs: { - name: "bingliang", - }, - onuse(result, player) { - if (get.distance(player, result.targets[0]) > 2) player.addTempSkill("new_duanliang_off"); - }, - prompt: "将一黑色的基本牌或装备牌当兵粮寸断使用", - check(card) { - return 6 - get.value(card); - }, - ai: { - order: 9, - basic: { - order: 1, - useful: 1, - value: 4, - }, - result: { - target(player, target) { - if (target.hasJudge("caomu")) return 0; - return -1.5 / Math.sqrt(target.countCards("h") + 1); - }, - }, - tag: { - skip: "phaseDraw", - }, - }, - }, new_shushen: { audio: "shushen", trigger: { @@ -15410,66 +15305,6 @@ export default () => { threaten: 1.3, }, }, - gzjieming: { - audio: "jieming", - trigger: { - player: "damageEnd", - }, - direct: true, - preHidden: true, - content() { - "step 0"; - player - .chooseTarget(get.prompt("gzjieming"), "令一名角色将手牌补至X张(X为其体力上限且至多为5)", function (card, player, target) { - return true; //target.countCards('h') 2) { - return Math.max(0, Math.min(5, target.maxHp) - target.countCards("h")); - } - return att / 3; - }) - .setHiddenSkill("gzjieming"); - ("step 1"); - if (result.bool) { - player.logSkill("gzjieming", result.targets); - for (var i = 0; i < result.targets.length; i++) { - var num = Math.min(5, result.targets[i].maxHp) - result.targets[i].countCards("h"); - if (num > 0) result.targets[i].draw(num); - } - } - }, - ai: { - maixie: true, - maixie_hp: true, - effect: { - target(card, player, target, current) { - if (get.tag(card, "damage") && target.hp > 1) { - if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; - var max = 0; - var players = game.filterPlayer(); - for (var i = 0; i < players.length; i++) { - if (get.attitude(target, players[i]) > 0) { - max = Math.max(Math.min(5, players[i].hp) - players[i].countCards("h"), max); - } - } - switch (max) { - case 0: - return 2; - case 1: - return 1.5; - case 2: - return [1, 2]; - default: - return [0, max]; - } - } - if ((card.name == "tao" || card.name == "caoyao") && target.hp > 1 && target.countCards("h") <= target.hp) return [0, 0]; - }, - }, - }, - }, gzfangzhu: { audio: "fangzhu", trigger: { @@ -19304,10 +19139,8 @@ export default () => { _yinyang_mark_add: "阴阳鱼", yinyang_add: "阴阳鱼", - gzjushou: "据守", - gzjushou_info: "结束阶段,你可以摸X张牌(X为亮明势力数),然后弃置一张手牌。若以此法弃置的牌为装备牌,则改为使用此牌。若X大于2,则你将武将牌叠置。", - new_duanliang: "断粮", - new_duanliang_info: "出牌阶段,你可以将一张黑色基本牌或黑色装备牌当做【兵粮寸断】使用。你使用【兵粮寸断】没有距离限制。若你对距离超过2的角色发动了〖断粮〗,则本回合不能再发动〖断粮〗。", + + new_shushen: "淑慎", new_shushen_info: "当你回复1点体力后,你可令一名其他角色摸一张牌。", new_luanji: "乱击", @@ -19342,8 +19175,6 @@ export default () => { baka_yinghun_info: "准备阶段,你可令一名其他角色执行一项:摸X张牌,然后弃置一张牌;或摸一张牌,然后弃置X张牌(X为你已损失的体力值)。", baka_yingzi: "英姿", baka_yingzi_info: "锁定技,摸牌阶段摸,你多摸一张牌;你的手牌上限+X(X为你已损失的体力值)。", - gzjieming: "节命", - gzjieming_info: "当你受到伤害后,你可以令一名角色将手牌摸至X张(X为其体力上限且最多为5)。", gzfangzhu: "放逐", gzfangzhu_info: "当你受到伤害后,你可以令一名其他角色选择一项:⒈摸X张牌并将武将牌叠置;⒉弃置X张牌并失去1点体力(X为你已损失的体力值)。", fengyin_main: "封印[主将]", diff --git a/mode/guozhan/src/character/index.js b/mode/guozhan/src/character/index.js index eb6884396f..134aaf22e6 100644 --- a/mode/guozhan/src/character/index.js +++ b/mode/guozhan/src/character/index.js @@ -1,6 +1,6 @@ import { Character } from "../../../../noname/library/element/index.js"; -import normal, { intro as normalIntro } from "./normal.js"; +import normal from "./normal.js"; /** @type {Record} */ export const pack = { @@ -134,6 +134,4 @@ export const pack = { ...normal, }; -export const intro = { - ...normalIntro -} +export { default as intro } from "./intro.js"; diff --git a/mode/guozhan/src/character/intro.js b/mode/guozhan/src/character/intro.js index e69de29bb2..407dd149da 100644 --- a/mode/guozhan/src/character/intro.js +++ b/mode/guozhan/src/character/intro.js @@ -0,0 +1,5 @@ +import { intro as normalIntro } from "./normal.js"; + +export default { + ...normalIntro, +}; diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index fbb74cc801..aefe302344 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -68,8 +68,56 @@ export default { skills: ["gz_shensu"], hasSkinInGuozhan: true, }), + gz_zhanghe: new Character({ + sex: "male", + group: "wei", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_qiaobian"], + }), + gz_xuhuang: new Character({ + sex: "male", + group: "wei", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_duanliang"], + }), + gz_caoren: new Character({ + sex: "male", + group: "wei", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_jushou"], + }), + gz_dianwei: new Character({ + sex: "male", + group: "wei", + hp: 5, + maxHp: 5, + hujia: 0, + skills: ["gz_qiangxi"], + hasSkinInGuozhan: true, + }), + gz_xunyu: new Character({ + sex: "male", + group: "wei", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["gz_quhu", "gz_jieming"], + }), + gz_caopi: ["male", "wei", 3, ["xingshang", "gzfangzhu"], ["gzskin"]], + gz_yuejin: ["male", "wei", 4, ["fakexiaoguo"], ["gzskin"]], }; export const intro = { - gz_xiahouyuan: "字妙才,沛国谯人。东汉末年曹操部下名将,夏侯惇之族弟,八虎骑之一。群雄征讨董卓时随曹操一同起兵,后征战四方,屡立功勋。在平定马超叛乱后负责西北防线的镇守。公元219年刘备攻打汉中,被刘备部将黄忠所杀。" -} + gz_xiahouyuan: "字妙才,沛国谯人。东汉末年曹操部下名将,夏侯惇之族弟,八虎骑之一。群雄征讨董卓时随曹操一同起兵,后征战四方,屡立功勋。在平定马超叛乱后负责西北防线的镇守。公元219年刘备攻打汉中,被刘备部将黄忠所杀。", + gz_zhanghe: "字儁乂,河间鄚人。三国时期魏国名将。官渡之战时,本为袁绍部将的张郃投降了曹操,并在曹操帐下多立功勋,于曹魏建立后加封为征西车骑将军。诸葛亮六出祁山之间,张郃多次抵御蜀军的进攻,于公元231年在木门道被诸葛亮设伏射死。后谥曰壮侯。为曹魏“五子良将”之一。", + gz_xuhuang: "字公明,河东杨人。三国时期曹魏名将,本为杨奉帐下骑都尉,杨奉被曹操击败后转投曹操,在曹操手下多立功勋,参与官渡、赤壁、关中征伐、汉中征伐等几次重大战役。", + gz_caoren: "字子孝,沛国谯人,曹操的从弟。三国时期曹魏名将,官至大司马。谥曰忠侯。", + gz_dianwei: "己吾城村人。东汉末年曹魏猛将。擅使大双戟,为人壮猛任侠,曾为乡人刘氏报仇,杀人出市,人莫敢近。相貌魁梧,膂力过人。建安二年(197),张绣背叛曹操,典韦为保护曹操而独挡叛军,击杀多人,但最终因寡不敌众而战死。", + gz_xunyu: "荀彧,字文若,颍川颍阴(今河南许昌)人。东汉末年曹操帐下首席谋臣,杰出的战略家。自小被世人称作“王佐之才”。", +}; diff --git a/mode/guozhan/src/patch/content.js b/mode/guozhan/src/patch/content.js index d5b0387023..838e55ca83 100644 --- a/mode/guozhan/src/patch/content.js +++ b/mode/guozhan/src/patch/content.js @@ -1098,7 +1098,7 @@ export async function hideCharacter(event, _trigger, player) { player.skills.remove(skills[i]); } - + player.checkConflict(); } @@ -1225,7 +1225,7 @@ export async function carryOutJunling(event, _trigger, player) { for (let i = 0; i < 2 && player.countCards("he") > 0; i++) { const { result } = await player.chooseCard("交给" + get.translation(source) + "第" + get.cnNumber(i + 1) + "张牌(共两张)", "he", true); - if (result.cards.length) { + if (result.cards?.length) { await player.give(result.cards, source); } } @@ -1270,6 +1270,10 @@ export async function carryOutJunling(event, _trigger, player) { return get.value(card); }); + if (!result.bool || !result.cards?.length) { + return; + } + const cards = player.getCards("he"); for (const card of result.cards) { cards.remove(card); @@ -1434,11 +1438,14 @@ export const changeVice = [ * @param {Player} player */ export async function mayChangeVice(event, _trigger, player) { - const result = await player.chooseBool("是否变更副将?").set("ai", function () { - const player = get.player(); - // @ts-expect-error 祖宗之法就是这么写的 - return get.guozhanRank(player.name2, player) <= 3; - }).forResult(); + const result = await player + .chooseBool("是否变更副将?") + .set("ai", function () { + const player = get.player(); + // @ts-expect-error 祖宗之法就是这么写的 + return get.guozhanRank(player.name2, player) <= 3; + }) + .forResult(); if (result.bool) { // @ts-expect-error 祖宗之法就是这么做的 if (!event.repeat) { @@ -1453,10 +1460,10 @@ export async function mayChangeVice(event, _trigger, player) { } /** - * - * @param {GameEvent} _event - * @param {GameEvent} _trigger - * @param {Player} player + * + * @param {GameEvent} _event + * @param {GameEvent} _trigger + * @param {Player} player */ export async function zhulian(_event, _trigger, player) { player.popup("珠联璧合"); diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index b3422a22b0..b002ec545c 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -476,4 +476,447 @@ export default { }, }, }, + + // gz_zhanghe + gz_qiaobian: { + audio: "qiaobian", // TODO: 你说得对,未来得拆,未来可期 + audioname2: { gz_jun_caocao: "jianan_qiaobian" }, + trigger: { + player: ["phaseJudgeBefore", "phaseDrawBefore", "phaseUseBefore", "phaseDiscardBefore"], + }, + /** + * @param {GameEvent} _event + * @param {PlayerGuozhan} player + * @returns {boolean} + */ + filter(_event, player) { + return player.countCards("h") > 0; + }, + preHidden: true, + /** + * @param {GameEvent} event + * @param {GameEvent} trigger + * @param {PlayerGuozhan} player + */ + async cost(event, trigger, player) { + let check; + let str = "弃置一张手牌并跳过"; + str += ["判定", "摸牌", "出牌", "弃牌"][lib.skill.qiaobian?.trigger?.player?.indexOf(event.triggername) ?? 0]; + str += "阶段"; + if (trigger.name == "phaseDraw") str += ",然后可以获得至多两名角色各一张手牌"; + if (trigger.name == "phaseUse") str += ",然后可以移动场上的一张牌"; + switch (trigger.name) { + case "phaseJudge": + check = player.countCards("j"); + break; + case "phaseDraw": { + let i; + let num = 0; + let num2 = 0; + const players = game.filterPlayer(lib.filter.all); + for (i = 0; i < players.length; i++) { + // @ts-ignore + if (player != players[i] && players[i].countCards("h")) { + const att = get.attitude(player, players[i]); + if (att <= 0) { + num++; + } + if (att < 0) { + num2++; + } + } + } + check = num >= 2 && num2 > 0; + break; + } + case "phaseUse": + if (!player.canMoveCard(true)) { + check = false; + } else { + check = game.hasPlayer(current => { + return get.attitude(player, current) > 0 && current.countCards("j") > 0; + }); + if (!check) { + if (player.countCards("h") > player.hp + 1) { + check = false; + } else if (player.countCards("h", { name: "wuzhong" })) { + check = false; + } else { + check = true; + } + } + } + break; + case "phaseDiscard": + check = player.needsToDiscard(); + break; + } + event.result = await player + .chooseToDiscard(get.prompt("qiaobian"), str, lib.filter.cardDiscardable) + .set("ai", card => { + /** @type {GameEvent & {check: any}} */ + const event = cast(get.event()); + if (!event.check) return -1; + return 7 - get.value(card); + }) + .set("check", check) + .setHiddenSkill("qiaobian") + .forResult(); + }, + /** + * @param {GameEvent} event + * @param {GameEvent} trigger + * @param {PlayerGuozhan} player + */ + async content(event, trigger, player) { + trigger.cancel(); + game.log(player, "跳过了", "#y" + ["判定", "摸牌", "出牌", "弃牌"][lib.skill.qiaobian?.trigger?.player?.indexOf(event.triggername) ?? 0] + "阶段"); + if (trigger.name == "phaseUse") { + if (player.canMoveCard()) await player.moveCard(); + } else if (trigger.name == "phaseDraw") { + const { result } = await player + .chooseTarget([1, 2], "获得至多两名角色各一张手牌", function (card, player, target) { + return target != player && target.countCards("h"); + }) + .set("ai", target => { + return 1 - get.attitude(get.player(), target); + }); + if (!result.bool) return; + result.targets?.sortBySeat(); + player.line(result.targets, "green"); + if (!result.targets?.length) return; + // @ts-ignore + await player.gainMultiple(result.targets); + await game.delay(); + } + }, + ai: { + threaten: 3, + }, + }, + + // gz_xuhuang + gz_duanliang: { + locked: false, + audio: "duanliang1", // 未来可期未来改 + audioname2: { + gz_jun_caocao: "jianan_duanliang", + }, + enable: "chooseToUse", + /** + * @param {Card} card + * @returns {boolean} + */ + filterCard(card) { + if (get.type(card) != "basic" && get.type(card) != "equip") return false; + return get.color(card) == "black"; + }, + /** + * @param {GameEvent} _event + * @param {PlayerGuozhan} player + * @returns {boolean} + */ + filter(_event, player) { + if (player.hasSkill("gz_duanliang_off")) return false; + return player.countCards("hes", { type: ["basic", "equip"], color: "black" }) > 0; + }, + position: "hes", + viewAs: { + name: "bingliang", + }, + onuse(result, player) { + if (get.distance(player, result.targets[0]) > 2) player.addTempSkill("gz_duanliang_off"); + }, + prompt: "将一黑色的基本牌或装备牌当兵粮寸断使用", + check(card) { + return 6 - get.value(card); + }, + mod: { + targetInRange(card, player, target) { + if (card.name == "bingliang") { + return true; + } + }, + }, + ai: { + order: 9, + basic: { + order: 1, + useful: 1, + value: 4, + }, + result: { + target(player, target) { + if (target.hasJudge("caomu")) return 0; + return -1.5 / Math.sqrt(target.countCards("h") + 1); + }, + }, + tag: { + skip: "phaseDraw", + }, + }, + subSkill: { + off: { + sub: true, + }, + }, + }, + + // gz_caoren + gz_jushou: { + audio: "xinjushou", // 你懂我要说什么.png + trigger: { + player: "phaseJieshuBegin", + }, + preHidden: true, + /** + * @param {GameEvent} event + * @param {GameEvent} trigger + * @param {PlayerGuozhan} player + */ + async content(event, trigger, player) { + "step 0"; + const groups = []; + const players = game.filterPlayer(lib.filter.all); + + for (var target of players) { + if (target.isUnseen(-1)) continue; + let add = true; + for (const group of groups) { + if (group.isFriendOf(target)) { + add = false; + break; + } + } + if (add) groups.add(target); + } + const num = groups.length; + await player.draw(num); + if (num > 2) { + await player.turnOver(); + } + + const result = await player + .chooseCard("h", true, "弃置一张手牌,若以此法弃置的是装备牌,则你改为使用之") + .set("ai", (/** @type {Card} */ card) => { + if (get.type(card) == "equip") { + return 5 - get.value(card); + } + return -get.value(card); + }) + .set("filterCard", lib.filter.cardDiscardable) + .forResult(); + + if (result.bool && result.cards?.length) { + if (get.type(result.cards[0]) == "equip" && player.hasUseTarget(result.cards[0])) { + player.chooseUseTarget(result.cards[0], true, "nopopup"); + } else { + player.discard(result.cards[0]); + } + } + }, + }, + + // gz_dianwei + /** @type {Skill} */ + gz_qiangxi: { + audio: "qiangxi", // 已经,没有什么好怕的了( + enable: "phaseUse", + filterCard(card) { + return get.subtype(card) == "equip1"; + }, + selectCard() { + return [0, 1]; + }, + filterTarget(_card, player, target) { + if (player == target) return false; + if (target.hasSkill("reqiangxi_off")) return false; + return player.inRange(target); + }, + async content(event, _trigger, player) { + const { cards, target } = event; + + if (cards.length == 0) { + await player.loseHp(); + } + + target.addTempSkill("gz_qiangxi_off", "phaseUseAfter"); + await target.damage("nocard"); + }, + /** + * @param {Card} card + * @returns {number} + */ + check(card) { + return 10 - get.value(card); + }, + position: "he", + ai: { + order: 8.5, + threaten: 1.5, + result: { + target(player, target) { + if (!ui.selected.cards.length) { + if (player.hp < 2) return 0; + if (target.hp >= player.hp) return 0; + } + return get.damageEffect(target, player); + }, + }, + }, + subSkill: { + off: { + sub: true, + }, + }, + }, + + // gz_xunyu + /** @type {Skill} */ + gz_quhu: { + audio: "quhu", + audioname: ["re_xunyu", "ol_xunyu"], + enable: "phaseUse", + usable: 1, + filter(_event, player) { + if (player.countCards("h") == 0) return false; + return game.hasPlayer(current => current.hp > player.hp && player.canCompare(current)); + }, + filterTarget(_card, player, target) { + return target.hp > player.hp && player.canCompare(target); + }, + async content(event, _trigger, player) { + const target = event.target; + const bool = await player.chooseToCompare(target, void 0).forResultBool(); + if (!bool) return void (await player.damage(target)); + if (!game.hasPlayer(player => player != target && target.inRange(player))) return; + const { result } = await player + .chooseTarget((card, player, target) => { + const source = _status.event?.source; + return target != source && source?.inRange(target); + }, true) + .set("ai", target => get.damageEffect(target, _status.event?.source, player)) + .set("source", target); + if (!result.bool || !result.targets || !result.targets.length) return; + target.line(result.targets[0], "green"); + await result.targets[0].damage(target); + }, + ai: { + order: 0.5, + result: { + target(player, target) { + const att = get.attitude(player, target); + const oc = target.countCards("h") == 1; + if (att > 0 && oc) return 0; + const players = game.filterPlayer(lib.filter.all); + for (let i = 0; i < players.length; i++) { + if (players[i] != target && players[i] != player && target.inRange(players[i])) { + if (get.damageEffect(players[i], target, player) > 0) { + return att > 0 ? att / 2 : att - (oc ? 5 : 0); + } + } + } + return 0; + }, + player(player, target) { + if (target.hasSkillTag("jueqing", false, target)) return -10; + const hs = player.getCards("h"); + let mn = 1; + for (let i = 0; i < hs.length; i++) { + const num = get.number(hs[i]); + if (typeof num == "number") { + mn = Math.max(mn, num); + } + } + if (mn <= 11 && player.hp < 2) return -20; + let max = player.maxHp - hs.length; + const players = game.filterPlayer(lib.filter.all); + for (let i = 0; i < players.length; i++) { + if (get.attitude(player, players[i]) > 2) { + max = Math.max(Math.min(5, players[i].hp) - players[i].countCards("h"), max); + } + } + switch (max) { + case 0: + return mn == 13 ? 0 : -20; + case 1: + return mn >= 12 ? 0 : -15; + case 2: + return 0; + case 3: + return 1; + default: + return max; + } + }, + }, + expose: 0.2, + }, + }, + /** @type {Skill} */ + gz_jieming: { + audio: "jieming", + trigger: { + player: "damageEnd", + }, + preHidden: true, + async cost(event, _trigger, player) { + const next = player.chooseTarget(get.prompt("gz_jieming"), "令一名角色将手牌补至X张(X为其体力上限且至多为5)"); + + next.set("ai", check); + next.setHiddenSkill("gz_jieming"); + + event.result = await next.forResult(); + + /** + * @param {PlayerGuozhan} target + */ + function check(target) { + const player = get.player(); + var att = get.attitude(player, target); + if (att > 2) { + return Math.max(0, Math.min(5, target.maxHp) - target.countCards("h")); + } + return att / 3; + } + }, + logTarget: "targets", + async content(event, _trigger, _player) { + for (const target of event.targets) { + const num = Math.min(5, target.maxHp) - target.countCards("h"); + if (num > 0) { + await target.draw(num); + } + } + }, + ai: { + maixie: true, + maixie_hp: true, + effect: { + target(card, player, target, current) { + if (get.tag(card, "damage") && target.hp > 1) { + if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; + var max = 0; + var players = game.filterPlayer(lib.filter.all); + for (var i = 0; i < players.length; i++) { + if (get.attitude(target, players[i]) > 0) { + max = Math.max(Math.min(5, players[i].hp) - players[i].countCards("h"), max); + } + } + switch (max) { + case 0: + return 2; + case 1: + return 1.5; + case 2: + return [1, 2]; + default: + return [0, max]; + } + } + if ((card.name == "tao" || card.name == "caoyao") && target.hp > 1 && target.countCards("h") <= target.hp) return [0, 0]; + }, + }, + }, + }, }; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index bc6e8d96f7..112401c50d 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -7,4 +7,9 @@ export default { gz_guojia: "郭嘉", gz_zhenji: "甄宓", gz_xiahouyuan: "夏侯渊", + gz_zhanghe: "张郃", + gz_xuhuang: "徐晃", + gz_caoren: "曹仁", + gz_dianwei: "典韦", + gz_xunyu: "荀彧", }; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index aa74c1eec3..0ade3bfd59 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -16,4 +16,21 @@ export default { gz_shensu: "神速", gz_shensu_info: "①判定阶段开始时,你可跳过此阶段和摸牌阶段,视为使用一张【杀】(无距离限制)。②出牌阶段开始时,你可跳过此阶段并弃置一张装备牌,视为使用一张【杀】(无距离限制)。③弃牌开始时,你可跳过此阶段并失去1点体力,视为使用一张【杀】(无距离限制)。", + + gz_qiaobian: "巧变", + gz_qiaobian_info: "你可以弃置一张手牌并跳过自己的一个阶段(准备阶段和结束阶段除外)。若你以此法跳过了摸牌阶段,则你可以获得至多两名其他角色的各一张手牌;若你以此法跳过了出牌阶段,则你可以移动场上的一张牌。", + + gz_duanliang: "断粮", + gz_duanliang_info: "出牌阶段,你可以将一张黑色基本牌或黑色装备牌当做【兵粮寸断】使用。你使用【兵粮寸断】没有距离限制。若你对距离超过2的角色发动了〖断粮〗,则本回合不能再发动〖断粮〗。", + + gz_jushou: "据守", + gz_jushou_info: "结束阶段,你可以摸X张牌(X为亮明势力数),然后弃置一张手牌。若以此法弃置的牌为装备牌,则改为使用此牌。若X大于2,则你将武将牌叠置。", + + gz_qiangxi: "强袭", + gz_qiangxi_info: "出牌阶段对每名其他角色限一次,你可以选择一项:1. 失去1点体力并对你攻击范围内的一名其他角色造成1点伤害;2. 弃置一张武器牌并对你攻击范围内的一名其他角色造成1点伤害。", + + gz_quhu: "驱虎", + gz_quhu_info: "出牌阶段限一次,你可以与一名体力值大于你的角色拼点,若你赢,则该角色对其攻击范围内另一名由你指定的角色造成1点伤害。若你没赢,该角色对你造成1点伤害。", + gz_jieming: "节命", + gz_jieming_info: "当你受到伤害后,你可以令一名角色将手牌摸至X张(X为其体力上限且最多为5)。", }; diff --git a/mode/guozhan/src/translate/voices/normal.js b/mode/guozhan/src/translate/voices/normal.js new file mode 100644 index 0000000000..ecdac7df05 --- /dev/null +++ b/mode/guozhan/src/translate/voices/normal.js @@ -0,0 +1,8 @@ +export default { + "#gz_xiahouyuan:die": "竟然……比我还……快……", + "#gz_zhanghe:die": "啊……膝盖……中箭了……", + "#gz_xuhuang:die": "一顿不吃,饿得慌……", + "#gz_caoren:die": "长江以南,再无王土矣……", + "#gz_dianwei:die": "主公,快走!", + "#gz_xunyu:die": "主公要臣死,臣不得不死……", +}; From 4ff69ef8ebb3b3a8191a40bda052e1e035331831 Mon Sep 17 00:00:00 2001 From: Rintim Date: Sun, 13 Apr 2025 23:13:15 +0800 Subject: [PATCH 38/48] feat: rewrite `gz_caopi` in new format of mode character. --- mode/guozhan.js | 83 ------------ mode/guozhan/src/character/normal.js | 11 +- mode/guozhan/src/skill/character/normal.js | 125 ++++++++++++++++++ .../src/translate/skill/character/normal.js | 5 + mode/guozhan/src/translate/voices/normal.js | 1 + 5 files changed, 141 insertions(+), 84 deletions(-) diff --git a/mode/guozhan.js b/mode/guozhan.js index 57ce20f0bc..4d7819851b 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -15305,87 +15305,6 @@ export default () => { threaten: 1.3, }, }, - gzfangzhu: { - audio: "fangzhu", - trigger: { - player: "damageEnd", - }, - direct: true, - preHidden: true, - content() { - "step 0"; - player - .chooseTarget(get.prompt2("gzfangzhu"), function (card, player, target) { - return player != target; - }) - .setHiddenSkill("gzfangzhu").ai = function (target) { - if (target.hasSkillTag("noturn")) return 0; - var player = _status.event.player, - att = get.attitude(player, target); - if (att == 0) return 0; - if (att > 0) { - if (target.isTurnedOver()) return 1000 - target.countCards("h"); - return -1; - } else { - if (target.isTurnedOver()) return -1; - if (player.getDamagedHp() >= 3) return -1; - return target.countCards("h") + 1; - } - }; - ("step 1"); - if (result.bool) { - var target = result.targets[0]; - event.target = target; - player.logSkill("gzfangzhu", target); - var num = player.getDamagedHp(); - if (num > 0) - target.chooseToDiscard("he", num, "放逐:弃置" + get.cnNumber(num) + "张牌并失去1点体力", "或者点击“取消”不弃牌,改为摸" + get.cnNumber(num) + "张牌并叠置").set("ai", function (card) { - var player = _status.event.player; - if (player.isTurnedOver()) return -1; - return player.hp * player.hp - Math.max(1, get.value(card)); - }); - else { - target.turnOver(); - event.finish(); - } - } else event.finish(); - ("step 2"); - if (result.bool) { - target.loseHp(); - } else { - target.draw(player.getDamagedHp()); - target.turnOver(); - } - }, - ai: { - maixie: true, - maixie_hp: true, - effect: { - target(card, player, target) { - if (get.tag(card, "damage")) { - if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; - if (target.hp <= 1) return; - if (!target.hasFriend()) return; - var hastarget = false; - var turnfriend = false; - var players = game.filterPlayer(); - for (var i = 0; i < players.length; i++) { - if (get.attitude(target, players[i]) < 0 && !players[i].isTurnedOver()) { - hastarget = true; - } - if (get.attitude(target, players[i]) > 0 && players[i].isTurnedOver()) { - hastarget = true; - turnfriend = true; - } - } - if (get.attitude(player, target) > 0 && !hastarget) return; - if (turnfriend || target.hp == target.maxHp) return [0.5, 1]; - if (target.hp > 1) return [1, 0.5]; - } - }, - }, - }, - }, fengyin_main: { init(player, skill) { player.addSkillBlocker(skill); @@ -19175,8 +19094,6 @@ export default () => { baka_yinghun_info: "准备阶段,你可令一名其他角色执行一项:摸X张牌,然后弃置一张牌;或摸一张牌,然后弃置X张牌(X为你已损失的体力值)。", baka_yingzi: "英姿", baka_yingzi_info: "锁定技,摸牌阶段摸,你多摸一张牌;你的手牌上限+X(X为你已损失的体力值)。", - gzfangzhu: "放逐", - gzfangzhu_info: "当你受到伤害后,你可以令一名其他角色选择一项:⒈摸X张牌并将武将牌叠置;⒉弃置X张牌并失去1点体力(X为你已损失的体力值)。", fengyin_main: "封印[主将]", fengyin_main_info: "", fengyin_vice: "封印[副将]", diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index aefe302344..3d40a489a8 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -109,7 +109,15 @@ export default { hujia: 0, skills: ["gz_quhu", "gz_jieming"], }), - gz_caopi: ["male", "wei", 3, ["xingshang", "gzfangzhu"], ["gzskin"]], + gz_caopi: new Character({ + sex: "male", + group: "wei", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["gz_xingshang", "gz_fangzhu"], + hasSkinInGuozhan: true, + }), gz_yuejin: ["male", "wei", 4, ["fakexiaoguo"], ["gzskin"]], }; @@ -120,4 +128,5 @@ export const intro = { gz_caoren: "字子孝,沛国谯人,曹操的从弟。三国时期曹魏名将,官至大司马。谥曰忠侯。", gz_dianwei: "己吾城村人。东汉末年曹魏猛将。擅使大双戟,为人壮猛任侠,曾为乡人刘氏报仇,杀人出市,人莫敢近。相貌魁梧,膂力过人。建安二年(197),张绣背叛曹操,典韦为保护曹操而独挡叛军,击杀多人,但最终因寡不敌众而战死。", gz_xunyu: "荀彧,字文若,颍川颍阴(今河南许昌)人。东汉末年曹操帐下首席谋臣,杰出的战略家。自小被世人称作“王佐之才”。", + gz_caopi: "字子桓,三国时期著名的政治家、文学家,曹魏的开国皇帝,公元220-226年在位。沛国谯人,魏武帝曹操与武宣卞皇后的长子。去世后庙号高祖,谥为文皇帝,葬于首阳陵。", }; diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index b002ec545c..e7df8143e5 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -919,4 +919,129 @@ export default { }, }, }, + + // gz_caopi + /** @type {Skill} */ + gz_xingshang: { + audio: "xingshang", + trigger: { + global: "die", + }, + preHidden: true, + filter(event) { + return event.player.countCards("he") > 0; + }, + async content(_event, trigger, player) { + const toGain = trigger.player.getCards("he"); + await player.gain(toGain, trigger.player, "giveAuto", "bySelf"); + }, + }, + /** @type {Skill} */ + gz_fangzhu: { + audio: "fangzhu", + trigger: { + player: "damageEnd", + }, + preHidden: true, + async cost(event, _trigger, player) { + const next = player.chooseTarget(get.prompt2("gz_fangzhu"), (_card, player, target) => player != target); + + next.setHiddenSkill("gz_fangzhu"); + next.set("ai", check); + + event.result = await next.forResult(); + + return; + + function check(target) { + if (target.hasSkillTag("noturn")) { + return 0; + } + + const player = get.player(); + const att = get.attitude(player, target); + + if (att == 0) return 0; + if (att > 0) { + if (target.isTurnedOver()) return 1000 - target.countCards("h"); + return -1; + } else { + if (target.isTurnedOver()) return -1; + if (player.getDamagedHp() >= 3) return -1; + return target.countCards("h") + 1; + } + } + }, + logTarget: "targets", + async content(event, _trigger, player) { + const { targets } = event; + const target = targets[0]; + const num = player.getDamagedHp(); + + /** + * @type {Partial} + */ + let result; + + if (num > 0) { + const str = [`放逐:弃置${get.cnNumber(num)}张牌并失去1点体力`, `或者点击“取消”不弃牌,改为摸${get.cnNumber(num)}张牌并叠置`]; + const next = target.chooseToDiscard(num, "he", ...str); + next.set("ai", check); + + result = await next.forResult(); + } else { + result = { + bool: false, + cards: [], + }; + } + + if (result.bool) { + await target.loseHp(); + } else { + if (num > 0) { + await target.draw(num); + } + await target.turnOver(false); + } + + return; + + function check(card) { + const player = get.player(); + if (player.isTurnedOver()) { + return -1; + } + return player.hp * player.hp - Math.max(1, get.value(card)); + } + }, + ai: { + maixie: true, + maixie_hp: true, + effect: { + target(card, player, target) { + if (get.tag(card, "damage")) { + if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; + if (target.hp <= 1) return; + if (!target.hasFriend()) return; + var hastarget = false; + var turnfriend = false; + var players = game.filterPlayer(lib.filter.all); + for (var i = 0; i < players.length; i++) { + if (get.attitude(target, players[i]) < 0 && !players[i].isTurnedOver()) { + hastarget = true; + } + if (get.attitude(target, players[i]) > 0 && players[i].isTurnedOver()) { + hastarget = true; + turnfriend = true; + } + } + if (get.attitude(player, target) > 0 && !hastarget) return; + if (turnfriend || target.hp == target.maxHp) return [0.5, 1]; + if (target.hp > 1) return [1, 0.5]; + } + }, + }, + }, + }, }; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index 0ade3bfd59..531851a988 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -33,4 +33,9 @@ export default { gz_quhu_info: "出牌阶段限一次,你可以与一名体力值大于你的角色拼点,若你赢,则该角色对其攻击范围内另一名由你指定的角色造成1点伤害。若你没赢,该角色对你造成1点伤害。", gz_jieming: "节命", gz_jieming_info: "当你受到伤害后,你可以令一名角色将手牌摸至X张(X为其体力上限且最多为5)。", + + gz_xingshang: "行殇", + gz_xingshang_info: "当有角色死亡后,你可以获得该角色的所有牌。", + gz_fangzhu: "放逐", + gz_fangzhu_info: "当你受到伤害后,你可以令一名其他角色选择一项:⒈摸X张牌并将武将牌叠置;⒉弃置X张牌并失去1点体力(X为你已损失的体力值)。", }; diff --git a/mode/guozhan/src/translate/voices/normal.js b/mode/guozhan/src/translate/voices/normal.js index ecdac7df05..22f8003af0 100644 --- a/mode/guozhan/src/translate/voices/normal.js +++ b/mode/guozhan/src/translate/voices/normal.js @@ -5,4 +5,5 @@ export default { "#gz_caoren:die": "长江以南,再无王土矣……", "#gz_dianwei:die": "主公,快走!", "#gz_xunyu:die": "主公要臣死,臣不得不死……", + "#gz_caopi:die": "子建,子建……", }; From 659672491f61ba08c77f25965ff0e853ca25e776 Mon Sep 17 00:00:00 2001 From: Rintim Date: Tue, 15 Apr 2025 08:50:55 +0800 Subject: [PATCH 39/48] feat: rewrite `gz_yuejin` in new format of mode character. --- mode/guozhan.js | 47 ---------------- mode/guozhan/src/character/normal.js | 11 +++- mode/guozhan/src/skill/character/normal.js | 54 +++++++++++++++++++ .../guozhan/src/translate/character/normal.js | 2 + .../src/translate/skill/character/normal.js | 3 ++ mode/guozhan/src/translate/voices/normal.js | 1 + 6 files changed, 70 insertions(+), 48 deletions(-) diff --git a/mode/guozhan.js b/mode/guozhan.js index 4d7819851b..24e7d3fcfd 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -1120,51 +1120,6 @@ export default () => { }, }, //官盗2023 - fakexiaoguo: { - audio: "xiaoguo", - audioname2: { gz_jun_caocao: "jianan_xiaoguo" }, - trigger: { global: "phaseZhunbeiBegin" }, - filter(event, player) { - return ( - event.player != player && - player.countCards("h", card => { - if (_status.connectMode) return true; - return get.type(card) == "basic" && lib.filter.cardDiscardable(card, player); - }) - ); - }, - async cost(event, trigger, player) { - event.result = await player - .chooseToDiscard( - get.prompt2("fakexiaoguo", trigger.player), - (card, player) => { - return get.type(card) == "basic"; - }, - [1, Infinity] - ) - .set("complexSelect", true) - .set("ai", card => { - const player = get.event("player"), - target = get.event().getTrigger().player; - const effect = get.damageEffect(target, player, player); - const cards = target.getCards("e", card => get.attitude(player, target) * get.value(card, target) < 0); - if (effect <= 0 && !cards.length) return 0; - if (ui.selected.cards.length > cards.length - (effect <= 0 ? 1 : 0)) return 0; - return 1 / (get.value(card) || 0.5); - }) - .set("logSkill", ["fakexiaoguo", trigger.player]) - .setHiddenSkill("fakexiaoguo") - .forResult(); - }, - popup: false, - preHidden: true, - async content(event, trigger, player) { - const num = trigger.player.countCards("e"), - num2 = event.cards.length; - await player.discardPlayerCard(trigger.player, "e", num2, true); - if (num2 > num) await trigger.player.damage(); - }, - }, fakeduanbing: { audio: "duanbing", inherit: "reduanbing", @@ -19396,8 +19351,6 @@ export default () => { ushio_xilv_info: "锁定技,此武将牌可作为任意单势力武将牌的副将。当你进行判定后,你令你的手牌上限+1直至你的下个结束阶段。", //官盗2023 - fakexiaoguo: "骁果", - fakexiaoguo_info: "一名其他角色的准备阶段,你可以弃置任意张基本牌,然后弃置其装备区等量的牌,若其装备区的牌数小于你弃置的牌数,则你对其造成1点伤害。", fakeduanbing: "短兵", fakeduanbing_info: "①你使用【杀】可以额外指定一名距离为1或以内的目标。②当你使用【杀】指定唯一目标后,你令目标角色需要额外使用一张【闪】响应此【杀】。", fakeduoshi: "度势", diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index 3d40a489a8..6512efe658 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -118,7 +118,15 @@ export default { skills: ["gz_xingshang", "gz_fangzhu"], hasSkinInGuozhan: true, }), - gz_yuejin: ["male", "wei", 4, ["fakexiaoguo"], ["gzskin"]], + gz_yuejin: new Character({ + sex: "male", + group: "wei", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_xiaoguo"], + hasSkinInGuozhan: true, + }), // ["male", "wei", 4, ["fakexiaoguo"], ["gzskin"]] }; export const intro = { @@ -129,4 +137,5 @@ export const intro = { gz_dianwei: "己吾城村人。东汉末年曹魏猛将。擅使大双戟,为人壮猛任侠,曾为乡人刘氏报仇,杀人出市,人莫敢近。相貌魁梧,膂力过人。建安二年(197),张绣背叛曹操,典韦为保护曹操而独挡叛军,击杀多人,但最终因寡不敌众而战死。", gz_xunyu: "荀彧,字文若,颍川颍阴(今河南许昌)人。东汉末年曹操帐下首席谋臣,杰出的战略家。自小被世人称作“王佐之才”。", gz_caopi: "字子桓,三国时期著名的政治家、文学家,曹魏的开国皇帝,公元220-226年在位。沛国谯人,魏武帝曹操与武宣卞皇后的长子。去世后庙号高祖,谥为文皇帝,葬于首阳陵。", + gz_yuejin: "字文谦,魏“五子良将”之一。容貌短小,以胆烈跟从曹操,南征北讨,战功无数。从击袁绍于官渡,奋勇力战,斩袁绍部将淳于琼。又从击袁绍子谭、尚于黎阳,斩其大将严敬。从平荆州,留屯襄阳,进击关羽、苏非等人,击退其众,南郡诸郡的山谷蛮夷都前往乐进处投降。后来从曹操征孙权,假进节。曹操回师后,留乐进与张辽、李典屯于合肥。又以乐进数有军功,迁右将军。建安二十三年逝世,谥曰威侯。", }; diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index e7df8143e5..dd22a67031 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -928,6 +928,7 @@ export default { global: "die", }, preHidden: true, + target: "player", filter(event) { return event.player.countCards("he") > 0; }, @@ -1044,4 +1045,57 @@ export default { }, }, }, + + // gz_yuejin + /** @type {Skill} */ + gz_xiaoguo: { + audio: "xiaoguo", + audioname2: { + gz_jun_caocao: "jianan_xiaoguo", + }, + trigger: { + global: "phaseZhunbeiBegin", + }, + filter(event, player) { + return ( + event.player != player && + player.countCards("h", card => { + if (_status.connectMode) return true; + // @ts-expect-error 类型系统未来可期 + return get.type(card) == "basic" && lib.filter.cardDiscardable(card, player); + }) > 0 + ); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseToDiscard( + get.prompt2("gz_xiaoguo", trigger.player), + (card, player) => { + return get.type(card) == "basic"; + }, + [1, Infinity] + ) + .set("complexSelect", true) + .set("ai", card => { + const player = get.event("player"), + target = get.event().getTrigger().player; + const effect = get.damageEffect(target, player, player); + const cards = target.getCards("e", card => get.attitude(player, target) * get.value(card, target) < 0); + if (effect <= 0 && !cards.length) return 0; + if (ui.selected.cards.length > cards.length - (effect <= 0 ? 1 : 0)) return 0; + return 1 / (get.value(card) || 0.5); + }) + .set("logSkill", ["gz_xiaoguo", trigger.player]) + .setHiddenSkill("gz_xiaoguo") + .forResult(); + }, + popup: false, + preHidden: true, + async content(event, trigger, player) { + const num = trigger.player.countCards("e"); + const num2 = event.cards.length; + await player.discardPlayerCard(trigger.player, "e", num2, true); + if (num2 > num) await trigger.player.damage(); + }, + }, }; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index 112401c50d..b7c184fb0d 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -12,4 +12,6 @@ export default { gz_caoren: "曹仁", gz_dianwei: "典韦", gz_xunyu: "荀彧", + gz_caopi: "曹丕", + gz_yuejin: "乐进", }; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index 531851a988..277771e4ef 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -38,4 +38,7 @@ export default { gz_xingshang_info: "当有角色死亡后,你可以获得该角色的所有牌。", gz_fangzhu: "放逐", gz_fangzhu_info: "当你受到伤害后,你可以令一名其他角色选择一项:⒈摸X张牌并将武将牌叠置;⒉弃置X张牌并失去1点体力(X为你已损失的体力值)。", + + gz_xiaoguo: "骁果", + gz_xiaoguo_info: "一名其他角色的准备阶段,你可以弃置任意张基本牌,然后弃置其装备区等量的牌,若其装备区的牌数小于你弃置的牌数,则你对其造成1点伤害。", }; diff --git a/mode/guozhan/src/translate/voices/normal.js b/mode/guozhan/src/translate/voices/normal.js index 22f8003af0..9c166b9333 100644 --- a/mode/guozhan/src/translate/voices/normal.js +++ b/mode/guozhan/src/translate/voices/normal.js @@ -6,4 +6,5 @@ export default { "#gz_dianwei:die": "主公,快走!", "#gz_xunyu:die": "主公要臣死,臣不得不死……", "#gz_caopi:die": "子建,子建……", + "#gz_yuejin:die": "箭疮发作,吾命休矣……", }; From d98395dc2b533f0a2ee50765de601f4201d4b113 Mon Sep 17 00:00:00 2001 From: Rintim Date: Tue, 15 Apr 2025 09:00:54 +0800 Subject: [PATCH 40/48] feat: rewrite `gz_liubei` in new format of mode character. --- mode/guozhan.js | 16 --- mode/guozhan/src/character/normal.js | 25 +++- mode/guozhan/src/skill/character/normal.js | 117 ++++++++++++++++++ .../guozhan/src/translate/character/normal.js | 2 + .../src/translate/skill/character/normal.js | 3 + 5 files changed, 146 insertions(+), 17 deletions(-) diff --git a/mode/guozhan.js b/mode/guozhan.js index 24e7d3fcfd..4c69abd822 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -90,22 +90,6 @@ export default () => { gz_mazhong: ["male", "shu", 4, ["twfuman"]], gz_ol_lisu: ["male", "qun", 3, ["qiaoyan", "xianzhu"]], - - gz_liubei: ["male", "shu", 4, ["rerende"]], - gz_guanyu: ["male", "shu", 5, ["new_rewusheng"], ["gzskin"]], - gz_zhangfei: ["male", "shu", 4, ["gzpaoxiao"]], - gz_zhugeliang: ["male", "shu", 3, ["guanxing", "new_kongcheng"], ["gzskin"]], - gz_zhaoyun: ["male", "shu", 4, ["new_longdan"]], - gz_machao: ["male", "shu", 4, ["mashu", "new_tieji"]], - gz_huangyueying: ["female", "shu", 3, ["jizhi", "qicai"], ["gzskin"]], - gz_huangzhong: ["male", "shu", 4, ["gzliegong"], ["gzskin"]], - gz_weiyan: ["male", "shu", 4, ["xinkuanggu"]], - gz_pangtong: ["male", "shu", 3, ["lianhuan", "oldniepan"]], - gz_sp_zhugeliang: ["male", "shu", 3, ["huoji", "bazhen", "kanpo"], ["gzskin"]], - gz_liushan: ["male", "shu", 3, ["xiangle", "fangquan"]], - gz_menghuo: ["male", "shu", 4, ["huoshou", "rezaiqi"]], - gz_zhurong: ["female", "shu", 4, ["juxiang", "lieren"]], - gz_ganfuren: ["female", "shu", 3, ["gzshushen_new", "shenzhi"], ["gzskin"]], gz_yuji: ["male", "qun", 3, ["qianhuan"], ["gzskin"]], gz_sunquan: ["male", "wu", 4, ["gzzhiheng"]], diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index 6512efe658..c1147e5d9b 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -126,7 +126,30 @@ export default { hujia: 0, skills: ["gz_xiaoguo"], hasSkinInGuozhan: true, - }), // ["male", "wei", 4, ["fakexiaoguo"], ["gzskin"]] + }), + + gz_liubei: new Character({ + sex: "male", + group: "shu", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_rende"], + }), + gz_guanyu: ["male", "shu", 5, ["new_rewusheng"], ["gzskin"]], + gz_zhangfei: ["male", "shu", 4, ["gzpaoxiao"]], + gz_zhugeliang: ["male", "shu", 3, ["guanxing", "new_kongcheng"], ["gzskin"]], + gz_zhaoyun: ["male", "shu", 4, ["new_longdan"]], + gz_machao: ["male", "shu", 4, ["mashu", "new_tieji"]], + gz_huangyueying: ["female", "shu", 3, ["jizhi", "qicai"], ["gzskin"]], + gz_huangzhong: ["male", "shu", 4, ["gzliegong"], ["gzskin"]], + gz_weiyan: ["male", "shu", 4, ["xinkuanggu"]], + gz_pangtong: ["male", "shu", 3, ["lianhuan", "oldniepan"]], + gz_sp_zhugeliang: ["male", "shu", 3, ["huoji", "bazhen", "kanpo"], ["gzskin"]], + gz_liushan: ["male", "shu", 3, ["xiangle", "fangquan"]], + gz_menghuo: ["male", "shu", 4, ["huoshou", "rezaiqi"]], + gz_zhurong: ["female", "shu", 4, ["juxiang", "lieren"]], + gz_ganfuren: ["female", "shu", 3, ["gzshushen_new", "shenzhi"], ["gzskin"]], }; export const intro = { diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index dd22a67031..5ba47f8159 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -1098,4 +1098,121 @@ export default { if (num2 > num) await trigger.player.damage(); }, }, + + // gz_liubei + /** @type {Skill} */ + gz_rende: { + audio: "rerende", + audioname: ["gz_jun_liubei"], + enable: "phaseUse", + filter(_event, player) { + // @ts-expect-error 类型系统未来可期 + return player.countCards("h") > 0 && game.hasPlayer(current => get.info("gz_rende").filterTarget?.(null, player, current)); + }, + filterTarget(_card, player, target) { + if (player == target) return false; + return !player.getStorage("rerende_targeted").includes(target); + }, + filterCard: true, + selectCard: [1, Infinity], + discard: false, + lose: false, + delay: false, + check(card) { + if (ui.selected.cards.length && ui.selected.cards[0].name == "du") return 0; + if (!ui.selected.cards.length && card.name == "du") return 20; + var player = get.owner(card); + if (player == null) { + return 0; + } + if (ui.selected.cards.length >= Math.max(2, player.countCards("h") - player.hp)) return 0; + if (player.hp == player.maxHp || player.storage.rerende < 0 || player.countCards("h") <= 1) { + var players = game.filterPlayer(lib.filter.all); + for (var i = 0; i < players.length; i++) { + if (players[i].hasSkill("haoshi") && !players[i].isTurnedOver() && !players[i].hasJudge("lebu") && get.attitude(player, players[i]) >= 3 && get.attitude(players[i], player) >= 3) { + return 11 - get.value(card); + } + } + if (player.countCards("h") > player.hp) return 10 - get.value(card); + if (player.countCards("h") > 2) return 6 - get.value(card); + return -1; + } + return 10 - get.value(card); + }, + async content(event, _trigger, player) { + const { target, cards, name } = event; + player.addTempSkill(name + "_targeted", "phaseUseAfter"); + player.markAuto(name + "_targeted", [target]); + let num = 0; + player.getHistory("lose", evt => { + // @ts-expect-error 类型系统未来可期 + if (evt.getParent(2)?.name == name) { + num += evt.cards.length; + } + return true; + }); + await player.give(cards, target); + const list = get.inpileVCardList(info => { + return get.type(info[2]) == "basic" && player.hasUseTarget(new lib.element.VCard({ name: info[2], nature: info[3] }), null, true); + }); + if (num < 2 && num + cards.length > 1 && list.length) { + const links = await player + .chooseButton(["是否视为使用一张基本牌?", [list, "vcard"]]) + .set("ai", button => { + return get.player().getUseValue({ name: button.link[2], nature: button.link[3], isCard: true }); + }) + .forResultLinks(); + if (!links?.length) return; + await player.chooseUseTarget(get.autoViewAs({ name: links[0][2], nature: links[0][3], isCard: true }), true); + } + }, + ai: { + fireAttack: true, + order(skill, player) { + if (player.hp < player.maxHp && player.storage.rerende < 2 && player.countCards("h") > 1) { + return 10; + } + return 4; + }, + result: { + target(player, target) { + if (target.hasSkillTag("nogain")) return 0; + if (ui.selected.cards.length && ui.selected.cards[0].name == "du") { + if (target.hasSkillTag("nodu")) return 0; + return -10; + } + if (target.hasJudge("lebu")) return 0; + var nh = target.countCards("h"); + var np = player.countCards("h"); + if (player.hp == player.maxHp || player.storage.rerende < 0 || player.countCards("h") <= 1) { + if (nh >= np - 1 && np <= player.hp && !target.hasSkill("haoshi")) return 0; + } + return Math.max(1, 5 - nh); + }, + }, + effect: { + // @ts-expect-error 类型系统未来可期 + target_use(card, player, target) { + if (player == target && get.type(card) == "equip") { + if (player.countCards("e", { subtype: get.subtype(card) })) { + if ( + game.hasPlayer(function (current) { + return current != player && get.attitude(player, current) > 0; + }) + ) { + return 0; + } + } + } + }, + }, + threaten: 0.8, + }, + subSkill: { + targeted: { + onremove: true, + charlotte: true, + }, + }, + }, }; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index b7c184fb0d..7b3d09e7e9 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -14,4 +14,6 @@ export default { gz_xunyu: "荀彧", gz_caopi: "曹丕", gz_yuejin: "乐进", + + gz_liubei: "刘备", }; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index 277771e4ef..889744639c 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -41,4 +41,7 @@ export default { gz_xiaoguo: "骁果", gz_xiaoguo_info: "一名其他角色的准备阶段,你可以弃置任意张基本牌,然后弃置其装备区等量的牌,若其装备区的牌数小于你弃置的牌数,则你对其造成1点伤害。", + + gz_rende: "仁德", + gz_rende_info: "出牌阶段,你可以将至少一张手牌交给其他角色,然后你于此阶段内不能再以此法交给该角色牌;若你于此阶段内给出的牌首次达到两张,你可以视为使用一张基本牌。", }; From d2df439f15cd854b9b4ac3d69bb9687e148b45d1 Mon Sep 17 00:00:00 2001 From: Rintim Date: Wed, 16 Apr 2025 15:27:52 +0800 Subject: [PATCH 41/48] pref: use vue single file component. --- mode/guozhan/src/help/App.vue | 39 ++++++++++++++++++++++++++++++++++ mode/guozhan/src/help/index.js | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 mode/guozhan/src/help/App.vue diff --git a/mode/guozhan/src/help/App.vue b/mode/guozhan/src/help/App.vue new file mode 100644 index 0000000000..0785520c25 --- /dev/null +++ b/mode/guozhan/src/help/App.vue @@ -0,0 +1,39 @@ + + + diff --git a/mode/guozhan/src/help/index.js b/mode/guozhan/src/help/index.js index 463c76d0f7..a07113c5f2 100644 --- a/mode/guozhan/src/help/index.js +++ b/mode/guozhan/src/help/index.js @@ -1,4 +1,4 @@ -import App from "./App.js"; +import App from "./App.vue"; export default { 国战模式: App, From 1e447038eb9933f10a7a1881d92eb0b925bfb50d Mon Sep 17 00:00:00 2001 From: Rintim Date: Wed, 16 Apr 2025 15:33:23 +0800 Subject: [PATCH 42/48] fix: correct the record string builder of game achievements. --- mode/guozhan/src/patch/game.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mode/guozhan/src/patch/game.js b/mode/guozhan/src/patch/game.js index dd27a05ac8..bede4a3f16 100644 --- a/mode/guozhan/src/patch/game.js +++ b/mode/guozhan/src/patch/game.js @@ -221,14 +221,14 @@ export class GameGuozhan extends Game { group = group.filter(group => group !== "shen" && group !== "western" && data[group]); // 将战绩记录转换为字符串 const strs = group.map(id => { - const name = get.translation(`${group[id]}2`); + const name = get.translation(`${id}2`); const [win, lose] = data[id]; return `${name}: ${win}胜 ${lose}负`; }); - const str = strs.join("
          "); + const str = strs.join("
          "); - lib.config.gameRecord.guozhan.str = str; + lib.config.gameRecord.guozhan.str = `${str}
          `; await game.promises.saveConfig("gameRecord", lib.config.gameRecord); } From ad5aa4a2dc2c2b8282e3b863ace5ad20af65d84c Mon Sep 17 00:00:00 2001 From: Rintim Date: Wed, 16 Apr 2025 16:22:25 +0800 Subject: [PATCH 43/48] feat: rewrite `gz_guanyu` in new format of mode character. --- mode/guozhan/src/character/normal.js | 20 ++++++- mode/guozhan/src/skill/character/normal.js | 54 +++++++++++++++++++ .../guozhan/src/translate/character/normal.js | 1 + .../src/translate/skill/character/normal.js | 3 ++ mode/guozhan/src/translate/voices/normal.js | 10 ++++ 5 files changed, 87 insertions(+), 1 deletion(-) diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index c1147e5d9b..686f60eca3 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -136,7 +136,15 @@ export default { hujia: 0, skills: ["gz_rende"], }), - gz_guanyu: ["male", "shu", 5, ["new_rewusheng"], ["gzskin"]], + gz_guanyu: new Character({ + sex: "male", + group: "shu", + hp: 5, + maxHp: 5, + hujia: 0, + skills: ["gz_wusheng"], + hasSkinInGuozhan: true, + }), gz_zhangfei: ["male", "shu", 4, ["gzpaoxiao"]], gz_zhugeliang: ["male", "shu", 3, ["guanxing", "new_kongcheng"], ["gzskin"]], gz_zhaoyun: ["male", "shu", 4, ["new_longdan"]], @@ -153,6 +161,13 @@ export default { }; export const intro = { + gz_caocao: "魏武帝曹操,字孟德,小名阿瞒、吉利,沛国谯人。精兵法,善诗歌,乃治世之能臣,乱世之奸雄也。", + gz_simayi: "晋宣帝,字仲达,河内温人。曾任职过曹魏的大都督,太尉,太傅。少有奇节,聪明多大略,博学洽闻,伏膺儒教,世之鬼才也。", + gz_xiahoudun: "字元让,沛国谯人。有拔矢啖睛之勇,性格勇猛刚烈。", + gz_zhangliao: "字文远,魏雁门马邑人。官至前将军、征东将军、晋阳侯。武功高强,又谋略过人,多次建立奇功,以800人突袭孙权十万大军,皆望风披靡。", + gz_xuzhu: "字仲康,谯国谯县人。和典韦一同统率着曹操的亲卫队“虎卫军”。因为他十分勇猛,所以有“虎痴”的绰号。曾有裸衣斗马超之举。", + gz_guojia: "字奉孝,颍川阳翟人,官至军师祭酒。惜天妒英才,英年早逝。有诗云:“良计环环不遗策,每临制变满座惊”。", + gz_zhenji: "中山无极人,别称甄洛或甄宓,庙号文昭甄皇后。魏文帝曹丕的正室。懂诗文,有倾国倾城之貌,《洛神赋》即是曹植为她所作。", gz_xiahouyuan: "字妙才,沛国谯人。东汉末年曹操部下名将,夏侯惇之族弟,八虎骑之一。群雄征讨董卓时随曹操一同起兵,后征战四方,屡立功勋。在平定马超叛乱后负责西北防线的镇守。公元219年刘备攻打汉中,被刘备部将黄忠所杀。", gz_zhanghe: "字儁乂,河间鄚人。三国时期魏国名将。官渡之战时,本为袁绍部将的张郃投降了曹操,并在曹操帐下多立功勋,于曹魏建立后加封为征西车骑将军。诸葛亮六出祁山之间,张郃多次抵御蜀军的进攻,于公元231年在木门道被诸葛亮设伏射死。后谥曰壮侯。为曹魏“五子良将”之一。", gz_xuhuang: "字公明,河东杨人。三国时期曹魏名将,本为杨奉帐下骑都尉,杨奉被曹操击败后转投曹操,在曹操手下多立功勋,参与官渡、赤壁、关中征伐、汉中征伐等几次重大战役。", @@ -161,4 +176,7 @@ export const intro = { gz_xunyu: "荀彧,字文若,颍川颍阴(今河南许昌)人。东汉末年曹操帐下首席谋臣,杰出的战略家。自小被世人称作“王佐之才”。", gz_caopi: "字子桓,三国时期著名的政治家、文学家,曹魏的开国皇帝,公元220-226年在位。沛国谯人,魏武帝曹操与武宣卞皇后的长子。去世后庙号高祖,谥为文皇帝,葬于首阳陵。", gz_yuejin: "字文谦,魏“五子良将”之一。容貌短小,以胆烈跟从曹操,南征北讨,战功无数。从击袁绍于官渡,奋勇力战,斩袁绍部将淳于琼。又从击袁绍子谭、尚于黎阳,斩其大将严敬。从平荆州,留屯襄阳,进击关羽、苏非等人,击退其众,南郡诸郡的山谷蛮夷都前往乐进处投降。后来从曹操征孙权,假进节。曹操回师后,留乐进与张辽、李典屯于合肥。又以乐进数有军功,迁右将军。建安二十三年逝世,谥曰威侯。", + + gz_liubei: "先主姓刘,讳备,字玄德,涿郡涿县人,汉景帝子中山靖王胜之后也。以仁德治天下。", + gz_guanyu: "字云长,本字长生,并州河东解州人。五虎上将之首,爵至汉寿亭侯,谥曰“壮缪侯”。被奉为“关圣帝君”,崇为“武圣”。", }; diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index 5ba47f8159..3fdc3579d3 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -1215,4 +1215,58 @@ export default { }, }, }, + + // gz_guanyu + /** @type {Skill} */ + gz_wusheng: { + audio: "wusheng", + audioname: ["re_guanyu", "jsp_guanyu", "re_guanzhang", "dc_jsp_guanyu"], + audioname2: { + dc_guansuo: "wusheng_guansuo", + guanzhang: "wusheng_guanzhang", + guansuo: "wusheng_guansuo", + gz_jun_liubei: "shouyue_wusheng", + std_guanxing: "wusheng_guanzhang", + ty_guanxing: "wusheng_guanzhang", + }, + enable: ["chooseToRespond", "chooseToUse"], + filterCard(card, player) { + if (get.zhu(player, "shouyue")) return true; + return get.color(card) == "red"; + }, + locked: false, + position: "hes", + viewAs: { + name: "sha", + }, + viewAsFilter(player) { + if (get.zhu(player, "shouyue")) { + if (!player.countCards("hes")) return false; + } else { + if (!player.countCards("hes", { color: "red" })) return false; + } + }, + prompt: "将一张红色牌当杀使用或打出", + check(card) { + const val = get.value(card); + const event = get.event(); + if (event.name == "chooseToRespond") return 1 / Math.max(0.1, val); + return 5 - val; + }, + mod: { + targetInRange(card) { + if (get.suit(card) == "diamond" && card.name == "sha") return true; + }, + }, + ai: { + respondSha: true, + skillTagFilter(player) { + if (get.zhu(player, "shouyue")) { + if (!player.countCards("hes")) return false; + } else { + if (!player.countCards("hes", { color: "red" })) return false; + } + }, + }, + }, }; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index 7b3d09e7e9..937d981bd2 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -16,4 +16,5 @@ export default { gz_yuejin: "乐进", gz_liubei: "刘备", + gz_guanyu: "关羽", }; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index 889744639c..f128e711b1 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -44,4 +44,7 @@ export default { gz_rende: "仁德", gz_rende_info: "出牌阶段,你可以将至少一张手牌交给其他角色,然后你于此阶段内不能再以此法交给该角色牌;若你于此阶段内给出的牌首次达到两张,你可以视为使用一张基本牌。", + + gz_wusheng: "武圣", + gz_wusheng_info: "你可以将一张红色牌当做【杀】使用或打出。你使用的方片【杀】没有距离限制。", }; diff --git a/mode/guozhan/src/translate/voices/normal.js b/mode/guozhan/src/translate/voices/normal.js index 9c166b9333..809920f37c 100644 --- a/mode/guozhan/src/translate/voices/normal.js +++ b/mode/guozhan/src/translate/voices/normal.js @@ -1,4 +1,11 @@ export default { + "#gz_caocao:die": "霸业未成未成啊!", + "#gz_simayi:die": "难道真是天意难违?", + "#gz_xiahoudun:die": "两,两边都看不见了……", + "#gz_zhangliao:die": "真的没想到……", + "#gz_xuzhu:die": "冷,好冷啊……", + "#gz_guojia:die": "咳,咳……", + "#gz_zhenji:die": "悼良会之永绝兮,哀一逝而异乡……", "#gz_xiahouyuan:die": "竟然……比我还……快……", "#gz_zhanghe:die": "啊……膝盖……中箭了……", "#gz_xuhuang:die": "一顿不吃,饿得慌……", @@ -7,4 +14,7 @@ export default { "#gz_xunyu:die": "主公要臣死,臣不得不死……", "#gz_caopi:die": "子建,子建……", "#gz_yuejin:die": "箭疮发作,吾命休矣……", + + "#gz_liubei:die": "这就是桃园吗?", + "#gz_guanyu:die": "什么?此地名叫麦城?", }; From c8e474cc7237413490831a5a7f73b1bb2ba1845e Mon Sep 17 00:00:00 2001 From: Rintim Date: Wed, 16 Apr 2025 23:53:57 +0800 Subject: [PATCH 44/48] feat: rewrite some characters in new format of mode character. --- mode/guozhan/src/character/normal.js | 31 +- mode/guozhan/src/skill/character/normal.js | 281 +++++++++++++++++- .../guozhan/src/translate/character/normal.js | 3 + .../src/translate/skill/character/normal.js | 9 + mode/guozhan/src/translate/voices/normal.js | 3 + noname/ui/create/menu/pages/otherMenu.js | 47 ++- 6 files changed, 363 insertions(+), 11 deletions(-) diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index 686f60eca3..73495a08bb 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -145,9 +145,31 @@ export default { skills: ["gz_wusheng"], hasSkinInGuozhan: true, }), - gz_zhangfei: ["male", "shu", 4, ["gzpaoxiao"]], - gz_zhugeliang: ["male", "shu", 3, ["guanxing", "new_kongcheng"], ["gzskin"]], - gz_zhaoyun: ["male", "shu", 4, ["new_longdan"]], + gz_zhangfei: new Character({ + sex: "male", + group: "shu", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_paoxiao"], + }), + gz_zhugeliang: new Character({ + sex: "male", + group: "shu", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["guanxing", "gz_kongcheng"], + hasSkinInGuozhan: true, + }), + gz_zhaoyun: new Character({ + sex: "male", + group: "shu", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["longdan", "gz_xingshang"], + }), gz_machao: ["male", "shu", 4, ["mashu", "new_tieji"]], gz_huangyueying: ["female", "shu", 3, ["jizhi", "qicai"], ["gzskin"]], gz_huangzhong: ["male", "shu", 4, ["gzliegong"], ["gzskin"]], @@ -179,4 +201,7 @@ export const intro = { gz_liubei: "先主姓刘,讳备,字玄德,涿郡涿县人,汉景帝子中山靖王胜之后也。以仁德治天下。", gz_guanyu: "字云长,本字长生,并州河东解州人。五虎上将之首,爵至汉寿亭侯,谥曰“壮缪侯”。被奉为“关圣帝君”,崇为“武圣”。", + gz_zhangfei: "字翼德,涿郡人,燕颔虎须,豹头环眼。有诗云:“长坂坡头杀气生,横枪立马眼圆睁。一声好似轰雷震,独退曹家百万兵”。", + gz_zhugeliang: "字孔明,号卧龙,琅琊阳都人,蜀汉丞相。在世时被封为武乡侯,谥曰忠武侯。著有《出师表》、《诫子书》等。怀不世之才,以空城戏司马,能观星象而通鬼神。", + gz_zhaoyun: "字子龙,常山真定人。身长八尺,姿颜雄伟。长坂坡单骑救阿斗,先主云:“子龙一身都是胆也。”", }; diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index 3fdc3579d3..ae74438722 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -1153,7 +1153,7 @@ export default { }); await player.give(cards, target); const list = get.inpileVCardList(info => { - return get.type(info[2]) == "basic" && player.hasUseTarget(new lib.element.VCard({ name: info[2], nature: info[3] }), null, true); + return get.type(info[2]) == "basic" && player.hasUseTarget(new lib.element.VCard({ name: info[2], nature: info[3] }), void 0, true); }); if (num < 2 && num + cards.length > 1 && list.length) { const links = await player @@ -1269,4 +1269,283 @@ export default { }, }, }, + + // gz_zhangfei + /** @type {Skill} */ + gz_paoxiao: { + audio: "paoxiao", + audioname2: { + gz_jun_liubei: "shouyue_paoxiao", + }, + trigger: { + player: "useCard", + }, + filter(event, player) { + // @ts-expect-error 类型系统未来可期 + if (_status.currentPhase != player) return false; + if (event.card.name != "sha") return false; + const history = player.getHistory("useCard", evt => { + return evt.card.name == "sha"; + }); + return history && history.indexOf(event) == 1; + }, + forced: true, + preHidden: true, + async content(_event, _trigger, player) { + await player.draw(); + }, + mod: { + cardUsable(card, player, num) { + if (card.name == "sha") return Infinity; + }, + }, + ai: { + unequip: true, + skillTagFilter(player, tag, arg) { + if (!get.zhu(player, "shouyue")) return false; + if (arg && arg.name == "sha") return true; + return false; + }, + }, + }, + + // gz_zhugeliang + /** @type {Skill} */ + gz_kongcheng: { + audio: "kongcheng", + trigger: { + target: "useCardToTarget", + }, + locked: true, + forced: true, + check(event, player) { + return get.effect(event.target, event.card, event.player, player) < 0; + }, + filter(event, player) { + return player.countCards("h") == 0 && (event.card.name == "sha" || event.card.name == "juedou"); + }, + async content(_event, trigger, player) { + // @ts-expect-error 类型系统未来可期 + trigger.getParent()?.targets.remove(player); + }, + onremove(player, skill) { + var cards = player.getExpansions(skill); + if (cards.length) player.loseToDiscardpile(cards); + }, + ai: { + effect: { + target(card, _player, target, _current) { + if (target.countCards("h") == 0 && (card.name == "sha" || card.name == "juedou")) return "zeroplayertarget"; + }, + }, + }, + intro: { + markcount: "expansion", + mark(dialog, _content, player) { + const contents = player.getExpansions("gz_kongcheng"); + if (contents?.length) { + if (player == game.me || player.isUnderControl(void 0, void 0)) { + dialog.addAuto(contents); + } else { + return "共有" + get.cnNumber(contents.length) + "张牌"; + } + } + }, + content(_content, player) { + const contents = player.getExpansions("gz_kongcheng"); + if (contents && contents.length) { + if (player == game.me || player.isUnderControl(void 0, void 0)) { + return get.translation(contents); + } + return "共有" + get.cnNumber(contents.length) + "张牌"; + } + }, + }, + group: ["gz_kongcheng_gain", "gz_kongcheng_got"], + subSkill: { + gain: { + audio: "kongcheng", + trigger: { + player: "gainBefore", + }, + filter(event, player) { + // @ts-expect-error 类型系统未来可期 + return event.source && event.source != player && player != _status.currentPhase && !event.bySelf && player.countCards("h") == 0; + }, + async content(_event, trigger, _player) { + trigger.name = "addToExpansion"; + trigger.setContent("addToExpansion"); + // @ts-expect-error 类型系统未来可期 + trigger.gaintag = ["gz_kongcheng"]; + // @ts-expect-error 类型系统未来可期 + trigger.untrigger(); + trigger.trigger("addToExpansionBefore"); + }, + sub: true, + forced: true, + }, + got: { + trigger: { + player: "phaseDrawBegin1", + }, + filter(_event, player) { + return player.getExpansions("gz_kongcheng").length > 0; + }, + async content(_event, _trigger, player) { + player.gain(player.getExpansions("gz_kongcheng"), "draw"); + }, + sub: true, + forced: true, + }, + }, + }, + + // gz_zhaoyun + /** @type {Skill} */ + new_longdan: { + audio: "longdan_sha", + audioname2: { gz_jun_liubei: "shouyue_longdan" }, + group: ["gz_longdan_sha", "gz_longdan_shan", "gz_longdan_draw", "gz_longdan_shamiss", "gz_longdan_shanafter"], + subSkill: { + shanafter: { + sub: true, + audio: "longdan_sha", + audioname2: { gz_jun_liubei: "shouyue_longdan" }, + trigger: { + player: "useCard", + }, + //priority:1, + filter(event, _player) { + // @ts-expect-error 类型系统未来可期 + return event.skill == "gz_longdan_shan" && event.getParent(2)?.name == "sha"; + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget("是否发动【龙胆】令一名其他角色回复1点体力?", function (card, player, target) { + return target != _status.event?.source && target != player && target.isDamaged(); + }) + .set("ai", function (target) { + return get.attitude(_status.event?.player, target); + }) + // @ts-expect-error 类型系统未来可期 + .set("source", trigger.getParent(2)?.player) + .forResult(); + }, + logTarget: "targets", + async content(event, _trigger, _player) { + await event.targets[0].recover(); + }, + }, + shamiss: { + sub: true, + audio: "longdan_sha", + audioname2: { gz_jun_liubei: "shouyue_longdan" }, + trigger: { + player: "shaMiss", + }, + direct: true, + filter(event, player) { + return event.skill == "gz_longdan_sha"; + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget("是否发动【龙胆】对一名其他角色造成1点伤害?", function (card, player, target) { + return target != _status.event?.target && target != player; + }) + .set("ai", function (target) { + return -get.attitude(_status.event?.player, target); + }) + .set("target", trigger.target) + .forResult(); + }, + logTarget: "targets", + async content(event, _trigger, _player) { + await event.targets[0].damage(); + }, + }, + draw: { + trigger: { + player: ["useCard", "respond"], + }, + audio: "longdan_sha", + audioname2: { gz_jun_liubei: "shouyue_longdan" }, + forced: true, + locked: false, + filter(event, player) { + if (!get.zhu(player, "shouyue")) return false; + return event.skill == "gz_longdan_sha" || event.skill == "gz_longdan_shan"; + }, + async content(_event, _trigger, player) { + player.draw(); + //player.storage.fanghun2++; + }, + sub: true, + }, + sha: { + audio: "longdan_sha", + audioname2: { gz_jun_liubei: "shouyue_longdan" }, + enable: ["chooseToUse", "chooseToRespond"], + filterCard: { + name: "shan", + }, + viewAs: { + name: "sha", + }, + position: "hs", + viewAsFilter(player) { + if (!player.countCards("hs", "shan")) return false; + }, + prompt: "将一张闪当杀使用或打出", + check() { + return 1; + }, + ai: { + effect: { + target(card, player, target, current) { + if (get.tag(card, "respondSha") && current < 0) return 0.6; + }, + }, + respondSha: true, + skillTagFilter(player) { + if (!player.countCards("hs", "shan")) return false; + }, + order() { + return get.order({ name: "sha" }) + 0.1; + }, + }, + sub: true, + }, + shan: { + audio: "longdan_sha", + audioname2: { gz_jun_liubei: "shouyue_longdan" }, + enable: ["chooseToRespond", "chooseToUse"], + filterCard: { + name: "sha", + }, + viewAs: { + name: "shan", + }, + position: "hs", + prompt: "将一张杀当闪使用或打出", + check() { + return 1; + }, + viewAsFilter(player) { + if (!player.countCards("hs", "sha")) return false; + }, + ai: { + respondShan: true, + skillTagFilter(player) { + if (!player.countCards("hs", "sha")) return false; + }, + effect: { + target(card, player, target, current) { + if (get.tag(card, "respondShan") && current < 0) return 0.6; + }, + }, + }, + sub: true, + }, + }, + }, }; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index 937d981bd2..19d3547cf5 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -17,4 +17,7 @@ export default { gz_liubei: "刘备", gz_guanyu: "关羽", + gz_zhangfei: "张飞", + gz_zhugeliang: "诸葛亮", + gz_zhaoyun: "赵云", }; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index f128e711b1..66255126ee 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -47,4 +47,13 @@ export default { gz_wusheng: "武圣", gz_wusheng_info: "你可以将一张红色牌当做【杀】使用或打出。你使用的方片【杀】没有距离限制。", + + gz_paoxiao: "咆哮", + gz_paoxiao_info: "锁定技,你使用【杀】无数量限制;当你于一回合内使用第二张【杀】时,摸一张牌。", + + gz_kongcheng: "空城", + gz_kongcheng_info: "锁定技,若你没有手牌,1.当你成为【杀】或【决斗】的目标时,取消之;2.你的回合外,其他角色交给你牌后,你将这些牌置于你的武将牌上。摸牌阶段开始时,你获得武将牌上的这些牌。", + + gz_longdan: "龙胆", + gz_longdan_info: "你可以将【杀】当【闪】,【闪】当【杀】使用或打出。当你发动〖龙胆〗使用的【杀】被【闪】抵消时,你可以对另一名角色造成1点伤害;当你发动〖龙胆〗使用的【闪】抵消了【杀】时,你可以令一名其他角色回复1点体力(不能是【杀】的使用者)。", }; diff --git a/mode/guozhan/src/translate/voices/normal.js b/mode/guozhan/src/translate/voices/normal.js index 809920f37c..b39c9190c1 100644 --- a/mode/guozhan/src/translate/voices/normal.js +++ b/mode/guozhan/src/translate/voices/normal.js @@ -17,4 +17,7 @@ export default { "#gz_liubei:die": "这就是桃园吗?", "#gz_guanyu:die": "什么?此地名叫麦城?", + "#gz_zhangfei:die": "实在是,杀不动了……", + "#gz_zhugeliang:die": "将星陨落,天命难违……", + "#gz_zhaoyun:die": "这,就是失败的滋味吗?", }; diff --git a/noname/ui/create/menu/pages/otherMenu.js b/noname/ui/create/menu/pages/otherMenu.js index ae824ac1bf..a1e55ae76a 100644 --- a/noname/ui/create/menu/pages/otherMenu.js +++ b/noname/ui/create/menu/pages/otherMenu.js @@ -1,7 +1,8 @@ import { menuContainer, menuxpages, menuUpdates, openMenu, clickToggle, clickSwitcher, clickContainer, clickMenuItem, createMenu, createConfig } from "../index.js"; import { ui, game, get, ai, lib, _status } from "../../../../../noname.js"; import { parseSize, checkVersion, getRepoTagDescription, request, createProgress, getLatestVersionFromGitHub, getTreesFromGithub } from "../../../../library/update.js"; -import security from "../../../../util/security.js"; +import { createApp } from "../../../../../game/vue.esm-browser.js"; +import security from "../../../../util/security.js" import dedent from "../../../../../game/dedent.js"; export const otherMenu = function (/** @type { boolean | undefined } */ connectMenu) { @@ -1626,14 +1627,46 @@ export const otherMenu = function (/** @type { boolean | undefined } */ connectM if (!get.config("menu_loadondemand")) node._initLink(); })(); - for (var i in lib.help) { - var page = ui.create.div(""); - var node = ui.create.div(".menubutton.large", i, start.firstChild, clickMode); - node.type = "help"; - node.link = page; + for (const [name, content] of Object.entries(lib.help)) { + // 创建帮助页面的内容元素 + const page = ui.create.div(""); + // 创建帮助按钮 + // TODO: 对是否应该对按钮进行其他框架的挂载处理 + var node = ui.create.div(".menubutton.large", name, start.firstChild, clickMode); + // 设置帮助按钮的类型 + Reflect.set(node, "type", "help"); + // 初始化帮助按钮的链接 + Reflect.set(node, "link", page); + // 在非帮助页面下默认隐藏 node.style.display = "none"; + // 设置帮助页面的类名 page.classList.add("menu-help"); - page.innerHTML = lib.help[i]; + + // 若传递的内容为对象,则特殊处理 + if (typeof content == "object") { + /** @type {object} */ + const contentObject = content; + + // 如果对象拥有"mount"方式,则调用该方法进行挂载 + if (typeof contentObject.mount == "function") { + contentObject.mount(page); + } + // 如果对象拥有"data"方式或"setup"方式,则视为vue组件 + else if (typeof contentObject.data == "function" || typeof contentObject.setup == "function") { + // 创建vue组件 + const component = createApp(contentObject); + // 挂载到页面 + component.mount(page); + } + // 否则相信`Object#toString`的结果 + else { + page.innerHTML = content; + } + } + // 否则将视为字符串,直接创建文本元素 + else { + page.innerHTML = content; + } } if (!connectMenu) { From bef13163b928eea30b3fef9d5d39cbd79672864a Mon Sep 17 00:00:00 2001 From: Rintim Date: Sun, 20 Apr 2025 22:39:50 +0800 Subject: [PATCH 45/48] feat: rewrite `gz_machao` in new format of mode character. --- mode/guozhan.js | 376 +----------------- mode/guozhan/src/character/normal.js | 12 +- mode/guozhan/src/skill/character/normal.js | 111 +++++- .../guozhan/src/translate/character/normal.js | 1 + .../src/translate/skill/character/normal.js | 5 +- mode/guozhan/src/translate/voices/normal.js | 1 + 6 files changed, 142 insertions(+), 364 deletions(-) diff --git a/mode/guozhan.js b/mode/guozhan.js index 4c69abd822..8560854396 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -14293,7 +14293,7 @@ export default () => { }, content() { "step 0"; - var list = ["new_rewusheng", "gzpaoxiao", "new_longdan", "new_tieji", "liegong", "xinkuanggu"]; + var list = ["gz_wusheng", "gz_paoxiao", "gz_longdan", "gz_tieji", "liegong", "xinkuanggu"]; player .chooseControl(list) .set("ai", function () { @@ -14306,20 +14306,20 @@ export default () => { (function () { let shas = player.mayHaveSha(player, "use", null, "count"), count = player.getCardUsable("sha"); - if (shas > count) return "gzpaoxiao"; - if (shas < count) return "new_rewusheng"; + if (shas > count) return "gz_paoxiao"; + if (shas < count) return "gz_wusheng"; if (!shas) return "xinkuanggu"; - return ["new_longdan", "new_tieji", "liegong"].randomGet(); //脑子不够用了 + return ["gz_longdan", "gz_tieji", "liegong"].randomGet(); //脑子不够用了 })() ) .set("prompt", "选择并获得一项技能直到回合结束"); ("step 1"); player.popup(result.control); var map = { - new_rewusheng: "fz_wusheng", - gzpaoxiao: "fz_new_paoxiao", - new_longdan: "fz_new_longdan", - new_tieji: "fz_new_tieji", + gz_wusheng: "fz_wusheng", + gz_paoxiao: "fz_new_paoxiao", + gz_longdan: "fz_new_longdan", + gz_tieji: "fz_new_tieji", liegong: "fz_liegong", xinkuanggu: "fz_xinkuanggu", }; @@ -14340,15 +14340,15 @@ export default () => { }, fz_new_paoxiao: { audio: true, - inherit: "gzpaoxiao", + inherit: "gz_paoxiao", }, fz_new_tieji: { audio: true, - inherit: "new_tieji", + inherit: "gz_tieji", }, fz_wusheng: { audio: true, - inherit: "new_rewusheng", + inherit: "gz_wusheng", }, fz_liegong: { audio: true, @@ -14776,89 +14776,6 @@ export default () => { }, }, }, - new_kongcheng: { - group: ["new_kongcheng_gain", "new_kongcheng_got"], - subSkill: { - gain: { - audio: "kongcheng", - trigger: { - player: "gainBefore", - }, - filter(event, player) { - return event.source && event.source != player && player != _status.currentPhase && !event.bySelf && player.countCards("h") == 0; - }, - content() { - trigger.name = "addToExpansion"; - trigger.setContent("addToExpansion"); - trigger.gaintag = ["new_kongcheng"]; - trigger.untrigger(); - trigger.trigger("addToExpansionBefore"); - }, - sub: true, - forced: true, - }, - got: { - trigger: { - player: "phaseDrawBegin1", - }, - filter(event, player) { - return player.getExpansions("new_kongcheng").length > 0; - }, - content() { - player.gain(player.getExpansions("new_kongcheng"), "draw"); - }, - sub: true, - forced: true, - }, - }, - audio: "kongcheng", - trigger: { - target: "useCardToTarget", - }, - forced: true, - check(event, player) { - return get.effect(event.target, event.card, event.player, player) < 0; - }, - filter(event, player) { - return player.countCards("h") == 0 && (event.card.name == "sha" || event.card.name == "juedou"); - }, - content() { - trigger.getParent().targets.remove(player); - }, - ai: { - effect: { - target(card, player, target, current) { - if (target.countCards("h") == 0 && (card.name == "sha" || card.name == "juedou")) return "zeroplayertarget"; - }, - }, - }, - intro: { - markcount: "expansion", - mark(dialog, content, player) { - var content = player.getExpansions("new_kongcheng"); - if (content && content.length) { - if (player == game.me || player.isUnderControl()) { - dialog.addAuto(content); - } else { - return "共有" + get.cnNumber(content.length) + "张牌"; - } - } - }, - content(content, player) { - var content = player.getExpansions("new_kongcheng"); - if (content && content.length) { - if (player == game.me || player.isUnderControl()) { - return get.translation(content); - } - return "共有" + get.cnNumber(content.length) + "张牌"; - } - }, - }, - onremove(player, skill) { - var cards = player.getExpansions(skill); - if (cards.length) player.loseToDiscardpile(cards); - }, - }, new_keji: { audio: "keji", forced: true, @@ -14914,186 +14831,7 @@ export default () => { player.moveCard(); }, }, - new_longdan: { - audio: "longdan_sha", - audioname2: { gz_jun_liubei: "shouyue_longdan" }, - group: ["new_longdan_sha", "new_longdan_shan", "new_longdan_draw", "new_longdan_shamiss", "new_longdan_shanafter"], - subSkill: { - shanafter: { - sub: true, - audio: "longdan_sha", - audioname2: { gz_jun_liubei: "shouyue_longdan" }, - trigger: { - player: "useCard", - }, - //priority:1, - filter(event, player) { - return event.skill == "new_longdan_shan" && event.getParent(2).name == "sha"; - }, - direct: true, - content() { - "step 0"; - player - .chooseTarget("是否发动【龙胆】令一名其他角色回复1点体力?", function (card, player, target) { - return target != _status.event.source && target != player && target.isDamaged(); - }) - .set("ai", function (target) { - return get.attitude(_status.event.player, target); - }) - .set("source", trigger.getParent(2).player); - ("step 1"); - if (result.bool && result.targets && result.targets.length) { - player.logSkill("new_longdan", result.targets[0]); - result.targets[0].recover(); - } - }, - }, - shamiss: { - sub: true, - audio: "longdan_sha", - audioname2: { gz_jun_liubei: "shouyue_longdan" }, - trigger: { - player: "shaMiss", - }, - direct: true, - filter(event, player) { - return event.skill == "new_longdan_sha"; - }, - content() { - "step 0"; - player - .chooseTarget("是否发动【龙胆】对一名其他角色造成1点伤害?", function (card, player, target) { - return target != _status.event.target && target != player; - }) - .set("ai", function (target) { - return -get.attitude(_status.event.player, target); - }) - .set("target", trigger.target); - ("step 1"); - if (result.bool && result.targets && result.targets.length) { - player.logSkill("new_longdan", result.targets[0]); - result.targets[0].damage(); - } - }, - }, - draw: { - trigger: { - player: ["useCard", "respond"], - }, - audio: "longdan_sha", - audioname2: { gz_jun_liubei: "shouyue_longdan" }, - forced: true, - locked: false, - filter(event, player) { - if (!get.zhu(player, "shouyue")) return false; - return event.skill == "new_longdan_sha" || event.skill == "new_longdan_shan"; - }, - content() { - player.draw(); - //player.storage.fanghun2++; - }, - sub: true, - }, - sha: { - audio: "longdan_sha", - audioname2: { gz_jun_liubei: "shouyue_longdan" }, - enable: ["chooseToUse", "chooseToRespond"], - filterCard: { - name: "shan", - }, - viewAs: { - name: "sha", - }, - position: "hs", - viewAsFilter(player) { - if (!player.countCards("hs", "shan")) return false; - }, - prompt: "将一张闪当杀使用或打出", - check() { - return 1; - }, - ai: { - effect: { - target(card, player, target, current) { - if (get.tag(card, "respondSha") && current < 0) return 0.6; - }, - }, - respondSha: true, - skillTagFilter(player) { - if (!player.countCards("hs", "shan")) return false; - }, - order() { - return get.order({ name: "sha" }) + 0.1; - }, - }, - sub: true, - }, - shan: { - audio: "longdan_sha", - audioname2: { gz_jun_liubei: "shouyue_longdan" }, - enable: ["chooseToRespond", "chooseToUse"], - filterCard: { - name: "sha", - }, - viewAs: { - name: "shan", - }, - position: "hs", - prompt: "将一张杀当闪使用或打出", - check() { - return 1; - }, - viewAsFilter(player) { - if (!player.countCards("hs", "sha")) return false; - }, - ai: { - respondShan: true, - skillTagFilter(player) { - if (!player.countCards("hs", "sha")) return false; - }, - effect: { - target(card, player, target, current) { - if (get.tag(card, "respondShan") && current < 0) return 0.6; - }, - }, - }, - sub: true, - }, - }, - }, - gzpaoxiao: { - audio: "paoxiao", - audioname2: { gz_jun_liubei: "shouyue_paoxiao" }, - trigger: { - player: "useCard", - }, - filter(event, player) { - if (_status.currentPhase != player) return false; - if (event.card.name != "sha") return false; - var history = player.getHistory("useCard", function (evt) { - return evt.card.name == "sha"; - }); - return history && history.indexOf(event) == 1; - }, - forced: true, - preHidden: true, - content() { - player.draw(); - }, - mod: { - cardUsable(card, player, num) { - if (card.name == "sha") return Infinity; - }, - }, - ai: { - unequip: true, - skillTagFilter(player, tag, arg) { - if (!get.zhu(player, "shouyue")) return false; - if (arg && arg.name == "sha") return true; - return false; - }, - }, - }, + new_kurou: { audio: "rekurou", enable: "phaseUse", @@ -15290,83 +15028,6 @@ export default () => { }, }, }, - new_tieji: { - audio: "retieji", - audioname2: { gz_jun_liubei: "shouyue_tieji" }, - trigger: { - player: "useCardToPlayered", - }, - check(event, player) { - return get.attitude(player, event.target) < 0; - }, - filter(event) { - return event.card.name == "sha"; - }, - logTarget: "target", - content() { - "step 0"; - var target = trigger.target; - var controls = []; - if (get.zhu(player, "shouyue")) { - if (!target.isUnseen(0)) target.addTempSkill("fengyin_main"); - if (!target.isUnseen(1)) target.addTempSkill("fengyin_vice"); - event.goto(2); - } - if (!target.isUnseen(0) && !target.hasSkill("fengyin_main")) controls.push("主将"); - if (!target.isUnseen(1) && !target.hasSkill("fengyin_vice")) controls.push("副将"); - if (controls.length > 0) { - if (controls.length == 1) event._result = { control: controls[0] }; - else { - player - .chooseControl(controls) - .set("ai", function () { - var choice = "主将"; - var skills = lib.character[target.name2][3]; - for (var i = 0; i < skills.length; i++) { - var info = get.info(skills[i]); - if (info && info.ai && info.ai.maixie) { - choice = "副将"; - break; - } - } - return choice; - }) - .set("prompt", "请选择一个武将牌,令" + get.translation(target) + "该武将牌上的非锁定技全部失效。"); - } - } else event.goto(2); - ("step 1"); - if (result.control) { - player.popup(result.control, "fire"); - var target = trigger.target; - if (result.control == "主将") target.addTempSkill("fengyin_main"); - else target.addTempSkill("fengyin_vice"); - } - ("step 2"); - player.judge(function () { - return 0; - }); - ("step 3"); - var suit = get.suit(result.card); - var target = trigger.target; - var num = target.countCards("h", "shan"); - target - .chooseToDiscard("请弃置一张" + get.translation(suit) + "牌,否则不能使用闪抵消此杀", "he", function (card) { - return get.suit(card) == _status.event.suit; - }) - .set("ai", function (card) { - var num = _status.event.num; - if (num == 0) return 0; - if (card.name == "shan") return num > 1 ? 2 : 0; - return 8 - get.value(card); - }) - .set("num", num) - .set("suit", suit); - ("step 4"); - if (!result.bool) { - trigger.getParent().directHit.add(trigger.target); - } - }, - }, hmkyuanyu: { audio: "zongkui", trigger: { @@ -17326,7 +16987,7 @@ export default () => { unique: true, forceunique: true, global: "wuhujiangdaqi", - derivation: ["wuhujiangdaqi", "new_rewusheng", "gzpaoxiao", "new_longdan", "new_tieji", "gzliegong"], + derivation: ["wuhujiangdaqi", "gz_wusheng", "gz_paoxiao", "gz_longdan", "gz_tieji", "gzliegong"], mark: true, lordSkill: true, init(player) { @@ -19007,20 +18668,16 @@ export default () => { new_qingcheng_info: "出牌阶段,你可以弃置一张黑色牌并选择一名武将牌均明置的其他角色,然后你暗置其一张武将牌。若你以此法弃置的牌为装备牌,则你可以暗置另一名武将牌均明置的角色的一张武将牌。", huoshui: "祸水", huoshui_info: "锁定技。你的回合内,①其他角色不能明置武将牌。②当你使用【杀】或【万箭齐发】指定目标后,若目标角色与你势力不同且有暗置武将牌,则其不能使用或出【闪】直到此牌结算结束。", - new_kongcheng: "空城", - new_kongcheng_info: "锁定技,若你没有手牌,1.当你成为【杀】或【决斗】的目标时,取消之;2.你的回合外,其他角色交给你牌后,你将这些牌置于你的武将牌上。摸牌阶段开始时,你获得武将牌上的这些牌。", new_keji: "克己", new_keji_info: "锁定技,若你没有在出牌阶段内使用过颜色不同的牌,则你本回合的手牌上限+4。", keji_add: "克己", keji_add_info: "", new_mouduan: "谋断", new_mouduan_info: "结束阶段,若你于本回合内使用过四种花色或三种类别的牌,则你可以移动场上的一张牌。", - new_longdan: "龙胆", - new_longdan_info: "你可以将【杀】当【闪】,【闪】当【杀】使用或打出。当你发动〖龙胆〗使用的【杀】被【闪】抵消时,你可以对另一名角色造成1点伤害;当你发动〖龙胆〗使用的【闪】抵消了【杀】时,你可以令一名其他角色回复1点体力(不能是【杀】的使用者)。", + fz_new_longdan: "龙胆", fz_new_longdan_info: "你可以将【杀】当【闪】,【闪】当【杀】使用或打出。当你发动〖龙胆〗使用的【杀】被【闪】抵消时,你可以对另一名角色造成1点伤害;当你发动〖龙胆〗使用的【闪】抵消了【杀】时,你可以令一名其他角色回复1点体力(不能是【杀】的使用者)。", - gzpaoxiao: "咆哮", - gzpaoxiao_info: "锁定技,你使用【杀】无数量限制;当你于一回合内使用第二张【杀】时,摸一张牌。", + new_kurou: "苦肉", new_kurou_info: "出牌阶段限一次,你可以弃置一张牌,然后失去1点体力并摸三张牌,本回合使用【杀】的次数上限+1。", kurou_effect: "苦肉", @@ -19037,8 +18694,7 @@ export default () => { fengyin_main_info: "", fengyin_vice: "封印[副将]", fengyin_vice_info: "", - new_tieji: "铁骑", - new_tieji_info: "当你使用【杀】指定目标后,你可以令其一张明置的武将牌上的非锁定技于本回合内失效,然后你进行判定,除非该角色弃置与结果花色相同的一张牌,否则其不能使用【闪】响应此【杀】。", + hmkyuanyu: "远域", hmkyuanyu_info: "锁定技,当你受到伤害时,若伤害来源与你的座次不相邻,防止此伤害。", hmkguishu: "鬼术", diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index 73495a08bb..34bd86e20e 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -168,9 +168,16 @@ export default { hp: 4, maxHp: 4, hujia: 0, - skills: ["longdan", "gz_xingshang"], + skills: ["gz_longdan"], }), - gz_machao: ["male", "shu", 4, ["mashu", "new_tieji"]], + gz_machao: new Character({ + sex: "male", + group: "shu", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["mashu", "gz_tieji"], + }), // ["male", "shu", 4, ["mashu", "new_tieji"]] gz_huangyueying: ["female", "shu", 3, ["jizhi", "qicai"], ["gzskin"]], gz_huangzhong: ["male", "shu", 4, ["gzliegong"], ["gzskin"]], gz_weiyan: ["male", "shu", 4, ["xinkuanggu"]], @@ -204,4 +211,5 @@ export const intro = { gz_zhangfei: "字翼德,涿郡人,燕颔虎须,豹头环眼。有诗云:“长坂坡头杀气生,横枪立马眼圆睁。一声好似轰雷震,独退曹家百万兵”。", gz_zhugeliang: "字孔明,号卧龙,琅琊阳都人,蜀汉丞相。在世时被封为武乡侯,谥曰忠武侯。著有《出师表》、《诫子书》等。怀不世之才,以空城戏司马,能观星象而通鬼神。", gz_zhaoyun: "字子龙,常山真定人。身长八尺,姿颜雄伟。长坂坡单骑救阿斗,先主云:“子龙一身都是胆也。”", + gz_machao: "字孟起,扶风茂陵人。面如冠玉,目如流星,虎体猿臂,彪腹狼腰,声雄力猛。因衣着讲究,举止非凡,故人称“锦马超”。麾铁骑,捻金枪。", }; diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index ae74438722..44f29ff3e2 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -1402,7 +1402,7 @@ export default { // gz_zhaoyun /** @type {Skill} */ - new_longdan: { + gz_longdan: { audio: "longdan_sha", audioname2: { gz_jun_liubei: "shouyue_longdan" }, group: ["gz_longdan_sha", "gz_longdan_shan", "gz_longdan_draw", "gz_longdan_shamiss", "gz_longdan_shanafter"], @@ -1548,4 +1548,113 @@ export default { }, }, }, + + // gz_machao + /** @type {Skill} */ + gz_tieji: { + audio: "retieji", + audioname2: { + gz_jun_liubei: "shouyue_tieji", + }, + trigger: { + player: "useCardToPlayered", + }, + check(event, player) { + return get.attitude(player, event.target) < 0; + }, + filter(event) { + return event.card.name == "sha"; + }, + logTarget: "target", + async content(_event, trigger, player) { + const { target } = trigger; + + /** @type {string[]} */ + const addingSkills = []; + const targetMainShowing = !target.isUnseen(0); + const targetViceShowing = !target.isUnseen(1); + if (get.zhu(player, "shouyue")) { + if (targetMainShowing) { + addingSkills.push("fengyin_main"); + } + if (targetViceShowing) { + addingSkills.push("fengyin_vice"); + } + } else { + const controls = []; + if (targetMainShowing && !target.hasSkill("fengyin_main")) { + controls.push("主将"); + } + if (targetViceShowing && !target.hasSkill("fengyin_vice")) { + controls.push("副将"); + } + + /** @type {?Partial} */ + let result = null; + + if (controls.length == 1) { + result = { control: controls[0] }; + } else if (controls.length > 1) { + result = await player + .chooseControl(controls) + .set("ai", () => { + let choice = "主将"; + const skills = lib.character[target.name2][3]; + for (const skill of skills) { + const info = get.info(skill); + if (info?.ai?.maixie) { + choice = "副将"; + break; + } + } + return choice; + }) + .set("prompt", `请选择一个武将牌,令${get.translation(target)}该武将牌上的非锁定技全部失效。`) + .forResult(); + } + + if (result?.control) { + const map = { + "主将": "fengyin_main", + "副将": "fengyin_vice", + } + + addingSkills.push(map[result.control]); + } + } + + addingSkills.forEach(skill => { + target.addTempSkill(skill); + }); + + const result = await player.judge(() => 0).forResult(); + + // @ts-expect-error 类型系统未来可期 + const suit = get.suit(result.card); + const num = target.countCards("h", "shan"); + const result2 = await target + .chooseToDiscard("请弃置一张" + get.translation(suit) + "牌,否则不能使用闪抵消此杀", "he", function (card) { + // @ts-expect-error 类型系统未来可期 + return get.suit(card) == get.event().suit; + }) + .set("ai", card => { + const num = get.event().num; + if (num == 0) { + return 0; + } + if (card.name == "shan") { + return num > 1 ? 2 : 0; + } + return 8 - get.value(card); + }) + .set("num", num) + .set("suit", suit) + .forResult(); + + if (!result2.bool) { + // @ts-expect-error 类型系统未来可期 + trigger.getParent().directHit.add(trigger.target); + } + }, + }, }; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index 19d3547cf5..2eaf426aa5 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -20,4 +20,5 @@ export default { gz_zhangfei: "张飞", gz_zhugeliang: "诸葛亮", gz_zhaoyun: "赵云", + gz_machao: "马超", }; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index 66255126ee..085fa6570e 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -56,4 +56,7 @@ export default { gz_longdan: "龙胆", gz_longdan_info: "你可以将【杀】当【闪】,【闪】当【杀】使用或打出。当你发动〖龙胆〗使用的【杀】被【闪】抵消时,你可以对另一名角色造成1点伤害;当你发动〖龙胆〗使用的【闪】抵消了【杀】时,你可以令一名其他角色回复1点体力(不能是【杀】的使用者)。", -}; + + gz_tieji: "铁骑", + gz_tieji_info: "当你使用【杀】指定目标后,你可以令其一张明置的武将牌上的非锁定技于本回合内失效,然后你进行判定,除非该角色弃置与结果花色相同的一张牌,否则其不能使用【闪】响应此【杀】。", +} diff --git a/mode/guozhan/src/translate/voices/normal.js b/mode/guozhan/src/translate/voices/normal.js index b39c9190c1..b06ab20773 100644 --- a/mode/guozhan/src/translate/voices/normal.js +++ b/mode/guozhan/src/translate/voices/normal.js @@ -20,4 +20,5 @@ export default { "#gz_zhangfei:die": "实在是,杀不动了……", "#gz_zhugeliang:die": "将星陨落,天命难违……", "#gz_zhaoyun:die": "这,就是失败的滋味吗?", + "#gz_machao:die": "(马蹄声远去……)", }; From ba3d64e7ec7ba6f1b1132790801f4bedd00eafb5 Mon Sep 17 00:00:00 2001 From: Rintim Date: Thu, 24 Apr 2025 11:34:44 +0800 Subject: [PATCH 46/48] chore: fix the type of event result. --- .../noname/library/element/gameEvent.d.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEvent.d.ts b/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEvent.d.ts index 0ef774a280..e288b88e9a 100644 --- a/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEvent.d.ts +++ b/node_modules/@types/noname-typings/nonameModules/noname/library/element/gameEvent.d.ts @@ -22,9 +22,9 @@ export class GameEvent implements PromiseLike> { */ _triggered: number | null; /** - * @type { Result } + * @type { Partial } */ - result: Result; + result: Partial; /** * @type { string } */ @@ -90,9 +90,9 @@ export class GameEvent implements PromiseLike> { */ _notrigger: Player[]; /** - * @type { Result } + * @type { Partial } */ - _result: Result; + _result: Partial; /** * @type { any[] } */ @@ -441,7 +441,7 @@ export class GameEvent implements PromiseLike> { * @param { T[] } params * @returns { Promise[]> } */ - forResult(): Promise; + forResult(): Promise>; /** * 获取 Result 对象中的信息。 * @example From 6e9c02e3144942d89225ca3703fc90e5f185475b Mon Sep 17 00:00:00 2001 From: Rintim Date: Thu, 24 Apr 2025 21:37:27 +0800 Subject: [PATCH 47/48] feat: rewrite rest characters of shu in new format of mode character. --- mode/guozhan.js | 93 +----- mode/guozhan/src/character/normal.js | 84 ++++- mode/guozhan/src/skill/character/normal.js | 303 +++++++++++++++++- .../guozhan/src/translate/character/normal.js | 4 + .../src/translate/skill/character/normal.js | 16 +- mode/guozhan/src/translate/voices/normal.js | 4 + 6 files changed, 402 insertions(+), 102 deletions(-) diff --git a/mode/guozhan.js b/mode/guozhan.js index 8560854396..2f3363b35e 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -946,29 +946,7 @@ export default () => { }, }, //甘夫人 - gzshushen_new: { - audio: "shushen", - trigger: { player: "recoverEnd" }, - getIndex: event => event.num || 1, - preHidden: true, - async cost(event, trigger, player) { - event.result = await player - .chooseTarget(get.prompt2("gzshushen_new"), lib.filter.notMe) - .set("ai", target => { - const player = get.player(); - return get.effect(target, { name: "draw" }, player, player) * (1 + !Boolean(target.countCards("h"))); - }) - .setHiddenSkill("gzshushen_new") - .forResult(); - }, - content() { - event.targets[0].draw(Boolean(event.targets[0].countCards("h")) ? 1 : 2); - }, - ai: { - threaten: 0.8, - expose: 0.1, - }, - }, + //徐盛 gzyicheng_new: { audio: "yicheng", @@ -8516,66 +8494,7 @@ export default () => { }, }, }, - //黄忠 - gzliegong: { - audio: "liegong", - audioname2: { gz_jun_liubei: "shouyue_liegong" }, - locked: false, - mod: { - targetInRange(card, player, target) { - if (card.name == "sha" && target.countCards("h") < player.countCards("h")) return true; - }, - attackRange(player, distance) { - if (get.zhu(player, "shouyue")) return distance + 1; - }, - }, - trigger: { player: "useCardToPlayered" }, - filter(event, player) { - return event.card.name == "sha" && player.hp <= event.target.hp; - }, - direct: true, - preHidden: true, - content() { - "step 0"; - var str = get.translation(trigger.target), - card = get.translation(trigger.card); - player - .chooseControl("cancel2") - .set("choiceList", ["令" + card + "对" + str + "的伤害+1", "令" + str + "不能响应" + card]) - .set("prompt", get.prompt("gzliegong", trigger.target)) - .setHiddenSkill("gzliegong") - .set("ai", function () { - var player = _status.event.player, - target = _status.event.getTrigger().target; - if (get.attitude(player, target) > 0) return 2; - return target.mayHaveShan( - player, - "use", - target.getCards("h", i => { - return i.hasGaintag("sha_notshan"); - }) - ) - ? 1 - : 0; - }); - ("step 1"); - if (result.control != "cancel2") { - var target = trigger.target; - player.logSkill("gzliegong", target); - if (result.index == 1) { - game.log(trigger.card, "不可被", target, "响应"); - trigger.directHit.add(target); - } else { - game.log(trigger.card, "对", target, "的伤害+1"); - var map = trigger.getParent().customArgs, - id = target.playerid; - if (!map[id]) map[id] = {}; - if (!map[id].extraDamage) map[id].extraDamage = 0; - map[id].extraDamage++; - } - } - }, - }, + //潘凤 gzkuangfu: { audio: "kuangfu", @@ -16987,7 +16906,7 @@ export default () => { unique: true, forceunique: true, global: "wuhujiangdaqi", - derivation: ["wuhujiangdaqi", "gz_wusheng", "gz_paoxiao", "gz_longdan", "gz_tieji", "gzliegong"], + derivation: ["wuhujiangdaqi", "gz_wusheng", "gz_paoxiao", "gz_longdan", "gz_tieji", "gz_liegong"], mark: true, lordSkill: true, init(player) { @@ -18429,8 +18348,7 @@ export default () => { gzwushuang_info: "锁定技。①当你使用【杀】指定一名角色为目标后,其需使用两张【闪】才能抵消;②当你使用【决斗】指定其他角色为目标后,或成为其他角色使用【决斗】的目标后,其每次响应需打出两张【杀】。③当你使用非转化的【决斗】选择目标后,你可为此【决斗】增加两个目标。", gzkuangfu: "狂斧", gzkuangfu_info: "出牌阶段限一次。当你使用【杀】指定目标后,你可获得目标角色装备区内的一张牌。然后若此【杀】未造成伤害,则你弃置两张手牌。", - gzliegong: "烈弓", - gzliegong_info: "①你对手牌数不大于你的角色使用【杀】不受距离关系的限制。②当你使用【杀】指定目标后,若其体力值不小于你,则你可以选择一项:⒈令此【杀】对其的伤害值基数+1。⒉令其不可响应此【杀】。", + gzhongyan: "红颜", gzhongyan_info: "锁定技。①你区域内的黑桃牌和黑桃判定牌的花色视为红桃。②若你的装备区内有红桃牌,则你的手牌上限+1。", gztianxiang: "天香", @@ -19151,8 +19069,7 @@ export default () => { gzsidi: "司敌", gzsidi_info: "①一名与你势力相同的角色受到伤害后,你可以将一张与武将牌上的“驭”类别均不同的一张牌称为“驭”置于武将牌上。②与你势力不同的角色的回合开始时,你可以移去至多三张“驭”,然后选择执行等量项:⒈选择移去“驭”中的一个类别,令其本回合无法使用此类别的牌。⒉选择其一个已明置武将牌上的一个技能,令此技能于本回合失效。⒊选择一名与你势力相同的已受伤其他角色,令其回复1点体力。", gz_ol_lisu: "李肃", - gzshushen_new: "淑慎", - gzshushen_new_info: "当你回复1点体力后,你可令一名其他角色摸一张牌(若其没有手牌则改为摸两张牌)。", + gzyicheng_new: "疑城", gzyicheng_new_info: "与你势力相同的角色使用【杀】指定第一个目标后或成为【杀】的目标后,你可以令其摸一张牌,然后其弃置一张牌。", gzduoshi: "度势", diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index 34bd86e20e..34959ff104 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -177,16 +177,76 @@ export default { maxHp: 4, hujia: 0, skills: ["mashu", "gz_tieji"], - }), // ["male", "shu", 4, ["mashu", "new_tieji"]] - gz_huangyueying: ["female", "shu", 3, ["jizhi", "qicai"], ["gzskin"]], - gz_huangzhong: ["male", "shu", 4, ["gzliegong"], ["gzskin"]], - gz_weiyan: ["male", "shu", 4, ["xinkuanggu"]], - gz_pangtong: ["male", "shu", 3, ["lianhuan", "oldniepan"]], - gz_sp_zhugeliang: ["male", "shu", 3, ["huoji", "bazhen", "kanpo"], ["gzskin"]], - gz_liushan: ["male", "shu", 3, ["xiangle", "fangquan"]], - gz_menghuo: ["male", "shu", 4, ["huoshou", "rezaiqi"]], - gz_zhurong: ["female", "shu", 4, ["juxiang", "lieren"]], - gz_ganfuren: ["female", "shu", 3, ["gzshushen_new", "shenzhi"], ["gzskin"]], + }), + gz_huangyueying: new Character({ + sex: "female", + group: "shu", + hp: 3, + maxHp: 3, + skills: ["jizhi", "qicai"], + hasSkinInGuozhan: true, + }), + gz_huangzhong: new Character({ + sex: "male", + group: "shu", + hp: 4, + maxHp: 4, + skills: ["gz_liegong"], + hasSkinInGuozhan: true, + }), + gz_weiyan: new Character({ + sex: "male", + group: "shu", + hp: 4, + maxHp: 4, + skills: ["gz_kuanggu"], + }), + gz_pangtong: new Character({ + sex: "male", + group: "shu", + hp: 3, + maxHp: 3, + skills: ["gz_lianhuan", "gz_niepan"], + }), + // 后续的武将如果不是本身拥有国战的技能,暂时都摆了,解耦时记得把技能从原来的包拿过来 + // 描述也是 + gz_sp_zhugeliang: new Character({ + sex: "male", + group: "shu", + hp: 3, + maxHp: 3, + skills: ["huoji", "bazhen", "kanpo"], + hasSkinInGuozhan: true, + }), + gz_liushan: new Character({ + sex: "male", + group: "shu", + hp: 3, + maxHp: 3, + skills: ["xiangle", "fangquan"], + }), + gz_menghuo: new Character({ + sex: "male", + group: "shu", + hp: 4, + maxHp: 4, + skills: ["huoshou", "rezaiqi"], + }), + gz_zhurong: new Character({ + sex: "female", + group: "shu", + hp: 4, + maxHp: 4, + skills: ["juxiang", "lieren"], + }), + gz_ganfuren: new Character({ + sex: "female", + group: "shu", + hp: 3, + maxHp: 3, + skills: ["gz_shushen", "shenzhi"], + hasSkinInGuozhan: true, + }), }; export const intro = { @@ -212,4 +272,8 @@ export const intro = { gz_zhugeliang: "字孔明,号卧龙,琅琊阳都人,蜀汉丞相。在世时被封为武乡侯,谥曰忠武侯。著有《出师表》、《诫子书》等。怀不世之才,以空城戏司马,能观星象而通鬼神。", gz_zhaoyun: "字子龙,常山真定人。身长八尺,姿颜雄伟。长坂坡单骑救阿斗,先主云:“子龙一身都是胆也。”", gz_machao: "字孟起,扶风茂陵人。面如冠玉,目如流星,虎体猿臂,彪腹狼腰,声雄力猛。因衣着讲究,举止非凡,故人称“锦马超”。麾铁骑,捻金枪。", + gz_huangyueying: "荆州沔南白水人,沔阳名士黄承彦之女,诸葛亮之妻,诸葛瞻之母。容貌甚丑,而有奇才:上通天文,下察地理,韬略近于诸书无所不晓,诸葛亮在南阳闻其贤而迎娶。", + gz_huangzhong: "字汉升,今河南南阳人。汉末三国时期蜀汉名将。本为刘表部下中郎将,后归刘备,并助刘备攻益州刘璋,在定军山一战中阵斩曹操部下名将夏侯渊。备称汉中王后改封后将军,赐关内侯。", + gz_weiyan: "字文长,义阳人。三国时期蜀汉名将,诸葛亮死后,魏延因被陷害谋反而遭杨仪一党所杀。", + gz_pangtong: "庞统,字士元,襄阳(治今湖北襄阳)人。三国时刘备帐下谋士,官拜军师中郎将。才智与诸葛亮齐名,人称“凤雏”。在进围雒县时,统率众攻城,不幸被流矢击中去世,时年三十六岁。追赐统为关内侯,谥曰靖侯。庞统死后,葬于落凤庞统墓坡。", }; diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index 44f29ff3e2..bcd233abe7 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -1615,9 +1615,9 @@ export default { if (result?.control) { const map = { - "主将": "fengyin_main", - "副将": "fengyin_vice", - } + 主将: "fengyin_main", + 副将: "fengyin_vice", + }; addingSkills.push(map[result.control]); } @@ -1657,4 +1657,301 @@ export default { } }, }, + + // gz_huangzhong + /** @type {Skill} */ + gz_liegong: { + audio: "liegong", + audioname2: { + gz_jun_liubei: "shouyue_liegong", + }, + trigger: { + player: "useCardToPlayered", + }, + locked: false, + filter(event, player) { + return event.card.name == "sha" && player.hp <= event.target.hp; + }, + preHidden: true, + async cost(event, trigger, player) { + const target = get.translation(trigger.target); + const card = get.translation(trigger.card); + + const next = player.chooseControl("cancel2"); + + next.set("prompt", get.prompt("gz_liegong", trigger.target)); + next.set("choiceList", [`令${card}对${target}的伤害+1`, `令${target}不能响应${card}`]); + next.set("ai", check); + next.setHiddenSkill("gz_liegong"); + + const result = await next.forResult(); + + event.result = { + bool: result.control != "cancel2", + targets: [trigger.target], + cost_data: { + index: result.index, + control: result.control, + }, + }; + + return; + + function check() { + const player = get.player(); + const target = get.event().getTrigger().target; + + if (get.attitude(player, target) > 0) { + return 2; + } + + const cards = target.getCards("h", card => card.hasGaintag("sha_notshan")); + return target.mayHaveShan(player, "use", cards) ? 1 : 0; + } + }, + logTarget: "targets", + async content(event, trigger, player) { + const [target] = event.targets; + + const { index } = event.cost_data; + + if (index == 1) { + game.log(trigger.card, "不可被", target, "响应"); + // @ts-expect-error 类型系统未来可期 + trigger.directHit.add(target); + } else { + game.log(trigger.card, "对", target, "的伤害+1"); + // @ts-expect-error 类型系统未来可期 + const map = trigger.getParent()?.customArgs; + const id = target.playerid; + map[id] ??= {}; + map[id].extraDamage ??= 0; + map[id].extraDamage++; + } + }, + mod: { + targetInRange(card, player, target) { + if (card.name == "sha" && target.countCards("h") < player.countCards("h")) return true; + }, + attackRange(player, distance) { + if (get.zhu(player, "shouyue")) return distance + 1; + }, + }, + }, + + // gz_weiyan + /** @type {Skill} */ + gz_kuanggu: { + audio: "kuanggu", + audioname: ["re_weiyan", "ol_weiyan"], + trigger: { + source: "damageSource", + }, + filter(event, _player) { + // @ts-expect-error 类型系统未来可期 + return event.checkKuanggu && event.num > 0; + }, + getIndex(event, _player, _triggername) { + return event.num; + }, + preHidden: true, + async cost(event, _trigger, player) { + let choice; + if ( + player.isDamaged() && + get.recoverEffect(player) > 0 && + player.countCards("hs", function (card) { + return card.name == "sha" && player.hasValueTarget(card); + }) >= player.getCardUsable("sha", void 0) + ) { + choice = "recover_hp"; + } else { + choice = "draw_card"; + } + const next = player.chooseDrawRecover("###" + get.prompt("xinkuanggu") + "###摸一张牌或回复1点体力"); + next.set("choice", choice); + next.set("ai", function () { + // @ts-expect-error 类型系统未来可期 + return _status.event.getParent().choice; + }); + next.setHiddenSkill("xinkuanggu"); + const control = await next.forResultControl(); + if (control == "cancel2") return; + event.result = { bool: true }; + }, + async content(_event, _trigger, _player) {}, + }, + + // gz_pangtong + /** @type {Skill} */ + gz_lianhuan: { + audio: "lianhuan", + hiddenCard(player, name) { + return name == "tiesuo" && player.hasCard(card => get.suit(card) == "club", "sh"); + }, + enable: "chooseToUse", + filter(event, player) { + if (!player.hasCard(card => get.suit(card) == "club", "sh")) return false; + return event.type == "phase" || event.filterCard(get.autoViewAs({ name: "tiesuo" }, "unsure"), player, event); + }, + position: "hs", + filterCard(card, player, event) { + if (!event) event = _status.event; + if (get.suit(card) != "club") return false; + if (event.type == "phase" && get.position(card) != "s" && player.canRecast(card)) { + return true; + } else { + // @ts-expect-error 类型系统未来可期 + if (game.checkMod(card, player, "unchanged", "cardEnabled2", player) === false) return false; + const cardx = get.autoViewAs({ name: "tiesuo" }, [card]); + return event._backup.filterCard(cardx, player, event); + } + }, + filterTarget(fuck, player, target) { + const card = ui.selected.cards[0]; + const event = get.event(); + const backup = event._backup; + // @ts-expect-error 类型系统未来可期 + if (!card || game.checkMod(card, player, "unchanged", "cardEnabled2", player) === false) return false; + const cardx = get.autoViewAs({ name: "tiesuo" }, [card]); + return backup.filterCard(cardx, player, event) && backup.filterTarget(cardx, player, target); + }, + selectTarget() { + const card = ui.selected.cards[0]; + const event = get.event(); + const player = event.player; + const backup = event._backup; + let recast = false; + let use = false; + const cardx = get.autoViewAs({ name: "tiesuo" }, [card]); + if (event.type == "phase" && player.canRecast(card)) recast = true; + // @ts-expect-error 类型系统未来可期 + if (card && game.checkMod(card, player, "unchanged", "cardEnabled2", player) !== false) { + if (backup.filterCard(cardx, player, event)) use = true; + } + if (!use) return [0, 0]; + else { + const select = backup.selectTarget(cardx, player); + if (recast && select[0] > 0) select[0] = 0; + return select; + } + }, + filterOk() { + const card = ui.selected.cards[0]; + const event = get.event(); + const player = event.player; + const backup = event._backup; + const selected = ui.selected.targets.length; + let recast = false, + use = false; + const cardx = get.autoViewAs({ name: "tiesuo" }, [card]); + if (event.type == "phase" && player.canRecast(card)) recast = true; + // @ts-expect-error 类型系统未来可期 + if (card && game.checkMod(card, player, "unchanged", "cardEnabled2", player) !== false) { + if (backup.filterCard(cardx, player, event)) use = true; + } + if (recast && selected == 0) { + return true; + } else if (use) { + const select = backup.selectTarget(cardx, player); + if (select[0] <= -1) return true; + return selected >= select[0] && selected <= select[1]; + } + }, + discard: false, + lose: false, + delay: false, + async precontent(event, trigger, player) { + const result = event.result; + // @ts-expect-error 类型系统未来可期 + if (result.targets.length > 0) result.card = get.autoViewAs({ name: "tiesuo" }, result.cards); + }, + async content(event, trigger, player) { + await player.recast(event.cards); + }, + }, + /** @type {Skill} */ + gz_niepan: { + audio: "niepan", + audioname2: { + sb_pangtong: "sbniepan", + }, + unique: true, + enable: "chooseToUse", + mark: true, + skillAnimation: true, + limited: true, + animationColor: "orange", + init(player) { + player.storage.gz_niepan = false; + }, + filter(event, player) { + if (player.storage.gz_niepan) return false; + if (event.type == "dying") { + // @ts-expect-error 类型系统未来可期 + if (player != event.dying) return false; + return true; + } + return false; + }, + async content(event, trigger, player) { + player.awakenSkill("gz_niepan", void 0); + player.storage.gz_niepan = true; + await player.discard(player.getCards("hej")); + await player.link(false); + await player.turnOver(false); + await player.draw(3); + if (player.hp < 3) { + await player.recover(3 - player.hp); + } + }, + ai: { + order: 1, + skillTagFilter(player, arg, target) { + if (player != target || player.storage.oldniepan) return false; + }, + save: true, + result: { + player(player) { + if (player.hp <= 0) return 10; + if (player.hp <= 2 && player.countCards("he") <= 1) return 10; + return 0; + }, + }, + threaten(player, target) { + if (!target.storage.oldniepan) return 0.6; + }, + }, + intro: { + content: "limited", + }, + }, + + // gz_ganfuren + /** @type {Skill} */ + gz_shushen: { + audio: "shushen", + trigger: { + player: "recoverEnd", + }, + getIndex: event => event.num || 1, + preHidden: true, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("gzshushen_new"), lib.filter.notMe) + .set("ai", target => { + const player = get.player(); + return get.effect(target, { name: "draw" }, player, player) * (1 + !Boolean(target.countCards("h"))); + }) + .setHiddenSkill("gzshushen_new") + .forResult(); + }, + async content(event, trigger, player) { + event.targets[0].draw(Boolean(event.targets[0].countCards("h")) ? 1 : 2); + }, + ai: { + threaten: 0.8, + expose: 0.1, + }, + }, }; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index 2eaf426aa5..8bb2fb432b 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -21,4 +21,8 @@ export default { gz_zhugeliang: "诸葛亮", gz_zhaoyun: "赵云", gz_machao: "马超", + gz_huangyueying: "黄月英", + gz_huangzhong: "黄忠", + gz_weiyan: "魏延", + gz_pangtong: "庞统", }; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index 085fa6570e..e6c114c53a 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -59,4 +59,18 @@ export default { gz_tieji: "铁骑", gz_tieji_info: "当你使用【杀】指定目标后,你可以令其一张明置的武将牌上的非锁定技于本回合内失效,然后你进行判定,除非该角色弃置与结果花色相同的一张牌,否则其不能使用【闪】响应此【杀】。", -} + + gz_liegong: "烈弓", + gz_liegong_info: "①你对手牌数不大于你的角色使用【杀】不受距离关系的限制。②当你使用【杀】指定目标后,若其体力值不小于你,则你可以选择一项:⒈令此【杀】对其的伤害值基数+1。⒉令其不可响应此【杀】。", + + gz_kuanggu: "狂骨", + gz_kuanggu_info: "当你造成1点伤害后,若受伤角色受到此伤害时你与其的距离不大于1,则你可以回复1点体力或摸一张牌。", + + gz_lianhuan: "连环", + gz_lianhuan_info: "你可以将♣手牌当作【铁索连环】使用或重铸。", + gz_niepan: "涅槃", + gz_niepan_info: "限定技,当你处于濒死状态时,你可以弃置你区域内的所有牌并复原你的武将牌,然后摸三张牌并将体力回复至3点。", + + gz_shushen: "淑慎", + gz_shushen_info: "当你回复1点体力后,你可令一名其他角色摸一张牌(若其没有手牌则改为摸两张牌)。", +}; diff --git a/mode/guozhan/src/translate/voices/normal.js b/mode/guozhan/src/translate/voices/normal.js index b06ab20773..937e3140e3 100644 --- a/mode/guozhan/src/translate/voices/normal.js +++ b/mode/guozhan/src/translate/voices/normal.js @@ -21,4 +21,8 @@ export default { "#gz_zhugeliang:die": "将星陨落,天命难违……", "#gz_zhaoyun:die": "这,就是失败的滋味吗?", "#gz_machao:die": "(马蹄声远去……)", + "#gz_huangyueying:die": "亮……", + "#gz_huangzhong:die": "不得不服老啦~", + "#gz_weiyan:die": "谁敢杀我?!呃啊……", + "#gz_pangtong:die": "看来我命中注定将丧命于此……", }; From 1a9c1ca58e54245488d392d66d27d25819a1c376 Mon Sep 17 00:00:00 2001 From: Rintim Date: Fri, 25 Apr 2025 15:15:19 +0800 Subject: [PATCH 48/48] feat: rewrite some characters in new format of mode character. --- character/shenhua/translate.js | 8 - character/sp/skill.js | 2 +- mode/guozhan.js | 646 ++---------------- mode/guozhan/src/character/index.js | 1 + mode/guozhan/src/character/normal.js | 257 +++++++ mode/guozhan/src/character/sort.js | 5 + mode/guozhan/src/skill/character/normal.js | 588 +++++++++++++++- mode/guozhan/src/translate/character/index.js | 2 + .../guozhan/src/translate/character/normal.js | 2 + mode/guozhan/src/translate/character/sort.js | 5 + .../src/translate/skill/character/normal.js | 35 + 11 files changed, 921 insertions(+), 630 deletions(-) create mode 100644 mode/guozhan/src/character/sort.js create mode 100644 mode/guozhan/src/translate/character/sort.js diff --git a/character/shenhua/translate.js b/character/shenhua/translate.js index 30a8f200cd..baf99537e7 100644 --- a/character/shenhua/translate.js +++ b/character/shenhua/translate.js @@ -285,14 +285,6 @@ const translates = { re_huangzhong: "黄忠", re_weiyan: "魏延", - gz_xiahouyuan: "夏侯渊", - gz_huangzhong: "黄忠", - gz_weiyan: "魏延", - gz_xuhuang: "徐晃", - gz_pangde: "庞德", - gz_caoren: "曹仁", - gz_zhoutai: "周泰", - old_zhoutai: "周泰", old_caoren: "曹仁", xuhuang: "旧徐晃", diff --git a/character/sp/skill.js b/character/sp/skill.js index e90a1b6696..dda0447db8 100644 --- a/character/sp/skill.js +++ b/character/sp/skill.js @@ -13795,7 +13795,7 @@ const skills = { }) .setHiddenSkill(event.name).ai = function (target) { var num = 1; - if (target.hasSkill("gzxiaoji")) num += 2.5; + if (target.hasSkill("gz_xiaoji")) num += 2.5; if (target.isDamaged() && target.getEquip("baiyin")) num += 2.5; if (target.hasSkill("xuanlve")) num += 2; return num; diff --git a/mode/guozhan.js b/mode/guozhan.js index 2f3363b35e..6b2a0457a8 100644 --- a/mode/guozhan.js +++ b/mode/guozhan.js @@ -1,7 +1,7 @@ import { lib, game, ui, get, ai, _status } from "../noname.js"; import { start, startBefore, onreinit } from "./guozhan/src/main.js"; import { gamePatch, getPatch, contentPatch, playerPatch } from "./guozhan/src/patch/index.js"; -import { pack, intro } from "./guozhan/src/character/index.js"; +import { pack, intro, sort } from "./guozhan/src/character/index.js"; import * as info from "./guozhan/src/info/index.js"; import skill from "./guozhan/src/skill/index.js"; import translate from "./guozhan/src/translate/index.js"; @@ -31,7 +31,8 @@ export default () => { }, characterSort: { mode_guozhan: { - guozhan_default: ["gz_caocao", "gz_simayi", "gz_xiahoudun", "gz_zhangliao", "gz_xuzhu", "gz_guojia", "gz_zhenji", "gz_xiahouyuan", "gz_zhanghe", "gz_xuhuang", "gz_caoren", "gz_dianwei", "gz_xunyu", "gz_caopi", "gz_yuejin", "gz_liubei", "gz_guanyu", "gz_zhangfei", "gz_zhugeliang", "gz_zhaoyun", "gz_machao", "gz_huangyueying", "gz_huangzhong", "gz_weiyan", "gz_pangtong", "gz_sp_zhugeliang", "gz_liushan", "gz_menghuo", "gz_zhurong", "gz_ganfuren", "gz_sunquan", "gz_ganning", "gz_lvmeng", "gz_huanggai", "gz_zhouyu", "gz_daqiao", "gz_luxun", "gz_sunshangxiang", "gz_sunjian", "gz_xiaoqiao", "gz_re_taishici", "gz_zhoutai", "gz_re_lusu", "gz_zhangzhang", "gz_dingfeng", "gz_huatuo", "gz_lvbu", "gz_diaochan", "gz_re_yuanshao", "gz_yanwen", "gz_jiaxu", "gz_pangde", "gz_zhangjiao", "gz_caiwenji", "gz_mateng", "gz_kongrong", "gz_jiling", "gz_tianfeng", "gz_panfeng", "gz_zoushi"], + ...sort, + guozhan_zhen: ["gz_dengai", "gz_caohong", "gz_jiangfei", "gz_jiangwei", "gz_xusheng", "gz_jiangqing", "gz_hetaihou", "gz_yuji"], guozhan_shi: ["gz_re_lidian", "gz_zangba", "gz_madai", "gz_mifuren", "gz_sunce", "gz_chendong", "gz_sp_dongzhuo", "gz_zhangren"], guozhan_bian: ["gz_liqueguosi", "gz_zuoci", "gz_bianfuren", "gz_xunyou", "gz_lingtong", "gz_lvfan", "gz_masu", "gz_shamoke"], @@ -92,37 +93,7 @@ export default () => { gz_yuji: ["male", "qun", 3, ["qianhuan"], ["gzskin"]], - gz_sunquan: ["male", "wu", 4, ["gzzhiheng"]], - gz_ganning: ["male", "wu", 4, ["qixi"]], - gz_lvmeng: ["male", "wu", 4, ["new_keji", "new_mouduan"]], - gz_huanggai: ["male", "wu", 4, ["new_kurou"]], - gz_zhouyu: ["male", "wu", 3, ["reyingzi", "refanjian"], ["gzskin"]], - gz_daqiao: ["female", "wu", 3, ["guose", "liuli"]], - gz_luxun: ["male", "wu", 3, ["gzqianxun", "gzduoshi"], ["gzskin"]], - gz_sunshangxiang: ["female", "wu", 3, ["jieyin", "gzxiaoji"], ["gzskin"]], - gz_sunjian: ["male", "wu", 5, ["yinghun"], ["gzskin"]], - gz_xiaoqiao: ["female", "wu", 3, ["gztianxiang", "gzhongyan"], ["gzskin"]], - gz_re_taishici: ["male", "wu", 4, ["tianyi", "fakehanzhan"], ["tempname:re_taishici", "die:re_taishici"]], - gz_zhoutai: ["male", "wu", 4, ["buqu", "new_fenji"]], - gz_re_lusu: ["male", "wu", 3, ["haoshi", "dimeng"]], - gz_zhangzhang: ["male", "wu", 3, ["zhijian", "guzheng"]], - gz_dingfeng: ["male", "wu", 4, ["fakeduanbing", "fenxun"], ["gzskin"]], - - gz_huatuo: ["male", "qun", 3, ["new_chuli", "jijiu"]], - gz_lvbu: ["male", "qun", 5, ["gzwushuang"], ["gzskin"]], - gz_diaochan: ["female", "qun", 3, ["lijian", "biyue"], ["gzskin"]], - gz_re_yuanshao: ["male", "qun", 4, ["new_luanji"], ["gzskin"]], - gz_yanwen: ["male", "qun", 4, ["fakeshuangxiong"]], - gz_jiaxu: ["male", "qun", 3, ["wansha", "luanwu", "gzweimu"], ["gzskin"]], - gz_pangde: ["male", "qun", 4, ["mashu", "jianchu"]], - gz_zhangjiao: ["male", "qun", 3, ["leiji", "guidao"]], - gz_caiwenji: ["female", "qun", 3, ["beige", "gzduanchang"]], - gz_mateng: ["male", "qun", 4, ["mashu", "xiongyi"]], - gz_kongrong: ["male", "qun", 3, ["gzmingshi", "lirang"]], - gz_jiling: ["male", "qun", 4, ["shuangren"]], - gz_tianfeng: ["male", "qun", 3, ["sijian", "gzsuishi"]], - gz_panfeng: ["male", "qun", 4, ["gzkuangfu"], ["gzskin"]], - gz_zoushi: ["female", "qun", 3, ["huoshui", "new_qingcheng"]], + gz_dengai: ["male", "wei", 4, ["tuntian", "ziliang", "gzjixi"], ["gzskin"]], gz_caohong: ["male", "wei", 4, ["fakehuyuan", "heyi"], ["gzskin"]], @@ -965,18 +936,7 @@ export default () => { }, }, //陆逊 - gzduoshi: { - audio: "duoshi", - trigger: { player: "phaseUseBegin" }, - filter(event, player) { - return player.hasUseTarget(new lib.element.VCard({ name: "yiyi" })); - }, - direct: true, - preHidden: true, - content() { - player.chooseUseTarget(get.prompt2(event.name), new lib.element.VCard({ name: "yiyi" }), false).set("hiddenSkill", event.name).logSkill = event.name; - }, - }, + //臧霸 gzhengjiang: { audio: "hengjiang", @@ -1082,36 +1042,7 @@ export default () => { }, }, //官盗2023 - fakeduanbing: { - audio: "duanbing", - inherit: "reduanbing", - preHidden: ["fakeduanbing_sha"], - group: ["fakeduanbing", "fakeduanbing_sha"], - subSkill: { - sha: { - audio: "duanbing", - trigger: { player: "useCardToPlayered" }, - filter(event, player) { - return event.card.name == "sha" && !event.getParent().directHit.includes(event.target) && event.targets.length == 1; - }, - forced: true, - logTarget: "target", - content() { - var id = trigger.target.playerid; - var map = trigger.getParent().customArgs; - if (!map[id]) map[id] = {}; - if (typeof map[id].shanRequired == "number") map[id].shanRequired++; - else map[id].shanRequired = 2; - }, - ai: { - directHit_ai: true, - skillTagFilter(player, tag, arg) { - if (!arg || !arg.card || !arg.target || arg.card.name != "sha" || arg.target.countCards("h", "shan") > 1 || get.distance(player, arg.target) > 1) return false; - }, - }, - }, - }, - }, + fakeduoshi: { audio: "duoshi", global: "fakeduoshi_global", @@ -1208,94 +1139,8 @@ export default () => { }, }, }, - fakehanzhan: { - audio: "hanzhan", - trigger: { - player: ["chooseToCompareAfter", "compareMultipleAfter"], - target: ["chooseToCompareAfter", "compareMultipleAfter"], - }, - filter(event, player) { - if (event.preserve) return false; - const list = [event.player, event.target]; - const targets = list.slice().filter(i => (event.num1 - event.num2) * get.sgn(0.5 - list.indexOf(i)) <= 0); - return targets.some(i => { - const target = list[1 - list.indexOf(i)]; - return target.hasCard(card => { - return lib.filter.canBeGained(card, i, target); - }, "e"); - }); - }, - async cost(event, trigger, player) { - let users = []; - const list = [trigger.player, trigger.target]; - let targets = list.slice().filter(i => (trigger.num1 - trigger.num2) * get.sgn(0.5 - list.indexOf(i)) <= 0); - targets = targets - .filter(i => { - const target = list[1 - list.indexOf(i)]; - return target.hasCard(card => { - return lib.filter.canBeGained(card, i, target); - }, "e"); - }) - .sortBySeat(player); - for (const i of targets) { - const aim = list[1 - list.indexOf(i)]; - const { - result: { bool }, - } = await i.chooseBool(get.prompt("fakehanzhan"), "获得" + get.translation(aim) + "装备区的一张牌").set( - "choice", - aim.hasCard(card => { - return get.value(card, aim) * get.attitude(i, aim) < 0; - }, "e") - ); - if (bool) users.push(i); - } - event.result = { bool: Boolean(users.length), targets: users }; - }, - logLine: false, - async content(event, trigger, player) { - const list = [trigger.player, trigger.target]; - let targets = list.slice().filter(i => (trigger.num1 - trigger.num2) * get.sgn(0.5 - list.indexOf(i)) <= 0); - targets = targets - .filter(i => { - const target = list[1 - list.indexOf(i)]; - return target.hasCard(card => { - return lib.filter.canBeGained(card, i, target); - }, "e"); - }) - .sortBySeat(player); - for (const i of targets) { - const aim = list[1 - list.indexOf(i)]; - i.line(aim, "green"); - await i.gainPlayerCard(aim, "e", true); - } - }, - }, - fakeshuangxiong: { - audio: "shuangxiong", - subfrequent: ["tiandu"], - group: ["fakeshuangxiong_effect", "fakeshuangxiong_tiandu"], - subSkill: { - effect: { - audio: "shuangxiong1", - inherit: "shuangxiong1", - content() { - player.judge().set("callback", get.info("fakeshuangxiong").subSkill.effect.callback); - trigger.changeToZero(); - }, - callback() { - player.addTempSkill("shuangxiong2"); - player.markAuto("shuangxiong2", [event.judgeResult.color]); - }, - }, - tiandu: { - audio: "shuangxiong", - inherit: "tiandu", - filter(event, player) { - return _status.currentPhase == player && get.info("tiandu").filter(event, player); - }, - }, - }, - }, + + fakeyicheng: { audio: "yicheng", inherit: "yicheng", @@ -5319,7 +5164,7 @@ export default () => { next.set("ai", target => { let num = 0; - if (target.hasSkill("gzxiaoji")) { + if (target.hasSkill("gz_xiaoji")) { num += 2.5; } if (target.isDamaged() && target.getEquip("baiyin")) { @@ -5410,7 +5255,7 @@ export default () => { next.set("ai", target => { let num = 0; - if (target.hasSkill("gzxiaoji")) { + if (target.hasSkill("gz_xiaoji")) { num += 2.5; } if (target.isDamaged() && target.getEquip("baiyin")) { @@ -7865,7 +7710,7 @@ export default () => { ("step 1"); game.broadcastAll("closeDialog", event.videoId); var list1 = ["wei", "shu", "wu", "qun", "jin"], - list2 = ["gzqice", "tiaoxin", "gzzhiheng", "new_chuli", "gzsanchen"]; + list2 = ["gzqice", "tiaoxin", "gz_zhiheng", "new_chuli", "gzsanchen"]; var skills = []; for (var i = 0; i < list1.length; i++) { if (event.groups.includes(list1[i])) skills.push(list2[i]); @@ -7878,7 +7723,7 @@ export default () => { player.addTempSkills(skill); player.popup(skill); }, - derivation: ["gzqice", "tiaoxin", "gzzhiheng", "new_chuli", "gzsanchen"], + derivation: ["gzqice", "tiaoxin", "gz_zhiheng", "new_chuli", "gzsanchen"], ai: { order: 10, result: { player: 1 }, @@ -8396,104 +8241,8 @@ export default () => { }, }, //小乔 - gztianxiang: { - audio: "tianxiang", - audioname: ["daxiaoqiao", "re_xiaoqiao", "ol_xiaoqiao"], - trigger: { player: "damageBegin4" }, - preHidden: true, - usable: 1, - filter(event, player) { - return ( - player.countCards("h", card => { - return _status.connectMode || (get.suit(card, player) == "heart" && lib.filter.cardDiscardable(card, player)); - }) > 0 && event.num > 0 - ); - }, - async cost(event, trigger, player) { - event.result = await player - .chooseCardTarget({ - filterCard(card, player) { - return get.suit(card) == "heart" && lib.filter.cardDiscardable(card, player); - }, - filterTarget: lib.filter.notMe, - ai1(card) { - return 10 - get.value(card); - }, - ai2(target) { - const att = get.attitude(get.player(), target); - const trigger = get.event().getTrigger(); - let da = 0; - if (get.player().hp == 1) { - da = 10; - } - const eff = get.damageEffect(target, trigger.source, target); - if (att == 0) return 0.1 + da; - if (eff >= 0 && att > 0) { - return att + da; - } - if (att > 0 && target.hp > 1) { - if (target.maxHp - target.hp >= 3) return att * 1.1 + da; - if (target.maxHp - target.hp >= 2) return att * 0.9 + da; - } - return -att + da; - }, - prompt: get.prompt(event.skill), - prompt2: lib.translate[`${event.skill}_info`], - }) - .setHiddenSkill(event.skill) - .forResult(); - }, - async content(event, trigger, player) { - const { - cards, - targets: [target], - } = event; - trigger.cancel(); - await player.discard(cards); - const { result } = await player - .chooseControlList(true, (event, player) => get.event().index, [`令${get.translation(target)}受到伤害来源对其造成的1点伤害,然后摸X张牌(X为其已损失体力值且至多为5)`, `令${get.translation(target)}失去1点体力,然后获得${get.translation(cards)}`]) - .set( - "index", - (() => { - let att = get.attitude(player, target); - if (target.hasSkillTag("maihp")) att = -att; - return att > 0 ? 0 : 1; - })() - ); - if (typeof result.index != "number") return; - if (result.index == 0) { - await target.damage(trigger.source || "nosource", "nocard"); - if (target.getDamagedHp()) await target.draw(Math.min(5, target.getDamagedHp())); - } else { - await target.loseHp(); - if (cards[0].isInPile()) await target.gain(cards, "gain2"); - } - }, - ai: { - maixie_defend: true, - effect: { - target(card, player, target) { - if (player.hasSkillTag("jueqing", false, target)) return; - if (get.tag(card, "damage") && target.countCards("he") > 1) return 0.7; - }, - }, - }, - }, - gzhongyan: { - mod: { - suit(card, suit) { - if (suit == "spade") return "heart"; - }, - maxHandcard(player, num) { - if ( - player.hasCard(function (card) { - return get.suit(card, player) == "heart"; - }, "e") - ) - return num + 1; - }, - }, - }, + + //潘凤 gzkuangfu: { @@ -8540,55 +8289,7 @@ export default () => { }, }, //吕布 - gzwushuang: { - audio: "wushuang", - audioname2: { gz_lvlingqi: "wushuang_lvlingqi" }, - forced: true, - locked: true, - group: ["wushuang1", "wushuang2"], - preHidden: ["wushuang1", "wushuang2", "gzwushuang"], - trigger: { player: "useCard1" }, - direct: true, - filter(event, player) { - if (event.card.name != "juedou" || !event.card.isCard) return false; - if (event.targets) { - if ( - game.hasPlayer(function (current) { - return !event.targets.includes(current) && lib.filter.targetEnabled2(event.card, player, current); - }) - ) { - return true; - } - } - return false; - }, - content() { - "step 0"; - var num = game.countPlayer(function (current) { - return !trigger.targets.includes(current) && lib.filter.targetEnabled2(trigger.card, player, current); - }); - player - .chooseTarget("无双:是否为" + get.translation(trigger.card) + "增加" + (num > 1 ? "至多两个" : "一个") + "目标?", [1, Math.min(2, num)], function (card, player, target) { - var trigger = _status.event.getTrigger(); - var card = trigger.card; - return !trigger.targets.includes(target) && lib.filter.targetEnabled2(card, player, target); - }) - .set("ai", function (target) { - var player = _status.event.player; - var card = _status.event.getTrigger().card; - return get.effect(target, card, player, player); - }) - .setHiddenSkill("gzwushuang"); - ("step 1"); - if (result.bool) { - if (player != game.me && !player.isOnline()) game.delayx(); - } else event.finish(); - ("step 2"); - var targets = result.targets.sortBySeat(); - player.logSkill("gzwushuang", targets); - trigger.targets.addArray(targets); - }, - }, + //吕玲绮 gzshenwei: { audio: "llqshenwei", @@ -8616,7 +8317,7 @@ export default () => { usable: 1, filter(event, player) { return ( - !player.hasSkill("gzwushuang") && + !player.hasSkill("gz_wushuang") && player.hasCard(function (card) { return get.type2(card, player) == "trick"; }, "h") @@ -8626,9 +8327,9 @@ export default () => { return get.type2(card, player) == "trick"; }, content() { - player.addTempSkill("gzwushuang", "phaseUseEnd"); + player.addTempSkill("gz_wushuang", "phaseUseEnd"); }, - derivation: "gzwushuang", + derivation: "gz_wushuang", }, wushuang_lvlingqi: { audio: 2 }, //荀谌 @@ -14503,102 +14204,7 @@ export default () => { expose: 0.1, }, }, - new_luanji: { - audio: "luanji", - enable: "phaseUse", - viewAs: { - name: "wanjian", - }, - filterCard(card, player) { - if (!player.storage.new_luanji) return true; - return !player.storage.new_luanji.includes(get.suit(card)); - }, - selectCard: 2, - position: "hs", - filter(event, player) { - return ( - player.countCards("hs", function (card) { - return !player.storage.new_luanji || !player.storage.new_luanji.includes(get.suit(card)); - }) > 1 - ); - }, - check(card) { - var player = _status.event.player; - var targets = game.filterPlayer(function (current) { - return player.canUse("wanjian", current); - }); - var num = 0; - for (var i = 0; i < targets.length; i++) { - var eff = get.sgn(get.effect(targets[i], { name: "wanjian" }, player, player)); - if (targets[i].hp == 1) { - eff *= 1.5; - } - num += eff; - } - if (!player.needsToDiscard(-1)) { - if (targets.length >= 7) { - if (num < 2) return 0; - } else if (targets.length >= 5) { - if (num < 1.5) return 0; - } - } - return 6 - get.value(card); - }, - group: ["new_luanji_count", "new_luanji_reset", "new_luanji_respond"], - subSkill: { - reset: { - trigger: { - player: "phaseAfter", - }, - silent: true, - filter(event, player) { - return player.storage.new_luanji ? true : false; - }, - content() { - delete player.storage.new_luanji; - }, - sub: true, - forced: true, - popup: false, - }, - count: { - trigger: { - player: "useCard", - }, - silent: true, - filter(event) { - return event.skill == "new_luanji"; - }, - content() { - if (!player.storage.new_luanji) { - player.storage.new_luanji = []; - } - for (var i = 0; i < trigger.cards.length; i++) { - player.storage.new_luanji.add(get.suit(trigger.cards[i])); - } - }, - sub: true, - forced: true, - popup: false, - }, - respond: { - trigger: { - global: "respond", - }, - silent: true, - filter(event) { - if (event.player.isUnseen()) return false; - return event.getParent(2).skill == "new_luanji" && event.player.isFriendOf(_status.currentPhase); - }, - content() { - trigger.player.draw(); - }, - sub: true, - forced: true, - popup: false, - }, - }, - }, + new_qingcheng: { audio: "qingcheng", enable: "phaseUse", @@ -14695,29 +14301,7 @@ export default () => { }, }, }, - new_keji: { - audio: "keji", - forced: true, - trigger: { - player: "phaseDiscardBegin", - }, - filter(event, player) { - var list = []; - player.getHistory("useCard", function (evt) { - if (evt.isPhaseUsing(player)) { - var color = get.color(evt.card); - if (color != "nocolor") list.add(color); - } - }); - return list.length <= 1; - }, - check(event, player) { - return player.needsToDiscard(); - }, - content() { - player.addTempSkill("keji_add", "phaseAfter"); - }, - }, + keji_add: { charlotte: true, mod: { @@ -14726,56 +14310,9 @@ export default () => { }, }, }, - new_mouduan: { - trigger: { - player: "phaseJieshuBegin", - }, - //priority:2, - audio: "botu", - filter(event, player) { - var history = player.getHistory("useCard"); - var suits = []; - var types = []; - for (var i = 0; i < history.length; i++) { - var suit = get.suit(history[i].card); - if (suit) suits.add(suit); - types.add(get.type(history[i].card)); - } - return suits.length >= 4 || types.length >= 3; - }, - check(event, player) { - return player.canMoveCard(true); - }, - content() { - player.moveCard(); - }, - }, + - new_kurou: { - audio: "rekurou", - enable: "phaseUse", - usable: 1, - filterCard: true, - check(card) { - return 8 - get.value(card); - }, - position: "he", - content() { - player.loseHp(); - player.draw(3); - player.addTempSkill("kurou_effect", "phaseAfter"); - }, - ai: { - order: 8, - result: { - player(player) { - if (player.hp <= 2) return player.countCards("h") == 0 ? 1 : 0; - if (player.countCards("h", { name: "sha", color: "red" })) return 1; - return player.countCards("h") <= player.hp ? 1 : 0; - }, - }, - }, - }, + kurou_effect: { mod: { cardUsable(card, player, num) { @@ -15651,7 +15188,7 @@ export default () => { enable: "phaseUse", usable: 1, audio: 2, - derivation: "gzzhiheng", + derivation: "gz_zhiheng", filterCard: true, check(card) { if (get.type(card) == "equip") return 0; @@ -15703,7 +15240,7 @@ export default () => { if (list.length) { player.gain(list, "gain2"); if (list.length >= 3 && player.hasStockSkill("lianzi")) { - player.changeSkills(["gzzhiheng"], ["lianzi"]); + player.changeSkills(["gz_zhiheng"], ["lianzi"]); } } }, @@ -15878,7 +15415,7 @@ export default () => { if (event.num >= 1 && !(player.hasSkill("reyingzi") || player.hasSkill("jiahe_reyingzi"))) list.push("reyingzi"); if (event.num >= 2 && !(player.hasSkill("haoshi") || player.hasSkill("jiahe_haoshi"))) list.push("haoshi"); if (event.num >= 3 && !(player.hasSkill("shelie") || player.hasSkill("jiahe_shelie"))) list.push("shelie"); - if (event.num >= 4 && !(player.hasSkill("gzduoshi") || player.hasSkill("jiahe_duoshi"))) list.push("gzduoshi"); + if (event.num >= 4 && !(player.hasSkill("gz_duoshi") || player.hasSkill("jiahe_duoshi"))) list.push("gz_duoshi"); if (!list.length) { event.finish(); return; @@ -15913,8 +15450,8 @@ export default () => { if (controls.includes("reyingzi")) { return "reyingzi"; } - if (controls.includes("gzduoshi")) { - return "gzduoshi"; + if (controls.includes("gz_duoshi")) { + return "gz_duoshi"; } return controls.randomGet(); }); @@ -15924,15 +15461,15 @@ export default () => { reyingzi: "jiahe_reyingzi", haoshi: "jiahe_haoshi", shelie: "jiahe_shelie", - gzduoshi: "jiahe_duoshi", + gz_duoshi: "jiahe_duoshi", }; var skills = map[result.control]; player.addTempSkills(skills); /* 语音修复 - if (skills == "gzduoshi") { + if (skills == "gz_duoshi") { game.broadcastAll(function (player) { - let info = lib.skill["gzduoshi"]; + let info = lib.skill["gz_duoshi"]; if (!info.audioname2) info.audioname2 = {}; info.audioname2[player.name1] = "jiahe_duoshi"; info.audioname2[player.name2] = "jiahe_duoshi"; @@ -15968,7 +15505,7 @@ export default () => { }, jiahe_duoshi: { audio: 2, - inherit: "gzduoshi", + inherit: "gz_duoshi", }, yuanjiangfenghuotu: { audio: 4, @@ -17714,38 +17251,7 @@ export default () => { }, }, }, - gzqianxun: { - audio: "qianxun", - trigger: { - target: "useCardToTarget", - player: "addJudgeBefore", - }, - forced: true, - preHidden: true, - priority: 15, - check(event, player) { - return event.name == "addJudge" || get.effect(event.target, event.card, event.player, player) < 0; - }, - filter(event, player) { - return event.card.name == (event.name == "addJudge" ? "lebu" : "shunshou"); - }, - content() { - if (trigger.name == "addJudge") { - trigger.cancel(); - var owner = get.owner(trigger.card); - if (owner && owner.getCards("hej").includes(trigger.card)) owner.lose(trigger.card, ui.discardPile); - else game.cardsDiscard(trigger.card); - game.log(trigger.card, "进入了弃牌堆"); - } else trigger.getParent().targets.remove(player); - }, - ai: { - effect: { - target(card, player, target, current) { - if (card.name == "shunshou" || card.name == "lebu") return "zeroplayertarget"; - }, - }, - }, - }, + gzkongcheng: { audio: "kongcheng", trigger: { target: "useCardToTarget" }, @@ -17768,19 +17274,7 @@ export default () => { }, }, }, - gzxiaoji: { - inherit: "xiaoji", - audio: "xiaoji", - preHidden: true, - getIndex(event, player) { - const evt = event.getl(player); - if (evt && evt.player === player && evt.es && evt.es.length) return 1; - return false; - }, - content() { - player.draw(player == _status.currentPhase ? 1 : 3); - }, - }, + gzrende: { audio: "rende", group: ["gzrende1"], @@ -17871,32 +17365,6 @@ export default () => { player.storage.gzrende = 0; }, }, - gzzhiheng: { - inherit: "zhiheng", - audio: "zhiheng", - selectCard() { - var player = _status.event.player; - var range1 = [1, player.maxHp]; - if (player.hasSkill("dinglanyemingzhu_skill")) { - for (var i = 0; i < ui.selected.cards.length; i++) { - if (ui.selected.cards[i] == player.getEquip("dinglanyemingzhu")) return range1; - } - return [1, Infinity]; - } - return range1; - }, - filterCard(card, player) { - if (ui.selected.cards.length < player.maxHp || !player.hasSkill("dinglanyemingzhu_skill")) return true; - return card != player.getEquip("dinglanyemingzhu"); - }, - complexCard: true, - complexSelect: true, - prompt() { - var player = _status.event.player; - if (player.hasSkill("dinglanyemingzhu_skill")) return "出牌阶段限一次,你可以弃置任意张牌,然后摸等量的牌"; - return "出牌阶段限一次,你可以弃置至多X张牌(X为你的体力上限),然后摸等量的牌"; - }, - }, duoshi: { enable: "chooseToUse", viewAs: { name: "yiyi" }, @@ -18344,15 +17812,12 @@ export default () => { ...translate, gz_miheng: "祢衡", - gzwushuang: "无双", - gzwushuang_info: "锁定技。①当你使用【杀】指定一名角色为目标后,其需使用两张【闪】才能抵消;②当你使用【决斗】指定其他角色为目标后,或成为其他角色使用【决斗】的目标后,其每次响应需打出两张【杀】。③当你使用非转化的【决斗】选择目标后,你可为此【决斗】增加两个目标。", + gzkuangfu: "狂斧", gzkuangfu_info: "出牌阶段限一次。当你使用【杀】指定目标后,你可获得目标角色装备区内的一张牌。然后若此【杀】未造成伤害,则你弃置两张手牌。", - gzhongyan: "红颜", - gzhongyan_info: "锁定技。①你区域内的黑桃牌和黑桃判定牌的花色视为红桃。②若你的装备区内有红桃牌,则你的手牌上限+1。", - gztianxiang: "天香", - gztianxiang_info: "每回合限一次。当你受到伤害时,你可以弃置一张红桃手牌,防止此次伤害并选择一名其他角色,然后你选择一项:1.令其受到伤害来源对其造成的1点伤害,然后摸X张牌(X为其已损失体力值且至多为5);2.令其失去1点体力,然后获得你弃置的牌。", + + gzqiangxi: "强袭", gzqiangxi_info: "出牌阶段限一次,你可以弃置一张武器牌或失去1点体力,然后对一名其他角色造成1点伤害。", @@ -18580,24 +18045,19 @@ export default () => { new_shushen: "淑慎", new_shushen_info: "当你回复1点体力后,你可令一名其他角色摸一张牌。", - new_luanji: "乱击", - new_luanji_info: "你可以将两张与你本回合以此法转化的花色均不相同的手牌当【万箭齐发】使用。当一名与你势力相同的角色因响应此牌而打出【闪】时,该角色摸一张牌。", + new_qingcheng: "倾城", new_qingcheng_info: "出牌阶段,你可以弃置一张黑色牌并选择一名武将牌均明置的其他角色,然后你暗置其一张武将牌。若你以此法弃置的牌为装备牌,则你可以暗置另一名武将牌均明置的角色的一张武将牌。", huoshui: "祸水", huoshui_info: "锁定技。你的回合内,①其他角色不能明置武将牌。②当你使用【杀】或【万箭齐发】指定目标后,若目标角色与你势力不同且有暗置武将牌,则其不能使用或出【闪】直到此牌结算结束。", - new_keji: "克己", - new_keji_info: "锁定技,若你没有在出牌阶段内使用过颜色不同的牌,则你本回合的手牌上限+4。", keji_add: "克己", keji_add_info: "", - new_mouduan: "谋断", - new_mouduan_info: "结束阶段,若你于本回合内使用过四种花色或三种类别的牌,则你可以移动场上的一张牌。", + fz_new_longdan: "龙胆", fz_new_longdan_info: "你可以将【杀】当【闪】,【闪】当【杀】使用或打出。当你发动〖龙胆〗使用的【杀】被【闪】抵消时,你可以对另一名角色造成1点伤害;当你发动〖龙胆〗使用的【闪】抵消了【杀】时,你可以令一名其他角色回复1点体力(不能是【杀】的使用者)。", - new_kurou: "苦肉", - new_kurou_info: "出牌阶段限一次,你可以弃置一张牌,然后失去1点体力并摸三张牌,本回合使用【杀】的次数上限+1。", + kurou_effect: "苦肉", kurou_effect_info: "", new_chuli: "除疠", @@ -18764,16 +18224,12 @@ export default () => { gzduanchang_info: "锁定技,当你死亡时,你令杀死你的角色失去一张武将牌上的所有技能。", gzweimu: "帷幕", gzweimu_info: "锁定技,当你成为黑色普通锦囊牌的目标时,或有黑色延时锦囊牌进入你的判定区时,取消之。", - gzqianxun: "谦逊", - gzqianxun_info: "锁定技,当你成为【顺手牵羊】的目标时,或有【乐不思蜀】进入你的判定区时,取消之。", + gzkongcheng: "空城", gzkongcheng_info: "锁定技,当你成为【杀】或【决斗】的目标时,若你没有手牌,则取消之。", - gzxiaoji: "枭姬", - gzxiaoji_info: "当你失去装备区里的牌后,你可以摸一张牌。若你不是当前回合角色,则你改为摸三张牌。", + gzrende: "仁德", gzrende_info: "出牌阶段,你可以将任意张手牌交给其他角色,然后若你于此阶段内给出第三张“仁德”牌时,你回复1点体力。", - gzzhiheng: "制衡", - gzzhiheng_info: "出牌阶段限一次,你可以弃置至多X张牌(X为你的体力上限),然后摸等量的牌。", duoshi: "度势", duoshi_info: "出牌阶段限四次,你可以将一张红色手牌当做【以逸待劳】使用。", gzxiaoguo: "骁果", @@ -18909,14 +18365,9 @@ export default () => { ushio_xilv_info: "锁定技,此武将牌可作为任意单势力武将牌的副将。当你进行判定后,你令你的手牌上限+1直至你的下个结束阶段。", //官盗2023 - fakeduanbing: "短兵", - fakeduanbing_info: "①你使用【杀】可以额外指定一名距离为1或以内的目标。②当你使用【杀】指定唯一目标后,你令目标角色需要额外使用一张【闪】响应此【杀】。", + fakeduoshi: "度势", fakeduoshi_info: "每轮限一次,友方角色可以将一张红色手牌当作【以逸待劳】使用,然后若你为小势力角色,你可以令一名友方角色将X张手牌当作不可被响应的【火烧连营】使用(X为此【以逸待劳】指定的目标数)。", - fakehanzhan: "酣战", - fakehanzhan_info: "有你参与的拼点事件结束后,没赢的角色可以获得对方装备区的一张牌。", - fakeshuangxiong: "双雄", - fakeshuangxiong_info: "①摸牌阶段,你可以放弃摸牌并进行判定,本回合你可以将一张与此牌颜色不同的手牌当作【决斗】使用。②当你的判定牌于回合内生效后,你获得此牌。", fakeyicheng: "疑城", fakeyicheng_info: "与你势力相同的角色成为【杀】的目标后,你可以令其摸一张牌,然后其可以使用一张装备牌,其于此回合结束时弃置X张牌(X为你本回合对其发动此技能的次数)。", fakefenming: "奋命", @@ -19072,14 +18523,12 @@ export default () => { gzyicheng_new: "疑城", gzyicheng_new_info: "与你势力相同的角色使用【杀】指定第一个目标后或成为【杀】的目标后,你可以令其摸一张牌,然后其弃置一张牌。", - gzduoshi: "度势", - gzduoshi_info: "出牌阶段开始时,你可以视为使用【以逸待劳】。", + gzhengjiang: "横江", gzhengjiang_info: "当你受到伤害后,你可以令当前回合角色本回合的手牌上限-X(X为其装备区牌数且至少为1)。然后其本回合弃牌阶段结束时,若其未于此阶段弃牌,则你将手牌摸至体力上限。", gzchengshang: "承赏", gzchengshang_info: "每回合限一次,当你使用指定了目标的牌结算完毕后,若你未因此牌造成过伤害,则你可以令其中一名目标角色交给你一张牌,若此牌和你使用的牌的花色和点数均相同,则你失去此技能。", - guozhan_default: "国战标准", guozhan_zhen: "君临天下·阵", guozhan_shi: "君临天下·势", guozhan_bian: "君临天下·变", @@ -19199,15 +18648,9 @@ export default () => { "#qianhuan1": "幻变迷踪,虽飞鸟亦难觅踪迹。", "#qianhuan2": "幻化于阴阳,藏匿于乾坤。", "#gz_yuji:die": "幻化之物,终是算不得真呐……", - "#liuli1": "交给你了~", - "#liuli2": "你来嘛~", "#duoshi1": "国之大计,审势为先。", "#duoshi2": "依今日之大势,当行此计。", "#gz_luxun:die": "还以为我已经不再年轻……", - "#guzheng2": "固国安邦,居当如是!", - "#lijian1": "嗯呵呵~~呵呵~~", - "#biyue1": "失礼了~", - "#biyue2": "羡慕吧~", "#jianchu1": "休想全身而退!", "#jianchu2": "杀到你丢盔弃甲!", "#gz_mateng:die": "儿子,为爹报仇啊!", @@ -19235,8 +18678,6 @@ export default () => { "#gz_xusheng:die": "可怜一身胆略,尽随一抔黄土……", "#yingyang1": "此战,我必取胜!", "#yingyang2": "相斗之趣,吾常胜之。", - "#yinghun_sunce1": "父亲,助我背水一战!", - "#yinghun_sunce2": "孙氏英烈,庇佑江东!", "#baoling1": "待吾大开杀戒,哈哈哈哈!", "#baoling2": "大丈夫,岂能妇人之仁?", "#zhangwu1": "遁剑归一,有凤来仪。", @@ -19322,7 +18763,6 @@ export default () => { "#gz_lukang:die": "抗仅以君子之交待叔子,未有半分背国之念啊!", "#gzfudi1": "弃暗投明,为明公计!", "#gzfudi2": "绣虽有降心,奈何贵营难容。", - "#drlt_congjian1": "听君谏言,去危亡,保宗祀!", "#jianan": "设使天下无孤,不知几人称帝,几人称王?", "#wuziliangjiangdao1": "行为军锋,还为后拒!", "#wuziliangjiangdao2": "国之良将,五子为先。", diff --git a/mode/guozhan/src/character/index.js b/mode/guozhan/src/character/index.js index 134aaf22e6..d1b79599e6 100644 --- a/mode/guozhan/src/character/index.js +++ b/mode/guozhan/src/character/index.js @@ -135,3 +135,4 @@ export const pack = { }; export { default as intro } from "./intro.js"; +export { default as sort } from "./sort.js"; diff --git a/mode/guozhan/src/character/normal.js b/mode/guozhan/src/character/normal.js index 34959ff104..c356e1d43a 100644 --- a/mode/guozhan/src/character/normal.js +++ b/mode/guozhan/src/character/normal.js @@ -247,6 +247,261 @@ export default { skills: ["gz_shushen", "shenzhi"], hasSkinInGuozhan: true, }), + + gz_sunquan: new Character({ + sex: "male", + group: "wu", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_zhiheng"], + }), + gz_ganning: new Character({ + sex: "male", + group: "wu", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["qixi"], + }), + gz_lvmeng: new Character({ + sex: "male", + group: "wu", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_keji", "gz_mouduan"], + }), + gz_huanggai: new Character({ + sex: "male", + group: "wu", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_kurou"], + }), + gz_zhouyu: new Character({ + sex: "male", + group: "wu", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["reyingzi", "refanjian"], + hasSkinInGuozhan: true, + }), + gz_daqiao: new Character({ + sex: "female", + group: "wu", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["guose", "liuli"], + }), + gz_luxun: new Character({ + sex: "male", + group: "wu", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["gz_qianxun", "gz_duoshi"], + hasSkinInGuozhan: true, + }), + gz_sunshangxiang: new Character({ + sex: "female", + group: "wu", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["jieyin", "gz_xiaoji"], + hasSkinInGuozhan: true, + }), + gz_sunjian: new Character({ + sex: "male", + group: "wu", + hp: 5, + maxHp: 5, + hujia: 0, + skills: ["yinghun"], + hasSkinInGuozhan: true, + }), + gz_xiaoqiao: new Character({ + sex: "female", + group: "wu", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["gz_tianxiang", "gz_hongyan"], + hasSkinInGuozhan: true, + }), + gz_re_taishici: new Character({ + sex: "male", + group: "wu", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["tianyi", "gz_hanzhan"], + tempname: ["re_taishici"], + dieAudios: ["re_taishici"], + }), + gz_zhoutai: new Character({ + sex: "male", + group: "wu", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["buqu", "new_fenji"], + }), + gz_re_lusu: new Character({ + sex: "male", + group: "wu", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["haoshi", "dimeng"], + }), + gz_zhangzhang: new Character({ + sex: "male", + group: "wu", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["zhijian", "guzheng"], + }), + gz_dingfeng: new Character({ + sex: "male", + group: "wu", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_duanbing", "fenxun"], + hasSkinInGuozhan: true, + }), + + gz_huatuo: new Character({ + sex: "male", + group: "qun", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["new_chuli", "jijiu"], + }), + gz_lvbu: new Character({ + sex: "male", + group: "qun", + hp: 5, + maxHp: 5, + hujia: 0, + skills: ["gz_wushuang"], + hasSkinInGuozhan: true, + }), + gz_diaochan: new Character({ + sex: "female", + group: "qun", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["lijian", "biyue"], + hasSkinInGuozhan: true, + }), + gz_re_yuanshao: new Character({ + sex: "male", + group: "qun", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_luanji"], + hasSkinInGuozhan: true, + }), + gz_yanwen: new Character({ + sex: "male", + group: "qun", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gz_shuangxiong"], + }), + gz_jiaxu: new Character({ + sex: "male", + group: "qun", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["wansha", "luanwu", "gzweimu"], + hasSkinInGuozhan: true, + }), + gz_pangde: new Character({ + sex: "male", + group: "qun", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["mashu", "jianchu"], + }), + gz_zhangjiao: new Character({ + sex: "male", + group: "qun", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["leiji", "guidao"], + }), + gz_caiwenji: new Character({ + sex: "female", + group: "qun", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["beige", "gzduanchang"], + }), + gz_mateng: new Character({ + sex: "male", + group: "qun", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["mashu", "xiongyi"], + }), + gz_kongrong: new Character({ + sex: "male", + group: "qun", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["gzmingshi", "lirang"], + }), + gz_jiling: new Character({ + sex: "male", + group: "qun", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["shuangren"], + }), + gz_tianfeng: new Character({ + sex: "male", + group: "qun", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["sijian", "gzsuishi"], + }), + gz_panfeng: new Character({ + sex: "male", + group: "qun", + hp: 4, + maxHp: 4, + hujia: 0, + skills: ["gzkuangfu"], + hasSkinInGuozhan: true, + }), + gz_zoushi: new Character({ + sex: "female", + group: "qun", + hp: 3, + maxHp: 3, + hujia: 0, + skills: ["huoshui", "new_qingcheng"], + }), }; export const intro = { @@ -277,3 +532,5 @@ export const intro = { gz_weiyan: "字文长,义阳人。三国时期蜀汉名将,诸葛亮死后,魏延因被陷害谋反而遭杨仪一党所杀。", gz_pangtong: "庞统,字士元,襄阳(治今湖北襄阳)人。三国时刘备帐下谋士,官拜军师中郎将。才智与诸葛亮齐名,人称“凤雏”。在进围雒县时,统率众攻城,不幸被流矢击中去世,时年三十六岁。追赐统为关内侯,谥曰靖侯。庞统死后,葬于落凤庞统墓坡。", }; + +export const sort = "guozhan_default"; diff --git a/mode/guozhan/src/character/sort.js b/mode/guozhan/src/character/sort.js new file mode 100644 index 0000000000..cce2cb1d6b --- /dev/null +++ b/mode/guozhan/src/character/sort.js @@ -0,0 +1,5 @@ +import normal, { sort as normalSort } from "./normal.js"; + +export default { + [normalSort]: Object.keys(normal), +}; diff --git a/mode/guozhan/src/skill/character/normal.js b/mode/guozhan/src/skill/character/normal.js index bcd233abe7..419166fcb6 100644 --- a/mode/guozhan/src/skill/character/normal.js +++ b/mode/guozhan/src/skill/character/normal.js @@ -327,7 +327,7 @@ export default { .set("ai", (/** @type {PlayerGuozhan} */ target) => { /** @type {GameEvent & { enemy: boolean }} */ const event = cast(get.event()); - var att = get.attitude(event.player, target); + const att = get.attitude(event.player, target); if (event.enemy) { return -att; } else if (att > 0) { @@ -679,7 +679,7 @@ export default { const groups = []; const players = game.filterPlayer(lib.filter.all); - for (var target of players) { + for (const target of players) { if (target.isUnseen(-1)) continue; let add = true; for (const group of groups) { @@ -873,7 +873,7 @@ export default { */ function check(target) { const player = get.player(); - var att = get.attitude(player, target); + const att = get.attitude(player, target); if (att > 2) { return Math.max(0, Math.min(5, target.maxHp) - target.countCards("h")); } @@ -896,9 +896,9 @@ export default { target(card, player, target, current) { if (get.tag(card, "damage") && target.hp > 1) { if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; - var max = 0; - var players = game.filterPlayer(lib.filter.all); - for (var i = 0; i < players.length; i++) { + let max = 0; + const players = game.filterPlayer(lib.filter.all); + for (let i = 0; i < players.length; i++) { if (get.attitude(target, players[i]) > 0) { max = Math.max(Math.min(5, players[i].hp) - players[i].countCards("h"), max); } @@ -1025,10 +1025,10 @@ export default { if (player.hasSkillTag("jueqing", false, target)) return [1, -2]; if (target.hp <= 1) return; if (!target.hasFriend()) return; - var hastarget = false; - var turnfriend = false; - var players = game.filterPlayer(lib.filter.all); - for (var i = 0; i < players.length; i++) { + let hastarget = false; + let turnfriend = false; + const players = game.filterPlayer(lib.filter.all); + for (let i = 0; i < players.length; i++) { if (get.attitude(target, players[i]) < 0 && !players[i].isTurnedOver()) { hastarget = true; } @@ -1121,14 +1121,14 @@ export default { check(card) { if (ui.selected.cards.length && ui.selected.cards[0].name == "du") return 0; if (!ui.selected.cards.length && card.name == "du") return 20; - var player = get.owner(card); + const player = get.owner(card); if (player == null) { return 0; } if (ui.selected.cards.length >= Math.max(2, player.countCards("h") - player.hp)) return 0; if (player.hp == player.maxHp || player.storage.rerende < 0 || player.countCards("h") <= 1) { - var players = game.filterPlayer(lib.filter.all); - for (var i = 0; i < players.length; i++) { + const players = game.filterPlayer(lib.filter.all); + for (let i = 0; i < players.length; i++) { if (players[i].hasSkill("haoshi") && !players[i].isTurnedOver() && !players[i].hasJudge("lebu") && get.attitude(player, players[i]) >= 3 && get.attitude(players[i], player) >= 3) { return 11 - get.value(card); } @@ -1182,8 +1182,8 @@ export default { return -10; } if (target.hasJudge("lebu")) return 0; - var nh = target.countCards("h"); - var np = player.countCards("h"); + const nh = target.countCards("h"); + const np = player.countCards("h"); if (player.hp == player.maxHp || player.storage.rerende < 0 || player.countCards("h") <= 1) { if (nh >= np - 1 && np <= player.hp && !target.hasSkill("haoshi")) return 0; } @@ -1329,7 +1329,7 @@ export default { trigger.getParent()?.targets.remove(player); }, onremove(player, skill) { - var cards = player.getExpansions(skill); + const cards = player.getExpansions(skill); if (cards.length) player.loseToDiscardpile(cards); }, ai: { @@ -1941,17 +1941,569 @@ export default { .chooseTarget(get.prompt2("gzshushen_new"), lib.filter.notMe) .set("ai", target => { const player = get.player(); - return get.effect(target, { name: "draw" }, player, player) * (1 + !Boolean(target.countCards("h"))); + return get.effect(target, { name: "draw" }, player, player) * (1 + (target.countCards("h") == 0 ? 1 : 0)); }) .setHiddenSkill("gzshushen_new") .forResult(); }, async content(event, trigger, player) { - event.targets[0].draw(Boolean(event.targets[0].countCards("h")) ? 1 : 2); + event.targets[0].draw(event.targets[0].countCards("h") > 0 ? 1 : 2); }, ai: { threaten: 0.8, expose: 0.1, }, }, + + // gz_sunquan + gz_zhiheng: { + inherit: "zhiheng", + audio: "zhiheng", + selectCard() { + const player = get.player(); + const range1 = [1, player.maxHp]; + if (player.hasSkill("dinglanyemingzhu_skill")) { + for (let i = 0; i < ui.selected.cards.length; i++) { + if (ui.selected.cards[i] == player.getEquip("dinglanyemingzhu")) return range1; + } + return [1, Infinity]; + } + return range1; + }, + filterCard(card, player) { + if (ui.selected.cards.length < player.maxHp || !player.hasSkill("dinglanyemingzhu_skill")) return true; + return card != player.getEquip("dinglanyemingzhu"); + }, + complexCard: true, + complexSelect: true, + prompt() { + const player = get.player(); + if (player.hasSkill("dinglanyemingzhu_skill")) return "出牌阶段限一次,你可以弃置任意张牌,然后摸等量的牌"; + return "出牌阶段限一次,你可以弃置至多X张牌(X为你的体力上限),然后摸等量的牌"; + }, + }, + + // gz_lvmeng + /** @type {Skill} */ + gz_keji: { + audio: "keji", + forced: true, + trigger: { + player: "phaseDiscardBegin", + }, + filter(event, player) { + const list = []; + player.getHistory("useCard", function (evt) { + if (evt.isPhaseUsing(player)) { + const color = get.color(evt.card); + if (color != "nocolor") list.add(color); + } + return true; + }); + return list.length <= 1; + }, + check(event, player) { + return player.needsToDiscard(); + }, + async content(event, trigger, player) { + player.addTempSkill("keji_add", "phaseAfter"); + }, + }, + /** @type {Skill} */ + gz_mouduan: { + trigger: { + player: "phaseJieshuBegin", + }, + //priority:2, + audio: "botu", + filter(event, player) { + const history = player.getHistory("useCard"); + const suits = []; + const types = []; + for (let i = 0; i < history.length; i++) { + const suit = get.suit(history[i].card); + if (suit) suits.add(suit); + types.add(get.type(history[i].card)); + } + return suits.length >= 4 || types.length >= 3; + }, + check(event, player) { + return player.canMoveCard(true, void 0); + }, + async content(event, trigger, player) { + await player.moveCard(); + }, + }, + + // gz_huanggai + /** @type {Skill} */ + gz_kurou: { + audio: "rekurou", + enable: "phaseUse", + usable: 1, + filterCard: true, + check(card) { + return 8 - get.value(card); + }, + position: "he", + async content(event, trigger, player) { + await player.loseHp(); + await player.draw(3); + player.addTempSkill("kurou_effect", "phaseAfter"); + }, + ai: { + order: 8, + result: { + player(player) { + if (player.hp <= 2) return player.countCards("h") == 0 ? 1 : 0; + if (player.countCards("h", { name: "sha", color: "red" })) return 1; + return player.countCards("h") <= player.hp ? 1 : 0; + }, + }, + }, + }, + + // gz_luxun + /** @type {Skill} */ + gz_qianxun: { + audio: "qianxun", + trigger: { + target: "useCardToTarget", + player: "addJudgeBefore", + }, + forced: true, + preHidden: true, + priority: 15, + check(event, player) { + return event.name == "addJudge" || get.effect(event.target, event.card, event.player, player) < 0; + }, + filter(event, player) { + return event.card.name == (event.name == "addJudge" ? "lebu" : "shunshou"); + }, + async content(event, trigger, player) { + if (trigger.name == "addJudge") { + trigger.cancel(undefined, undefined, undefined); + const owner = get.owner(trigger.card); + if (owner && owner.getCards("hej").includes(trigger.card)) owner.lose(trigger.card, ui.discardPile); + else game.cardsDiscard(trigger.card); + game.log(trigger.card, "进入了弃牌堆"); + // @ts-expect-error 类型系统未来可期 + } else trigger.getParent()?.targets?.remove(player); + }, + ai: { + effect: { + target(card, player, target, current) { + if (card.name == "shunshou" || card.name == "lebu") return "zeroplayertarget"; + }, + }, + }, + }, + /** @type {Skill} */ + gz_duoshi: { + audio: "duoshi", + trigger: { player: "phaseUseBegin" }, + filter(event, player) { + return player.hasUseTarget(new lib.element.VCard({ name: "yiyi" })); + }, + direct: true, + preHidden: true, + async content(event, trigger, player) { + await player + .chooseUseTarget(get.prompt2(event.name), new lib.element.VCard({ name: "yiyi" }), false) + .set("hiddenSkill", event.name) + .set("logSkill", event.name); + }, + }, + + // gz_sunshangxiang + gzxiaoji: { + inherit: "xiaoji", + audio: "xiaoji", + preHidden: true, + getIndex(event, player) { + const evt = event.getl(player); + if (evt && evt.player === player && evt.es && evt.es.length) return 1; + return false; + }, + async content(event, trigger, player) { + // @ts-expect-error 类型系统未来可期 + await player.draw(player == _status.currentPhase ? 1 : 3); + }, + }, + + // gz_xiaoqiao + gz_tianxiang: { + audio: "tianxiang", + audioname: ["daxiaoqiao", "re_xiaoqiao", "ol_xiaoqiao"], + trigger: { player: "damageBegin4" }, + preHidden: true, + usable: 1, + filter(event, player) { + return ( + player.countCards("h", card => { + return _status.connectMode || (get.suit(card, player) == "heart" && lib.filter.cardDiscardable(card, player)); + }) > 0 && event.num > 0 + ); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseCardTarget({ + filterCard(card, player) { + return get.suit(card) == "heart" && lib.filter.cardDiscardable(card, player); + }, + filterTarget: lib.filter.notMe, + ai1(card) { + return 10 - get.value(card); + }, + ai2(target) { + const att = get.attitude(get.player(), target); + const trigger = get.event().getTrigger(); + let da = 0; + if (get.player().hp == 1) { + da = 10; + } + const eff = get.damageEffect(target, trigger.source, target); + if (att == 0) return 0.1 + da; + if (eff >= 0 && att > 0) { + return att + da; + } + if (att > 0 && target.hp > 1) { + if (target.maxHp - target.hp >= 3) return att * 1.1 + da; + if (target.maxHp - target.hp >= 2) return att * 0.9 + da; + } + return -att + da; + }, + prompt: get.prompt(event.skill), + prompt2: lib.translate[`${event.skill}_info`], + }) + .setHiddenSkill(event.skill) + .forResult(); + }, + async content(event, trigger, player) { + const { + cards, + targets: [target], + } = event; + trigger.cancel(); + await player.discard(cards); + const { result } = await player + // @ts-expect-error 类型系统未来可期 + .chooseControlList(true, (event, player) => get.event().index, [`令${get.translation(target)}受到伤害来源对其造成的1点伤害,然后摸X张牌(X为其已损失体力值且至多为5)`, `令${get.translation(target)}失去1点体力,然后获得${get.translation(cards)}`]) + .set( + "index", + (() => { + let att = get.attitude(player, target); + if (target.hasSkillTag("maihp")) att = -att; + return att > 0 ? 0 : 1; + })() + ); + if (typeof result.index != "number") return; + if (result.index == 0) { + await target.damage(trigger.source || "nosource", "nocard"); + if (target.getDamagedHp()) await target.draw(Math.min(5, target.getDamagedHp())); + } else { + await target.loseHp(); + if (cards[0].isInPile()) await target.gain(cards, "gain2"); + } + }, + ai: { + maixie_defend: true, + effect: { + target(card, player, target) { + if (player.hasSkillTag("jueqing", false, target)) return; + if (get.tag(card, "damage") && target.countCards("he") > 1) return 0.7; + }, + }, + }, + }, + gz_hongyan: { + mod: { + suit(card, suit) { + if (suit == "spade") return "heart"; + }, + maxHandcard(player, num) { + if ( + player.hasCard(function (card) { + return get.suit(card, player) == "heart"; + }, "e") + ) + return num + 1; + }, + }, + }, + + // gz_re_taishici + gz_hanzhan: { + audio: "hanzhan", + trigger: { + player: ["chooseToCompareAfter", "compareMultipleAfter"], + target: ["chooseToCompareAfter", "compareMultipleAfter"], + }, + filter(event, player) { + if (event.preserve) return false; + const list = [event.player, event.target]; + const targets = list.slice().filter(i => (event.num1 - event.num2) * get.sgn(0.5 - list.indexOf(i)) <= 0); + return targets.some(i => { + const target = list[1 - list.indexOf(i)]; + return target.hasCard(card => { + return lib.filter.canBeGained(card, i, target); + }, "e"); + }); + }, + async cost(event, trigger, player) { + let users = []; + const list = [trigger.player, trigger.target]; + let targets = list.slice().filter(i => (trigger.num1 - trigger.num2) * get.sgn(0.5 - list.indexOf(i)) <= 0); + targets = targets + .filter(i => { + const target = list[1 - list.indexOf(i)]; + return target.hasCard(card => { + return lib.filter.canBeGained(card, i, target); + }, "e"); + }) + .sortBySeat(player); + for (const i of targets) { + const aim = list[1 - list.indexOf(i)]; + const { + result: { bool }, + } = await i.chooseBool(get.prompt("fakehanzhan"), "获得" + get.translation(aim) + "装备区的一张牌").set( + "choice", + aim.hasCard(card => { + return get.value(card, aim) * get.attitude(i, aim) < 0; + }, "e") + ); + if (bool) users.push(i); + } + event.result = { bool: Boolean(users.length), targets: users }; + }, + logLine: false, + async content(event, trigger, player) { + const list = [trigger.player, trigger.target]; + let targets = list.slice().filter(i => (trigger.num1 - trigger.num2) * get.sgn(0.5 - list.indexOf(i)) <= 0); + targets = targets + .filter(i => { + const target = list[1 - list.indexOf(i)]; + return target.hasCard(card => { + return lib.filter.canBeGained(card, i, target); + }, "e"); + }) + .sortBySeat(player); + for (const i of targets) { + const aim = list[1 - list.indexOf(i)]; + i.line(aim, "green"); + await i.gainPlayerCard(aim, "e", true); + } + }, + }, + + // gz_dingfeng + gz_duanbing: { + audio: "duanbing", + inherit: "reduanbing", + preHidden: ["gz_duanbing_sha"], + group: ["gz_duanbing", "gz_duanbing_sha"], + subSkill: { + sha: { + audio: "duanbing", + trigger: { player: "useCardToPlayered" }, + filter(event, player) { + return event.card.name == "sha" && !event.getParent().directHit.includes(event.target) && event.targets.length == 1; + }, + forced: true, + logTarget: "target", + async content(event, trigger, player) { + const id = trigger.target.playerid; + const map = trigger.getParent().customArgs; + if (!map[id]) map[id] = {}; + if (typeof map[id].shanRequired == "number") map[id].shanRequired++; + else map[id].shanRequired = 2; + }, + ai: { + directHit_ai: true, + skillTagFilter(player, tag, arg) { + if (!arg || !arg.card || !arg.target || arg.card.name != "sha" || arg.target.countCards("h", "shan") > 1 || get.distance(player, arg.target) > 1) return false; + }, + }, + }, + }, + }, + + // gz_lvbu + gz_wushuang: { + audio: "wushuang", + audioname2: { + gz_lvlingqi: "wushuang_lvlingqi", + }, + forced: true, + locked: true, + group: ["wushuang1", "wushuang2"], + preHidden: ["wushuang1", "wushuang2", "gz_wushuang"], + trigger: { player: "useCard1" }, + direct: true, + filter(event, player) { + if (event.card.name != "juedou" || !event.card.isCard) return false; + if (event.targets) { + if ( + game.hasPlayer(function (current) { + return !event.targets.includes(current) && lib.filter.targetEnabled2(event.card, player, current); + }) + ) { + return true; + } + } + return false; + }, + async cost(event, trigger, player) { + const num = game.countPlayer(current => !trigger.targets.includes(current) && lib.filter.targetEnabled2(trigger.card, player, current)); + + event.result = await player + .chooseTarget("无双:是否为" + get.translation(trigger.card) + "增加" + (num > 1 ? "至多两个" : "一个") + "目标?", [1, Math.min(2, num)], (card, player, target) => { + const trigger = get.event().getTrigger(); + const cardx = trigger.card; + return !trigger.targets.includes(target) && lib.filter.targetEnabled2(cardx, player, target); + }) + .set("ai", target => { + const player = get.event().player; + const card = get.event().getTrigger().card; + return get.effect(target, card, player, player); + }) + .setHiddenSkill("gzwushuang") + .forResult(); + + if (event.result.bool && player != game.me && !player.isOnline()) { + await game.delayx(); + } + }, + logTarget: "targets", + async content(event, trigger, player) { + const targets = event.targets.sortBySeat(); + trigger.targets.addArray(targets); + }, + }, + + // gz_yuanshao + gz_luanji: { + audio: "luanji", + enable: "phaseUse", + viewAs: { + name: "wanjian", + }, + filterCard(card, player) { + if (!player.storage.gz_luanji) return true; + return !player.storage.gz_luanji.includes(get.suit(card)); + }, + selectCard: 2, + position: "hs", + filter(event, player) { + return ( + player.countCards("hs", function (card) { + return !player.storage.gz_luanji || !player.storage.gz_luanji.includes(get.suit(card)); + }) > 1 + ); + }, + check(card) { + const player = get.player(); + const targets = game.filterPlayer(current => player.canUse("wanjian", current) ?? false); + let num = 0; + for (let i = 0; i < targets.length; i++) { + let eff = get.sgn(get.effect(targets[i], { name: "wanjian" }, player, player)); + if (targets[i].hp == 1) { + eff *= 1.5; + } + num += eff; + } + if (!player.needsToDiscard(-1)) { + if (targets.length >= 7) { + if (num < 2) return 0; + } else if (targets.length >= 5) { + if (num < 1.5) return 0; + } + } + return 6 - get.value(card); + }, + group: ["gz_luanji_count", "gz_luanji_reset", "gz_luanji_respond"], + subSkill: { + reset: { + trigger: { + player: "phaseAfter", + }, + silent: true, + filter(event, player) { + return player.storage.gz_luanji ? true : false; + }, + async content(event, trigger, player) { + delete player.storage.gz_luanji; + }, + sub: true, + forced: true, + popup: false, + }, + count: { + trigger: { + player: "useCard", + }, + silent: true, + filter(event) { + return event.skill == "gz_luanji"; + }, + async content(event, trigger, player) { + if (!player.storage.gz_luanji) { + player.storage.gz_luanji = []; + } + for (let i = 0; i < trigger.cards.length; i++) { + player.storage.gz_luanji.add(get.suit(trigger.cards[i])); + } + }, + sub: true, + forced: true, + popup: false, + }, + respond: { + trigger: { + global: "respond", + }, + silent: true, + filter(event) { + if (event.player.isUnseen()) return false; + // @ts-expect-error 类型系统未来可期 + return event.getParent(2).skill == "gz_luanji" && event.player.isFriendOf(_status.currentPhase); + }, + async content(event, trigger, player) { + await trigger.player.draw(); + }, + sub: true, + forced: true, + popup: false, + }, + }, + }, + + // gz_yanwen + gz_shuangxiong: { + audio: "shuangxiong", + subfrequent: ["tiandu"], + group: ["gz_shuangxiong_effect", "gz_shuangxiong_tiandu"], + subSkill: { + effect: { + audio: "shuangxiong1", + inherit: "shuangxiong1", + async content(event, trigger, player) { + player.judge().set("callback", get.info("gz_shuangxiong").subSkill?.effect.callback); + trigger.changeToZero(); + }, + async callback(event, trigger, player) { + player.addTempSkill("shuangxiong2"); + player.markAuto("shuangxiong2", [event.judgeResult.color]); + }, + }, + tiandu: { + audio: "shuangxiong", + inherit: "tiandu", + filter(event, player) { + // @ts-expect-error 类型系统未来可期 + return _status.currentPhase == player && get.info("tiandu").filter(event, player); + }, + }, + }, + }, }; diff --git a/mode/guozhan/src/translate/character/index.js b/mode/guozhan/src/translate/character/index.js index 87a7fae07b..92a5430521 100644 --- a/mode/guozhan/src/translate/character/index.js +++ b/mode/guozhan/src/translate/character/index.js @@ -1,5 +1,7 @@ +import sort from "./sort.js"; import normal from "./normal.js"; export default { + ...sort, ...normal, }; diff --git a/mode/guozhan/src/translate/character/normal.js b/mode/guozhan/src/translate/character/normal.js index 8bb2fb432b..5b274f3727 100644 --- a/mode/guozhan/src/translate/character/normal.js +++ b/mode/guozhan/src/translate/character/normal.js @@ -26,3 +26,5 @@ export default { gz_weiyan: "魏延", gz_pangtong: "庞统", }; + +export const sort = ["guozhan_default", "国战标准"]; diff --git a/mode/guozhan/src/translate/character/sort.js b/mode/guozhan/src/translate/character/sort.js new file mode 100644 index 0000000000..baf2d0b79e --- /dev/null +++ b/mode/guozhan/src/translate/character/sort.js @@ -0,0 +1,5 @@ +import { sort as normalSort } from "./normal.js"; + +export default { + [normalSort[0]]: normalSort[1], +}; diff --git a/mode/guozhan/src/translate/skill/character/normal.js b/mode/guozhan/src/translate/skill/character/normal.js index e6c114c53a..7030959e26 100644 --- a/mode/guozhan/src/translate/skill/character/normal.js +++ b/mode/guozhan/src/translate/skill/character/normal.js @@ -73,4 +73,39 @@ export default { gz_shushen: "淑慎", gz_shushen_info: "当你回复1点体力后,你可令一名其他角色摸一张牌(若其没有手牌则改为摸两张牌)。", + + gz_zhiheng: "制衡", + gz_zhiheng_info: "出牌阶段限一次,你可以弃置至多X张牌(X为你的体力上限),然后摸等量的牌。", + + gz_keji: "克己", + gz_keji_info: "锁定技,若你没有在出牌阶段内使用过颜色不同的牌,则你本回合的手牌上限+4。", + gz_mouduan: "谋断", + gz_mouduan_info: "结束阶段,若你于本回合内使用过四种花色或三种类别的牌,则你可以移动场上的一张牌。", + + gz_qianxun: "谦逊", + gz_qianxun_info: "锁定技,当你成为【顺手牵羊】的目标时,或有【乐不思蜀】进入你的判定区时,取消之。", + gz_duoshi: "度势", + gz_duoshi_info: "出牌阶段开始时,你可以视为使用【以逸待劳】。", + + gz_xiaoji: "枭姬", + gz_xiaoji_info: "当你失去装备区里的牌后,你可以摸一张牌。若你不是当前回合角色,则你改为摸三张牌。", + + gz_tianxiang: "天香", + gz_tianxiang_info: "每回合限一次。当你受到伤害时,你可以弃置一张红桃手牌,防止此次伤害并选择一名其他角色,然后你选择一项:1.令其受到伤害来源对其造成的1点伤害,然后摸X张牌(X为其已损失体力值且至多为5);2.令其失去1点体力,然后获得你弃置的牌。", + gz_hongyan: "红颜", + gz_hongyan_info: "锁定技。①你区域内的黑桃牌和黑桃判定牌的花色视为红桃。②若你的装备区内有红桃牌,则你的手牌上限+1。", + + gz_hanzhan: "酣战", + gz_hanzhan_info: "有你参与的拼点事件结束后,没赢的角色可以获得对方装备区的一张牌。", + gz_duanbing: "短兵", + gz_duanbing_info: "①你使用【杀】可以额外指定一名距离为1或以内的目标。②当你使用【杀】指定唯一目标后,你令目标角色需要额外使用一张【闪】响应此【杀】。", + + gz_wushuang: "无双", + gz_wushuang_info: "锁定技。①当你使用【杀】指定一名角色为目标后,其需使用两张【闪】才能抵消;②当你使用【决斗】指定其他角色为目标后,或成为其他角色使用【决斗】的目标后,其每次响应需打出两张【杀】。③当你使用非转化的【决斗】选择目标后,你可为此【决斗】增加两个目标。", + + gz_luanji: "乱击", + gz_luanji_info: "你可以将两张与你本回合以此法转化的花色均不相同的手牌当【万箭齐发】使用。当一名与你势力相同的角色因响应此牌而打出【闪】时,该角色摸一张牌。", + + gz_shuangxiong: "双雄", + gz_shuangxiong_info: "①摸牌阶段,你可以放弃摸牌并进行判定,本回合你可以将一张与此牌颜色不同的手牌当作【决斗】使用。②当你的判定牌于回合内生效后,你获得此牌。", };