diff --git a/.eslintrc.json b/.eslintrc.json index fde84ce4b7..84e8898fc3 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -31,4 +31,4 @@ "ecmaVersion": 13, "sourceType": "module" } -} \ No newline at end of file +} diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d2239a1e25..feaeaf832c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -32,4 +32,4 @@ - [ ] 如果此次PR需要扩展跟进,我已在`扩展适配`中写入详细文档 - [ ] 如果这个PR解决了一个issue,我在`诱因和背景`中明确链接到该issue - [ ] 我保证该PR中没有随意修改换行符等内容,没有制造出大量的Diff -- [ ] 我保证该PR遵循项目中`.editorconfig`、`.eslintrc.json`和`.prettierrc`所规定的代码样式,并且已经通过`prettier`格式化过代码 +- [ ] 我保证该PR遵循项目中`.editorconfig`、`eslint.config.mjs`和`prettier.config.mjs`所规定的代码样式,并且已经通过`prettier`格式化过代码 diff --git a/.gitignore b/.gitignore index cf3bd6cc25..c8875aef3e 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,4 @@ noname.ico package-lock.json package.json Thumbs.db +bun.lockb diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index b138a611b1..0000000000 --- a/.prettierrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "arrowParens": "always", - "bracketSpacing": true, - "endOfLine": "lf", - "printWidth": 110, - "proseWrap": "preserve", - "quoteProps": "as-needed", - "semi": true, - "tabWidth": 4, - "trailingComma": "es5", - "useTabs": true -} diff --git a/card/standard.js b/card/standard.js index aeca20f1be..9ea1a0d370 100644 --- a/card/standard.js +++ b/card/standard.js @@ -2146,138 +2146,48 @@ game.import("card", function () { }, result: { player: function (player, target) { - let att = get.attitude(player, target), - hs = target.hasCard( - (card) => lib.filter.canBeGained(card, player, target), - "h" - ), - lose = hs, - gain = att > 0 ? 0.52 : 1.28; - if (Math.abs(att) < 5.03) { - let temp = 0.015 * att * att; - if (att < 0) gain = 0.9 + temp; - else gain = 0.9 - temp; + const hs = target.getGainableCards(player, 'h'); + const es = target.getGainableCards(player, 'e'); + const js = target.getGainableCards(player, 'j'); + const att = get.attitude(player, target); + if (att < 0) { + if (!hs.length && !es.some(card => { + return get.value(card, target) > 0 && card != target.getEquip('jinhe'); + }) && !js.some(card => { + var cardj = card.viewAs ? { name: card.viewAs } : card; + return get.effect(target, cardj, target, player) < 0; + })) return 0; } - target.countCards("e", function (card) { - if ( - card.name != "jinhe" && - lib.filter.canBeGained(card, player, target) && - att * get.value(card, target) < 0 - ) { - lose = true; - let val = get.value(card, player); - if (val > 0) gain = Math.max(gain, val / 7); - } - }); - target.countCards("j", function (card) { - let cardj = card.viewAs ? new lib.element.VCard({ name: card.viewAs }) : card; - if ( - lib.filter.canBeGained(card, player, target) && - att * get.effect(target, cardj, target, target) < 0 - ) { - lose = true; - if (cardj.name == "lebu") { - let needs = target.needsToDiscard(2); - if (att > 0) gain = Math.max(gain, 1.6 + needs / 10); - } else if ( - cardj.name == "shandian" || - cardj.name == "fulei" || - cardj.name == "plague" - ) - gain = Math.max(gain, 1.5 / Math.max(1, target.hp)); - else if (att > 0) gain = Math.max(gain, 1.7); - } - }); - if (!lose) return 0; - return gain; + else if (att > 1) { + return (es.some(card => { + return get.value(card, target) <= 0; + }) || js.some(card => { + var cardj = card.viewAs ? { name: card.viewAs } : card; + return get.effect(target, cardj, target, player) < 0; + })) ? 1.5 : 0; + } + return 1; }, target: function (player, target) { - let att = get.attitude(player, target), - hs = target.countCards("h", (card) => - lib.filter.canBeGained(card, player, target) - ), - es = target.countCards("e", (card) => - lib.filter.canBeGained(card, player, target) - ), - js = target.countCards("j", (card) => - lib.filter.canBeGained(card, player, target) - ), - noh = !hs || target.hasSkillTag("noh"), - noe = !es || target.hasSkillTag("noe"), - check = [-1, att > 0 ? -1.3 : 1.3, att > 0 ? -2.5 : 2.5], - idx = -1; - if (hs) { - idx = 0; - if (noh) check[0] = 0.7; - } - if (es) { - if (idx < 0) idx = 1; - if ( - target.getEquip("baiyin") && - target.isDamaged() && - lib.filter.canBeGained(target.getEquip("baiyin"), player, target) - ) { - let rec = get.recoverEffect(target, player, target); - if (es == 1 || att * rec > 0) { - let val = 3 - 0.6 * Math.min(5, target.hp); - if (rec > 0) check[1] = val; - else if (rec < 0) check[1] = -val; - } - } - target.countCards("e", function (card) { - let val = get.value(card, target); - if ( - card.name == "jinhe" || - att * val >= 0 || - !lib.filter.canBeGained(card, player, target) - ) - return false; - if (att > 0) { - check[1] = Math.max(1.3, check[1]); - return true; - } - let sub = get.subtype(card); - if (sub == "equip2" || sub == "equip5") val += 4; - else if (sub == "equip1") val *= 0.4 * Math.min(3.6, target.hp); - else val *= 0.6; - if (target.hp < 3 && sub != "equip2" && sub != "equip5") val *= 0.4; - check[1] = Math.min(-0.16 * val, check[1]); - }); - if (noe) check[1] += 0.9; - } - if (js) { - let func = function (num) { - if (att > 0) check[2] = Math.max(check[2], num); - else check[2] = Math.min(check[2], 0.6 - num); - }; - if (idx < 0) idx = 2; - target.countCards("j", function (card) { - let cardj = card.viewAs - ? new lib.element.VCard({ name: card.viewAs }) - : card; - if ( - !lib.filter.canBeGained(card, player, target) || - att * get.effect(target, cardj, target, target) >= 0 - ) - return false; - if (cardj.name == "lebu") func(2.1 + 0.4 * target.needsToDiscard(2)); - else if (cardj.name == "bingliang") func(2.4); - else if ( - cardj.name == "shandian" || - cardj.name == "fulei" || - cardj.name == "plague" - ) - func(Math.abs(check[2]) / (1 + target.hp)); - else func(2.1); - }); - } - if (idx < 0) return 0; - for (let i = idx + 1; i < 3; i++) { - if ((i == 1 && !es) || (i == 2 && !js)) continue; - if ((att > 0 && check[i] > check[idx]) || (att <= 0 && check[i] < check[idx])) - idx = i; + const hs = target.getGainableCards(player, 'h'); + const es = target.getGainableCards(player, 'e'); + const js = target.getGainableCards(player, 'j'); + + if (get.attitude(player, target) <= 0) { + if (hs.length > 0) return -1.5; + return (es.some(card => { + return get.value(card, target) > 0 && card != target.getEquip('jinhe'); + }) || js.some(card => { + var cardj = card.viewAs ? { name: card.viewAs } : card; + return get.effect(target, cardj, target, player) < 0; + })) ? -1.5 : 1.5; } - return check[idx]; + return (es.some(card => { + return get.value(card, target) <= 0; + }) || js.some(card => { + var cardj = card.viewAs ? { name: card.viewAs } : card; + return get.effect(target, cardj, target, player) < 0; + })) ? 1.5 : -1.5; }, }, tag: { @@ -2546,92 +2456,38 @@ game.import("card", function () { }, result: { target: function (player, target) { - let att = get.attitude(player, target), - hs = target.countCards("h", (card) => - lib.filter.canBeDiscarded(card, player, target) - ), - es = target.countCards("e", (card) => - lib.filter.canBeDiscarded(card, player, target) - ), - js = target.countCards("j", (card) => - lib.filter.canBeDiscarded(card, player, target) - ), - noh = !hs || target.hasSkillTag("noh"), - noe = !es || target.hasSkillTag("noe"), - check = [-1, att > 0 ? -1.3 : 1.3, att > 0 ? -2.5 : 2.5], - idx = -1; - if (hs) { - idx = 0; - if (noh) check[0] = 0.7; - } - if (es) { - if (idx < 0) idx = 1; - if ( - target.getEquip("baiyin") && - target.isDamaged() && - lib.filter.canBeDiscarded(target.getEquip("baiyin"), player, target) - ) { - let rec = get.recoverEffect(target, player, target); - if (es == 1 || att * rec > 0) { - let val = 3 - 0.6 * Math.min(5, target.hp); - if (rec > 0) check[1] = val; - else if (rec < 0) check[1] = -val; - } + const att = get.attitude(player, target); + const hs = target.getDiscardableCards(player, 'h'); + const es = target.getDiscardableCards(player, 'e'); + const js = target.getDiscardableCards(player, 'j'); + if (!hs.length && !es.length && !js.length) return 0; + if (att > 0) { + if (js.some(card => { + const cardj = card.viewAs ? { name: card.viewAs } : card; + return get.effect(target, cardj, target, player) < 0; + })) return 3; + if (target.isDamaged() && es.some(card => card.name == 'baiyin') && + get.recoverEffect(target, player, player) > 0) { + if (target.hp == 1 && !target.hujia) return 1.6; } - target.countCards("e", function (card) { - let val = get.value(card, target); - if ( - card.name == "jinhe" || - att * val >= 0 || - !lib.filter.canBeDiscarded(card, player, target) - ) - return false; - if (att > 0) { - check[1] = Math.max(1.3, check[1]); - return true; - } - let sub = get.subtype(card); - if (sub == "equip2" || sub == "equip5") val += 4; - else if (sub == "equip1") val *= 0.4 * Math.min(3.6, target.hp); - else val *= 0.6; - if (target.hp < 3 && sub != "equip2" && sub != "equip5") val *= 0.4; - check[1] = Math.min(-0.16 * val, check[1]); - }); - if (noe) check[1] += 0.9; - } - if (js) { - let func = function (num) { - if (att > 0) check[2] = Math.max(check[2], num); - else check[2] = Math.min(check[2], 0.6 - num); - }; - if (idx < 0) idx = 2; - target.countCards("j", function (card) { - let cardj = card.viewAs - ? new lib.element.VCard({ name: card.viewAs }) - : card; - if ( - !lib.filter.canBeDiscarded(card, player, target) || - att * get.effect(target, cardj, target, target) >= 0 - ) - return false; - if (cardj.name == "lebu") func(2.1 + 0.4 * target.needsToDiscard(2)); - else if (cardj.name == "bingliang") func(2.4); - else if ( - cardj.name == "shandian" || - cardj.name == "fulei" || - cardj.name == "plague" - ) - func(Math.abs(check[2]) / (1 + target.hp)); - else func(2.1); - }); + if (es.some(card => { + return get.value(card, target) < 0; + })) return 1; + return -1.5; } - if (idx < 0) return 0; - for (let i = idx + 1; i < 3; i++) { - if ((i == 1 && !es) || (i == 2 && !js)) continue; - if ((att > 0 && check[i] > check[idx]) || (att <= 0 && check[i] < check[idx])) - idx = i; + else { + const noh = (hs.length == 0 || target.hasSkillTag('noh')); + const noe = (es.length == 0 || target.hasSkillTag('noe')); + const noe2 = (noe || !es.some(card => { + return get.value(card, target) > 0; + })); + const noj = (js.length == 0 || !js.some(card => { + const cardj = card.viewAs ? { name: card.viewAs } : card; + return get.effect(target, cardj, target, player) < 0; + })) + if (noh && noe2 && noj) return 1.5; + return -1.5; } - return check[idx]; }, }, tag: { @@ -2989,7 +2845,7 @@ game.import("card", function () { cf = Math.pow(get.threaten(target, player), 2); if (!num) return -0.01 * cf; if (target.hp > 2) num--; - let dist = Math.sqrt(get.distance(player, target, "absolute")); + let dist = Math.sqrt(1 + get.distance(player, target, "absolute")); if (dist < 1) dist = 1; if (target.isTurnedOver()) dist++; return (Math.min(-0.1, -num) * cf) / dist; diff --git a/character/clan.js b/character/clan.js index 2e209b4705..c99823343e 100644 --- a/character/clan.js +++ b/character/clan.js @@ -1162,7 +1162,7 @@ game.import("character", function () { var num = get.cardNameLength(event.card); return typeof num == "number" && num > 0 && player.countCards("he") > 0; }, - async content(event, trigger, player) { + async cost(event, trigger, player) { var num = get.cardNameLength(trigger.card), str = ""; if (player.getDamagedHp() > 0) diff --git a/character/ddd.js b/character/ddd.js index 07065aeb25..adaa7e8ba4 100644 --- a/character/ddd.js +++ b/character/ddd.js @@ -3361,6 +3361,9 @@ game.import("character", function () { content() { player.draw(3); }, + ai: { + combo: "dddfusi" + }, }, dddchashi: { trigger: { global: "phaseUseBegin" }, @@ -5113,6 +5116,9 @@ game.import("character", function () { }, }, }, + ai: { + combo: "dddyouxue" + }, }, dddyouxue_old: { audio: 2, @@ -6624,7 +6630,7 @@ game.import("character", function () { "锁定技。出牌阶段开始时,你选择一名角色,其弃置两张牌,然后你对一名角色造成1点伤害。" + (player.storage["dddxiaheng_del"] ? "" - : "。“若两名角色:均不为你,你失去一点体力上限;为同一名角色,你失去一点体力;然后若以此法对包括你在内三名不同的角色造成伤害,删除双引号里的描述内容”") + : "“若两名角色:均不为你,你失去一点体力上限;为同一名角色,你失去一点体力;然后若以此法对包括你在内三名不同的角色造成伤害,删除双引号里的描述内容”") ); }, dddshichao(player) { @@ -6638,9 +6644,8 @@ game.import("character", function () { return ( "转换技,摸牌阶段,你" + (player.hasMark("dddxuanlun_del") ? "" : "可") + - "展示手牌(无牌则不展示),并改为摸其中" + - (!player.storage["dddlanghuai"] ? "包含" : "缺少") + - "花色数的牌。" + "展示手牌(无牌则不展示),并改为摸其中:" + + (player.storage["dddlanghuai"] ? '阴:包含花色数的牌;阳:缺少花色数的牌。' : '阴:包含花色数的牌;阳:缺少花色数的牌。') ); }, dddxuanlun(player) { diff --git a/character/diy.js b/character/diy.js index 36bb7ae458..4d338ba346 100755 --- a/character/diy.js +++ b/character/diy.js @@ -5467,6 +5467,9 @@ game.import("character", function () { content: () => { trigger.forceYingbian = true; }, + ai: { + combo: "asara_shelu" + }, }, yukito_kongwu: { enable: "phaseUse", diff --git a/character/extra.js b/character/extra.js index 1be166f7ac..77939c6101 100755 --- a/character/extra.js +++ b/character/extra.js @@ -753,6 +753,7 @@ game.import("character", function () { }, direct: true, changeSeat: true, + derivation: "tamo_faq", async content(event, trigger, player) { const toSortPlayers = game.filterPlayer((current) => !current.isZhu2()); toSortPlayers.sortBySeat(game.findPlayer2((current) => current.getSeatNum() == 1, true)); @@ -870,7 +871,7 @@ game.import("character", function () { }); const { result } = await next; if (!result.bool) return; - player.logSkill("tamo"); + await player.logSkill("tamo"); const resultList = result.moved[0].map((info) => { return parseInt(info.split("|")[0]); }); @@ -891,6 +892,25 @@ game.import("character", function () { game.swapSeat(list[0], list[1], false); } }, toSwapList); + if (trigger.name === "phase" && !trigger.player.isZhu2() && trigger.player !== toSortPlayers[0] && !trigger._finished) { + trigger.finish(); + trigger._triggered = 5; + const evt = toSortPlayers[0].insertPhase(); + delete evt.skill; + const evt2 = trigger.getParent(); + if (evt2.name == "phaseLoop" && evt2._isStandardLoop) { + evt2.player = toSortPlayers[0]; + } + //跳过新回合的phaseBefore + evt.pushHandler("onPhase", (event, option) => { + if ( + event.step === 0 && + option.state === "begin" + ) { + event.step = 1; + } + }); + } await game.asyncDelay(); }, }, @@ -899,8 +919,9 @@ game.import("character", function () { audio: 2, trigger: { player: "phaseAfter" }, filter(event, player) { - return game.hasPlayer((current) => { - return current.countCards("h") + player.countCards("h") > 0 && player != current; + return game.hasPlayer(target => { + if(target==player||target.countCards('h')+player.countCards('h')==0) return false; + return get.mode()=='identity'||target.countCards('h')<=player.countCards('h')+1; }); }, direct: true, @@ -912,9 +933,8 @@ game.import("character", function () { get.prompt("zhimeng"), "与一名其他角色平分手牌", (card, player, target) => { - return ( - target.countCards("h") + player.countCards("h") > 0 && player != target - ); + if(target==player||target.countCards('h')+player.countCards('h')==0) return false; + return get.mode()=='identity'||target.countCards('h')<=player.countCards('h')+1; } ) .set("ai", (target) => { @@ -1164,7 +1184,6 @@ game.import("character", function () { default: return false; } - break; } }, forced: true, @@ -9397,6 +9416,9 @@ game.import("character", function () { } } }, + ai: { + combo: "nzry_junlve" + }, }, nzry_dinghuo: { audio: 2, @@ -10814,10 +10836,14 @@ game.import("character", function () { dingzhou_info: "出牌阶段限一次。你可以将X张牌交给一名场上有牌的角色,然后你获得其场上的所有牌(X为其场上的牌数+1)。", tamo: "榻谟", - tamo_info: "游戏开始时,你可以重新分配除主公外所有角色的座次。", + tamo_info: + "游戏开始时,你可以重新分配除主公外所有角色的座次。", + tamo_faq: "FAQ", + tamo_faq_info: + "
  • Q:在一号位不为主公的情况下,〖榻谟〗如何结算?
  • A:该角色可以正常进行座次交换。若受此技能影响导致一号位角色发生了变化,则以排列后的一号位角色为起始角色开始本局游戏。
  • ", zhimeng: "智盟", - zhimeng_info: - "回合结束后,你可以与一名其他角色将各自所有手牌置于处理区,然后你随机获得这些牌中的一半(向上取整),其获得剩余的牌。", + zhimeng_info_identity:'回合结束后,你可以选择一名其他角色。若如此做,你与其将各自所有手牌置于处理区,然后你随机获得这些牌中的一半(向上取整),其获得剩余的牌。', + zhimeng_info:'回合结束后,你可以选择一名手牌数不大于Y的其他角色(Y为你的手牌数+1)。若如此做,你与其将各自所有手牌置于处理区,然后你随机获得这些牌中的一半(向上取整),其获得剩余的牌。', shen_xuzhu: "神许褚", shen_xuzhu_prefix: "神", zhengqing: "争擎", diff --git a/character/huicui.js b/character/huicui.js index a4a7236292..d1bc8a5636 100644 --- a/character/huicui.js +++ b/character/huicui.js @@ -7987,7 +7987,7 @@ game.import("character", function () { }, async content(event, trigger, player) { if (event.cards && event.cards.length) { - await player.dicard(cards); + await player.discard(event.cards); lib.skill.dcxieshou.change(player, 1); } else { player.drawTo(player.maxHp); @@ -8005,6 +8005,9 @@ game.import("character", function () { return false; }, }, + ai: { + neg: true + }, }, //公孙度 dczhenze: { @@ -10831,7 +10834,10 @@ game.import("character", function () { player.addTempSkill("zhishi_mark", { player: "phaseBegin" }); } }, - ai: { expose: 0.3 }, + ai: { + combo: "xunli", + expose: 0.3 + }, subSkill: { mark: { trigger: { @@ -12096,6 +12102,9 @@ game.import("character", function () { } } }, + ai: { + combo: "huguan" + }, }, mingluan: { audio: 2, @@ -15060,6 +15069,10 @@ game.import("character", function () { content: function () { player.removeMark("recangchu", Math.min(player.countMark("recangchu"), trigger.num || 1)); }, + ai: { + combo: "recangchu", + neg: true + }, group: "reshishou2", }, reshishou2: { @@ -15493,7 +15506,7 @@ game.import("character", function () { var list = ["sha", "shan", "tao", "jiu"]; for (var i of list) { var strx = "【" + get.translation(i) + "】"; - if (!info || !info[0].includes(i)) + if (info && !info[0].includes(i)) strx = '' + strx + ""; str += strx; if (i != "jiu") str += "/"; diff --git a/character/jsrg.js b/character/jsrg.js index d5015f55d0..1d2830e010 100644 --- a/character/jsrg.js +++ b/character/jsrg.js @@ -8741,6 +8741,9 @@ game.import("character", function () { .set("cards", trigger.cards); } }, + ai: { + combo: "jsrglirang" + }, }, //朱儁 jsrgfendi: { diff --git a/character/mobile.js b/character/mobile.js index 0a4992fc2e..38dbc9102d 100644 --- a/character/mobile.js +++ b/character/mobile.js @@ -394,8 +394,6 @@ game.import("character", function () { "南华老仙,是古典小说《三国演义》中的虚拟人物。其原型来自道教典籍中对庄子的封号,又称“南华仙人”、“南华真人”等。在古典小说《三国演义》通行本的第一回中,描述了南华老仙将《太平要术》赠送给张角的情节。", chenzhen: "陈震(?—公元235年),字孝起。荆州南阳郡(今河南南阳)人。三国时期蜀汉官员。刘备领荆州牧时,辟陈震为从事。后随刘备入蜀,为蜀郡北部都尉、汶山太守、犍为太守。建兴三年(225年),拜尚书,迁尚书令。建兴七年(229年),孙权称帝。蜀汉以陈震为卫尉,前往祝贺,与孙权开坛歃盟,交分天下。还蜀,封城阳亭侯。建兴十三年(235年),卒。", - nanhualaoxian: - "南华老仙,其原型来自道教典籍中对庄子的封号,又称“南华仙人”、“南华真人”等。在古典小说《三国演义》通行本的第一回中,描述了南华老仙将《太平要术》赠送给张角的情节。", hucheer: "胡车儿(生卒年不详),东汉末年武将,初从张绣,为其心腹猛将,勇冠三军,与贾诩交情甚佳。宛城大战后,张绣投降曹操,曹操爱胡车儿之骁勇,手以黄金与之。后因曹操私纳张绣亡叔张济的遗孀邹氏,张绣深感其辱,欲杀曹操,与贾诩商议后决心反曹。《三国演义》中,作者考虑到典韦的勇猛,便增加了令胡车儿盗走典韦的双戟的情节。最终典韦、曹昂(曹操长子)、曹安民(曹操侄子)皆死于此次战斗。野史说胡车儿跟随曹操征战,被赵云在长坂坡上红枪挑死。", simashi: @@ -660,7 +658,6 @@ game.import("character", function () { }, mbshishou: { audio: 2, - forced: true, trigger: { player: "useSkillAfter" }, filter(event, player) { return event.skill === "mbzuoyou" && !event.targets.includes(player); @@ -675,6 +672,9 @@ game.import("character", function () { player ); }, + ai: { + combo: "mbzuoyou" + }, }, //成济 mbkuangli: { @@ -1061,6 +1061,9 @@ game.import("character", function () { }) ); }, + ai: { + combo: "mbqianlong" + }, }, mbcmqingzheng: { audio: "sbqingzheng", @@ -1732,6 +1735,9 @@ game.import("character", function () { }, }, }, + ai: { + combo: "mbxuetu" + }, }, //霍骏 sidai: { @@ -1907,10 +1913,9 @@ game.import("character", function () { if (name == "damageSource" && player.getHistory("sourceDamage").indexOf(event) != 0) return false; return game.hasPlayer((target) => { - if (get.mode() != "doudizhu") { - if (name == "damageEnd" && get.distance(player, target) <= 2) return false; - if (name == "damageSource" && get.distance(player, target) > 2) return false; - } + const num = (get.mode() == 'doudizhu' ? 1 : 2); + if (name == "damageEnd" && get.distance(player, target) <= num) return false; + if (name == "damageSource" && get.distance(player, target) > num) return false; const zhoufa = player.storage.zhoulin_zhoufa; if (!zhoufa) return true; if (zhoufa == "豹" || zhoufa == "兔") return true; @@ -1931,7 +1936,7 @@ game.import("character", function () { : "令其随机执行一个效果"; const nodoudizhu = get.mode() == "doudizhu" - ? "" + ? "距离" + (event.triggername == "damageEnd" ? "" : "不") + "大于1的" : "距离" + (event.triggername == "damageEnd" ? "" : "不") + "大于2的"; const { result: { bool, targets }, @@ -1941,12 +1946,9 @@ game.import("character", function () { "选择一名" + nodoudizhu + "角色," + str, (card, player, target) => { const name = _status.event.triggername; - if (get.mode() != "doudizhu") { - if (name == "damageEnd" && get.distance(player, target) <= 2) - return false; - if (name == "damageSource" && get.distance(player, target) > 2) - return false; - } + const num = (get.mode() == 'doudizhu' ? 1 : 2); + if (name == "damageEnd" && get.distance(player, target) <= num) return false; + if (name == "damageSource" && get.distance(player, target) > num) return false; const zhoufa = player.storage.zhoulin_zhoufa; if (!zhoufa) return true; if (zhoufa == "豹" || zhoufa == "兔") return true; @@ -2714,7 +2716,6 @@ game.import("character", function () { }, forced: true, popup: false, - onremove: true, firstDo: true, init: function (player, skill) { player.storage[skill] = 0; @@ -10578,23 +10579,6 @@ game.import("character", function () { //钟会 requanji: { audio: 2, - mod: { - aiOrder: (player, card, num) => { - if ( - num <= 0 || - typeof card !== "object" || - !player.isPhaseUsing() || - !player.hasSkill("zili") || - player.needsToDiscard() - ) - return num; - if ( - player.getExpansions("quanji").length < 3 && - player.getUseValue(card) < Math.min(4, (player.hp * player.hp) / 4) - ) - return 0; - }, - }, trigger: { player: ["damageEnd", "phaseUseEnd"] }, frequent: true, locked: false, @@ -10634,9 +10618,24 @@ game.import("character", function () { } }, mod: { - maxHandcard: function (player, num) { + maxHandcard(player, num) { return num + player.getExpansions("quanji").length; }, + aiOrder(player, card, num) { + if ( + num <= 0 || + typeof card !== "object" || + !player.isPhaseUsing() || + !player.hasSkill("zili") || + player.needsToDiscard() + ) + return num; + if ( + player.getExpansions("quanji").length < 3 && + player.getUseValue(card) < Math.min(4, (player.hp * player.hp) / 4) + ) + return 0; + }, }, onremove: function (player, skill) { var cards = player.getExpansions("quanji"); @@ -14213,6 +14212,9 @@ game.import("character", function () { evt.targets.push(target); } }, + ai: { + combo: "zhengjian" + }, }, //一 将 成 名 zhilve: { @@ -20043,7 +20045,7 @@ game.import("character", function () { }, shoufa: function (player) { const zhoufa = player.storage.zhoulin_zhoufa; - const nodoudizhu = get.mode() == "doudizhu" ? "" : "与你距离大于/不大于2的"; + const nodoudizhu = get.mode() == "doudizhu" ? "与你距离大于/不大于1的" : "与你距离大于/不大于2的"; if (!zhoufa) return ( "当你受到伤害后/于一回合首次造成伤害后,你可以选择一名" + @@ -21081,10 +21083,6 @@ game.import("character", function () { re_liru_prefix: "手杀界", re_chenqun: "手杀界陈群", re_chenqun_prefix: "手杀界", - re_liru: "手杀界李儒", - re_liru_prefix: "手杀界", - re_chenqun: "手杀界陈群", - re_chenqun_prefix: "手杀界", old_yuanshu: "手杀袁术", old_yuanshu_prefix: "手杀", baoxin: "鲍信", @@ -21161,7 +21159,7 @@ game.import("character", function () { shoufa_info: "当你受到伤害后/于一回合首次造成伤害后,你可以选择一名与你距离大于/不大于2的角色,令其随机执行以下一项:豹,令其受到1点无来源伤害;鹰,你随机获得其一张牌;熊,你随机弃置其装备区的一张牌;兔,令其摸一张牌。", shoufa_info_doudizhu: - "当你受到伤害后/于一回合首次造成伤害后,你可以选择一名角色,令其随机执行以下一项:豹,令其受到1点无来源伤害;鹰,你随机获得其一张牌;熊,你随机弃置其装备区的一张牌;兔,令其摸一张牌。", + "当你受到伤害后/于一回合首次造成伤害后,你可以选择一名与你距离大于/不大于1的角色,令其随机执行以下一项:豹,令其受到1点无来源伤害;鹰,你随机获得其一张牌;熊,你随机弃置其装备区的一张牌;兔,令其摸一张牌。", yuxiang: "御象", yuxiang_info: "锁定技,若你有护甲值,则:①你计算与其他角色的距离-1,其他角色计算与你的距离+1;②当你受到火焰伤害时,此伤害+1。", diff --git a/character/offline.js b/character/offline.js index f606dda500..662a28be9e 100644 --- a/character/offline.js +++ b/character/offline.js @@ -4049,6 +4049,7 @@ game.import("character", function () { result: { player: 1, }, + combo: "zyquanji" }, }, //孙綝 @@ -6954,6 +6955,9 @@ game.import("character", function () { player.loseToDiscardpile(cards); if (num <= 1) player.draw(); }, + ai: { + combo: "spyicong" + }, }, sptuji2: { onremove: true, diff --git a/character/old.js b/character/old.js index a4f2eaeed9..aaf9d071f3 100755 --- a/character/old.js +++ b/character/old.js @@ -1169,7 +1169,13 @@ game.import("character", function () { content: function () { player.addToExpansion(cards, player, "give").gaintag.add("old_jijun"); }, - ai: { order: 1, result: { player: 1 } }, + ai: { + order: 1, + result: { + player: 1 + }, + combo: "old_fangtong" + }, }, old_fangtong: { trigger: { @@ -1186,6 +1192,9 @@ game.import("character", function () { var winners = player.getFriends(); game.over(player == game.me || winners.includes(game.me)); }, + ai:{ + combo: "oldjijun" + }, }, oldanxu: { enable: "phaseUse", diff --git a/character/rank.js b/character/rank.js index 04ecef1a0c..3ad34972e2 100644 --- a/character/rank.js +++ b/character/rank.js @@ -1,6 +1,6 @@ window.noname_character_rank = { s: [ - 'sp_sunce', + "sp_sunce", "gjqt_bailitusu", "gjqt_beiluo", "gjqt_xieyi", @@ -1720,7 +1720,7 @@ window.noname_character_rank = { ], rarity: { legend: [ - 'sp_sunce', + "sp_sunce", "star_caoren", "dc_zhaoyun", "dc_caocao", diff --git a/character/sb.js b/character/sb.js index a294009df6..519e02fdca 100644 --- a/character/sb.js +++ b/character/sb.js @@ -890,7 +890,7 @@ game.import("character", function () { } = await player .chooseTarget( get.prompt("sbjieming"), - `令一名角色摸三张牌,然后其可以弃置任意张牌。若其弃置的牌数不大于${get.cnNumber( + `令一名角色摸四张牌,然后其可以弃置任意张牌。若其弃置的牌数不大于${get.cnNumber( num )}张,你失去1点体力。` ) @@ -921,7 +921,7 @@ game.import("character", function () { if (!bool) return; const target = targets[0]; player.logSkill("sbjieming", target); - await target.draw(3); + await target.draw(4); num = Math.max(1, player.getDamagedHp()); const { result: { bool: bool2, cards }, @@ -8984,7 +8984,7 @@ game.import("character", function () { "出牌阶段限一次。你可以选择两名有牌的其他角色,你与这些角色同时将任意张牌扣置于武将牌上。若你以此法扣置的牌唯一最少,则扣置牌最多的其他角色获得你扣置的牌,且这些角色获得各自扣置的牌;否则这两名角色中扣置牌较多的角色对较少的角色造成1点伤害,获得你扣置的牌,然后这些角色将各自扣置的牌置入弃牌堆(若这两名角色扣置的牌数相同,视为与你逆时针最近座次的角色扣置牌较多)。", sbjieming: "节命", sbjieming_info: - "当你受到伤害后,你可以令一名角色摸三张牌,然后其可以弃置任意张牌。若其弃置的牌数不大于X,你失去1点体力(X为你已损失的体力值,至少为1)。", + "当你受到伤害后,你可以令一名角色摸四张牌,然后其可以弃置任意张牌。若其弃置的牌数不大于X,你失去1点体力(X为你已损失的体力值,至少为1)。", sb_xiahoudun: "谋夏侯惇", sb_xiahoudun_prefix: "谋", sbganglie: "刚烈", diff --git a/character/shiji.js b/character/shiji.js index acf6dddf13..88ed695d2c 100644 --- a/character/shiji.js +++ b/character/shiji.js @@ -3554,6 +3554,9 @@ game.import("character", function () { "step 1"; player.addSkills("xinmouli"); }, + ai: { + combo: "xingqi" + }, group: ["mibei_fail", "mibei_silent"], derivation: "xinmouli", subSkill: { diff --git a/character/sp.js b/character/sp.js index 0caadc3a33..1654df0524 100755 --- a/character/sp.js +++ b/character/sp.js @@ -18,6 +18,7 @@ game.import("character", function () { "tengfanglan", "ruiji", "caoxiancaohua", + "caoyu", ], sp_sibi: [ "ol_lukai", @@ -143,7 +144,7 @@ game.import("character", function () { "sp_zhangliao", "sp_ol_zhanghe", "sp_menghuo", - 'sp_sunce', + "sp_sunce", ], sp_qifu: [ "ol_feiyi", @@ -168,7 +169,6 @@ game.import("character", function () { "ol_tw_zhangji", "ol_liwan", "ol_liuyan", - "caoyu", "liupan", "ol_liupi", ], @@ -184,12 +184,12 @@ game.import("character", function () { ol_mengda(mode) { return mode !== "guozhan"; }, - ol_mengda(mode){ - return mode!=='guozhan'; + ol_mengda(mode) { + return mode !== "guozhan"; }, }, character: { - sp_sunce:['male','qun',4,['olliantao']], + sp_sunce: ["male", "qun", 4, ["olliantao"]], ol_liupi: ["male", "qun", 4, ["olyicheng"]], ol_lukai: ["male", "wu", 3, ["olxuanzhu", "oljiane"]], liupan: ["male", "qun", 4, ["olpijing"]], @@ -968,117 +968,177 @@ game.import("character", function () { }, skill: { //SP孙策 - olliantao:{ - audio:2, - trigger:{player:'phaseUseBegin'}, - filter(event,player){ - return game.hasPlayer(target=>target!=player); - }, - async cost(event,trigger,player){ - event.result=await player.chooseTarget(get.prompt2('olliantao'),lib.filter.notMe).set('ai',target=>{ - const player=get.event('player'),att=get.attitude(player,target); - const colors=Object.keys(lib.color).filter(i=>i!='none'); - if(!colors.some(color=>player.hasCard(card=>{ - const juedou=get.autoViewAs({name:'juedou'},[card]); - return player.canUse(juedou,target,false); - },'h'))) return 20+(3-get.sgn(att))+Math.random(); - const effs=colors.reduce((list,color)=>{ - const cards=player.getCards('h',card=>{ - const juedou=get.autoViewAs({name:'juedou'},[card]); - return player.canUse(juedou,target,false); - }); - if(cards.length){ - list.push(cards.reduce((sum,card)=>{ - const juedou=get.autoViewAs({name:'juedou'},[card]); - return sum+get.effect(target,card,player,player); - },0)); - } - return list; - },[]); - return Math[att>0?'max':'min'].apply(Math,list); - }).forResult(); - }, - async content(event,trigger,player){ - const target=event.targets[0]; - const colors=Object.keys(lib.color).filter(i=>i!='none'); - if(colors.length&&player.countCards('h')){ - const result=await target.chooseControl(colors) - .set('prompt','连讨:请选择一个颜色').set('ai',()=>{ - const player=get.event('player'),source=get.event().getParent().player; - let controls=get.event('controls').slice(); - if(controls.length==1) return controls[0]; - const getSum=function(color,player,source){ - return source.getCards('h',card=>{ - if(get.color(card)!=color) return false; - const juedou=get.autoViewAs({name:'juedou'},[card]); - return source.canUse(juedou,player,false); - }).reduce((num,card)=>{ - const juedou=get.autoViewAs({name:'juedou'},[card]); - return num+get.effect(player,card,source,player); - },0); - }; - return controls.sort((a,b)=>getSum(b,player,source)-getSum(a,player,source))[0]; - }).set('prompt2',get.translation(player)+'将对你依次使用由其手牌中所有此颜色的牌转化的【决斗】').forResult(); - const color=result.control; - game.broadcastAll((color,target)=>{ - lib.skill.olliantao_backup.filterCardx=[color,target]; - lib.skill.olliantao_backup.filterCard=function(card,player){ - const list=lib.skill.olliantao_backup.filterCardx; - if(get.color(card)!=list[0]) return false; - const juedou=get.autoViewAs({name:'juedou'},[card]); - return player.canUse(juedou,list[1],false); - }; - },color,target); - while(target.isIn()&&player.hasCard(card=>lib.skill.olliantao_backup.filterCard(card,player))&&!game.getGlobalHistory('everything',evt=>{ - return evt.name=='dying'&&[player,target].includes(evt.player)&&evt.getParent('olliantao')==event; - }).length){ - await player.chooseToUse().set('forced',true) - .set('openskilldialog','连讨:将一张'+get.translation(color)+'手牌当作【决斗】对'+get.translation(target)+'使用') - .set('norestore',true).set('_backupevent','olliantao_backup').set('custom',{ - add:{}, - replace:{window:function(){}}, - }).backup('olliantao_backup').set('targetRequired',true).set('complexSelect',true) - .set('filterTarget',function(card,player,target){ - if(target!=_status.event.sourcex&&!ui.selected.targets.includes(_status.event.sourcex)) return false; - return lib.filter.targetEnabled.apply(this, arguments); - }).set('sourcex',target).set('addCount',false); - } - } - const num=player.getHistory('sourceDamage',evt=>{ - return evt.getParent(4)==event; - }).reduce((sum,evt)=>sum+evt.num,0); - if(num) await player.draw(num); - if(!game.hasPlayer2(current=>{ - return current.getHistory('damage',evt=>{ - return evt.getParent(4)==event; - }).length; - })){ + olliantao: { + audio: 2, + trigger: { player: "phaseUseBegin" }, + filter(event, player) { + return game.hasPlayer((target) => target != player); + }, + async cost(event, trigger, player) { + event.result = await player + .chooseTarget(get.prompt2("olliantao"), lib.filter.notMe) + .set("ai", (target) => { + const player = get.event("player"), + att = get.attitude(player, target); + const colors = Object.keys(lib.color).filter((i) => i != "none"); + if ( + !colors.some((color) => + player.hasCard((card) => { + const juedou = get.autoViewAs({ name: "juedou" }, [card]); + return player.canUse(juedou, target, false); + }, "h") + ) + ) + return 20 + (3 - get.sgn(att)) + Math.random(); + const effs = colors.reduce((list, color) => { + const cards = player.getCards("h", (card) => { + const juedou = get.autoViewAs({ name: "juedou" }, [card]); + return player.canUse(juedou, target, false); + }); + if (cards.length) { + list.push( + cards.reduce((sum, card) => { + const juedou = get.autoViewAs({ name: "juedou" }, [card]); + return sum + get.effect(target, juedou, player, player); + }, 0) + ); + } + return list; + }, []); + return Math[att > 0 ? "max" : "min"].apply(Math, list); + }) + .forResult(); + }, + async content(event, trigger, player) { + const target = event.targets[0]; + const colors = Object.keys(lib.color).filter((i) => i != "none"); + if (colors.length && player.countCards("h")) { + const result = await target + .chooseControl(colors) + .set("prompt", "连讨:请选择一个颜色") + .set("ai", () => { + const player = get.event("player"), + source = get.event().getParent().player; + let controls = get.event("controls").slice(); + if (controls.length == 1) return controls[0]; + const getSum = function (color, player, source) { + return source + .getCards("h", (card) => { + if (get.color(card) != color) return false; + const juedou = get.autoViewAs({ name: "juedou" }, [card]); + return source.canUse(juedou, player, false); + }) + .reduce((num, card) => { + const juedou = get.autoViewAs({ name: "juedou" }, [card]); + return num + get.effect(player, juedou, source, player); + }, 0); + }; + return controls.sort( + (a, b) => getSum(b, player, source) - getSum(a, player, source) + )[0]; + }) + .set( + "prompt2", + get.translation(player) + + "将对你依次使用由其手牌中所有此颜色的牌转化的【决斗】" + ) + .forResult(); + const color = result.control; + game.broadcastAll( + (color, target) => { + lib.skill.olliantao_backup.filterCardx = [color, target]; + lib.skill.olliantao_backup.filterCard = function (card, player) { + const list = lib.skill.olliantao_backup.filterCardx; + if (get.color(card) != list[0]) return false; + const juedou = get.autoViewAs({ name: "juedou" }, [card]); + return player.canUse(juedou, list[1], false); + }; + }, + color, + target + ); + while ( + target.isIn() && + player.hasCard((card) => lib.skill.olliantao_backup.filterCard(card, player)) && + !game.getGlobalHistory("everything", (evt) => { + return ( + evt.name == "dying" && + [player, target].includes(evt.player) && + evt.getParent("olliantao") == event + ); + }).length + ) { + await player + .chooseToUse() + .set("forced", true) + .set( + "openskilldialog", + "连讨:将一张" + + get.translation(color) + + "手牌当作【决斗】对" + + get.translation(target) + + "使用" + ) + .set("norestore", true) + .set("_backupevent", "olliantao_backup") + .set("custom", { + add: {}, + replace: { window: function () {} }, + }) + .backup("olliantao_backup") + .set("targetRequired", true) + .set("complexSelect", true) + .set("filterTarget", function (card, player, target) { + if ( + target != _status.event.sourcex && + !ui.selected.targets.includes(_status.event.sourcex) + ) + return false; + return lib.filter.targetEnabled.apply(this, arguments); + }) + .set("sourcex", target) + .set("addCount", false); + } + } + const num = player + .getHistory("sourceDamage", (evt) => { + return evt.getParent(4) == event; + }) + .reduce((sum, evt) => sum + evt.num, 0); + if (num) await player.draw(num); + if ( + !game.hasPlayer2((current) => { + return current.getHistory("damage", (evt) => { + return evt.getParent(4) == event; + }).length; + }) + ) { await player.draw(3); - player.addTempSkill('olliantao_buff'); - player.addMark('olliantao_buff',3,false); + player.addTempSkill("olliantao_buff"); + player.addMark("olliantao_buff", 3, false); } }, - subSkill:{ - backup:{ - viewAs:{name:'juedou'}, - position:'h', - check:()=>1+Math.random(), - precontent(){ + subSkill: { + backup: { + viewAs: { name: "juedou" }, + position: "h", + check: () => 1 + Math.random(), + precontent() { delete event.result.skill; }, }, - buff:{ - charlotte:true, - onremove:true, - mod:{ - maxHandcard(player,num){ - return num+player.countMark('olliantao_buff'); + buff: { + charlotte: true, + onremove: true, + mod: { + maxHandcard(player, num) { + return num + player.countMark("olliantao_buff"); }, - cardEnabled(card){ - if(card.name=='sha') return false; + cardEnabled(card) { + if (card.name == "sha") return false; }, }, - intro:{content:'手牌上限+#,不能使用【杀】'}, + intro: { content: "手牌上限+#,不能使用【杀】" }, }, }, }, @@ -1088,7 +1148,7 @@ game.import("character", function () { enable: "phaseUse", usable: 1, async content(event, trigger, player) { - let cards = get.cards(3); + let num = player.maxHp, cards = get.cards(num); await game.cardsGotoOrdering(cards); await player.showCards(cards, get.translation(player) + "发动了【易城】"); if (player.countCards("h")) { @@ -1121,7 +1181,7 @@ game.import("character", function () { .set("filterOk", (moved) => moved[1].some((i) => !get.owner(i))) .set("processAI", (list) => { const player = get.event("player"), - limit = Math.min(3, player.countCards("h")); + limit = Math.min(get.event("num"), player.countCards("h")); let cards = list[0][1].slice(), hs = player.getCards("h"); if ( @@ -1156,7 +1216,8 @@ game.import("character", function () { } return list; } - }); + }) + .set("num", num); if (bool) { const puts = player.getCards("h", (i) => moved[0].includes(i)); const gains = cards.filter((i) => moved[1].includes(i)); @@ -2606,18 +2667,18 @@ game.import("character", function () { if (!ui.selected.targets.length) return 0; const target = ui.selected.targets[0]; if ( - player.getHistory("useSkill", (evt) => { + player.hasAllHistory("useSkill", (evt) => { return ( evt.skill == "olgongjie" && (evt.targets || [evt.target]).includes(target) ); - }).length && - player.getHistory("useSkill", (evt) => { + }) && + player.hasAllHistory("useSkill", (evt) => { return ( evt.skill == "olxiangxv" && (evt.targets || [evt.target]).includes(target) ); - }).length + }) ) { if (get.attitude(player, target) > 0) return 1; if (player.canSaveCard(card, player)) return 0; @@ -2634,18 +2695,18 @@ game.import("character", function () { ai2(target) { const player = get.event("player"); const goon = - player.getHistory("useSkill", (evt) => { + player.hasAllHistory("useSkill", (evt) => { return ( evt.skill == "olgongjie" && (evt.targets || [evt.target]).includes(target) ); - }).length && - player.getHistory("useSkill", (evt) => { + }) && + player.hasAllHistory("useSkill", (evt) => { return ( evt.skill == "olxiangxv" && (evt.targets || [evt.target]).includes(target) ); - }).length, + }), att = get.attitude(player, target); if (goon) return 5 * att; if (!!player.countCards("he", (cardx) => player.canSaveCard(cardx, player))) @@ -2664,12 +2725,12 @@ game.import("character", function () { player.awakenSkill("olxiangzuo"); await player.give(cards, target); if ( - player.getHistory("useSkill", (evt) => { + player.hasAllHistory("useSkill", (evt) => { return evt.skill == "olgongjie" && evt.targets.includes(target); - }).length && - player.getHistory("useSkill", (evt) => { + }) && + player.hasAllHistory("useSkill", (evt) => { return evt.skill == "olxiangxv" && evt.targets.includes(target); - }).length + }) ) await player.recover(cards.length); }, @@ -3056,7 +3117,7 @@ game.import("character", function () { ? "" : `。若${get.translation( trigger.player - )}受到了此【杀】的伤害,你获得其一张牌。` + )}受到了此【杀】的伤害,你获得其一张牌。` }` ); next.set("norestore", true); @@ -3395,9 +3456,8 @@ game.import("character", function () { ]; [0, 1, 2].forEach((item, index) => { if (event.list.includes(item)) { - choiceList[ - index - ] = `${choiceList[index]}`; + choiceList[index] = + `${choiceList[index]}`; } else choices.push(`选项${get.cnNumber(index + 1, true)}`); }); game.me @@ -7028,7 +7088,7 @@ game.import("character", function () { delete stat.gushe; }, ai: { - combo: "gushe" + combo: "gushe", }, }, //OL刘老板 @@ -12778,10 +12838,13 @@ game.import("character", function () { (_status.connectMode || current.hasSha()) ) { current - .chooseToUse(function (card, player, event) { - if (get.name(card) != "sha") return false; - return lib.filter.filterCard.apply(this, arguments); - }, "同协:是否对" + get.translation(target) + "使用一张杀?") + .chooseToUse( + function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, + "同协:是否对" + get.translation(target) + "使用一张杀?" + ) .set("targetRequired", true) .set("complexSelect", true) .set("filterTarget", function (card, player, target) { @@ -14430,6 +14493,10 @@ game.import("character", function () { "的选项" ); }, + ai: { + combo: "luochong", + neg: true + }, }, //SP孟获 spmanwang: { @@ -17318,10 +17385,13 @@ game.import("character", function () { "step 0"; var target = trigger.targets[0]; target - .chooseToUse(function (card, player, event) { - if (get.name(card) != "sha") return false; - return lib.filter.filterCard.apply(this, arguments); - }, "武娘:是否对" + get.translation(player) + "使用一张杀?") + .chooseToUse( + function (card, player, event) { + if (get.name(card) != "sha") return false; + return lib.filter.filterCard.apply(this, arguments); + }, + "武娘:是否对" + get.translation(player) + "使用一张杀?" + ) .set("targetRequired", true) .set("complexSelect", true) .set("filterTarget", function (card, player, target) { @@ -21948,7 +22018,7 @@ game.import("character", function () { }, }, ai: { - combo: "wylianji" + combo: "wylianji", }, }, jingong: { @@ -28882,7 +28952,7 @@ game.import("character", function () { player.changeSkills(["xiaoji"], ["liangzhu"]); }, ai: { - combo: "liangzhu" + combo: "liangzhu", }, }, mingshi: { @@ -31423,6 +31493,7 @@ game.import("character", function () { }, usable: 1, direct: true, + derivation: ["lingren_jianxiong", "lingren_xingshang"], content: function () { "step 0"; player @@ -32577,6 +32648,9 @@ game.import("character", function () { player.gain(event.togain, "gain2"); } }, + ai: { + combo: "xinfu_falu" + }, }, zhenyi_spade: { trigger: { @@ -32783,7 +32857,7 @@ game.import("character", function () { }, spmanwang: function (player) { var num = 4 - player.countMark("spmanwang"); - var str = "出牌阶段,你可以弃置任意张牌。然后你依次执行以下选项中的前X项:"; + var str = "出牌阶段,你可以弃置任意张牌。然后你依次执行以下选项中的前等量项:"; var list = ["⒈获得〖叛侵〗。", "⒉摸一张牌。", "⒊回复1点体力。", "⒋摸两张牌并失去〖叛侵〗。"]; for (var i = 0; i < 4; i++) { if (i == num) { @@ -34465,7 +34539,7 @@ game.import("character", function () { "当你的手牌数变为全场最少时,你可以获得以下效果:本回合结束时,将手牌数调整至与当前回合角色手牌数相同(至多摸至五张),然后若你以此法弃置了至少两张手牌,则你回复1点体力。", olxiangzuo: "襄胙", olxiangzuo_info: - "限定技,当你进入濒死状态时,你可以交给一名其他角色任意张牌,然后若你本回合已对其发动过〖恭节〗和〖相胥〗,你回复等量的体力。", + "限定技,当你进入濒死状态时,你可以交给一名其他角色任意张牌,然后若你已对其发动过〖恭节〗和〖相胥〗,你回复等量的体力。", liyi: "李异", olchanshuang: "缠双", olchanshuang_info: @@ -34504,11 +34578,12 @@ game.import("character", function () { ol_liupi: "刘辟", olyicheng: "易城", olyicheng_info: - "出牌阶段限一次,你可以亮出牌堆顶的三张牌,然后你可以以任意手牌交换这些牌,若这三张牌的点数和因此增加,则你可以选择用所有手牌交换这三张牌。最后你将这三张牌置于牌堆顶。", - sp_sunce:'SP孙策', - sp_sunce_prefix:'SP', - olliantao:'连讨', - olliantao_info:'出牌阶段开始时,你可以令一名其他角色选择一个颜色,然后你依次将此颜色的所有手牌当作【决斗】对其使用直到有一方进入濒死状态,然后你摸X张牌(X为你本次以此法造成的伤害数)。若没有角色因本次技能结算受到伤害,你摸三张牌,本回合手牌上限+3且本回合你不能使用【杀】。', + "出牌阶段限一次,你可以亮出牌堆顶的X张牌(X为你的体力上限),然后你可以以任意手牌交换其中等量张牌,若亮出的牌的点数和因此增加,则你可以选择用所有手牌交换亮出的牌。最后你将亮出的牌置于牌堆顶。", + sp_sunce: "SP孙策", + sp_sunce_prefix: "SP", + olliantao: "连讨", + olliantao_info: + "出牌阶段开始时,你可以令一名其他角色选择一个颜色,然后你依次将此颜色的所有手牌当作【决斗】对其使用直到有一方进入濒死状态,然后你摸X张牌(X为你本次以此法造成的伤害数)。若没有角色因本次技能结算受到伤害,你摸三张牌,本回合手牌上限+3且本回合你不能使用【杀】。", sp_tianji: "天极·皇室宗亲", sp_sibi: "四弼·辅国文曲", diff --git a/character/sp2.js b/character/sp2.js index 6caefd98f7..de3e006b48 100644 --- a/character/sp2.js +++ b/character/sp2.js @@ -2448,7 +2448,7 @@ game.import("character", function () { } = await player.chooseButton(dialog, true).set("ai", (button) => { const player = get.event("player"), target = get.event().getParent().targets[0]; - return get.value(card, player) * get.value(card, target) * (1 + Math.random()); + return get.value(button.link, player) * get.value(button.link, target) * (1 + Math.random()); }); if (bool) { await player.gain(links, target, "giveAuto", "bySelf"); @@ -9794,6 +9794,9 @@ game.import("character", function () { player.markSkill("mubing_rewrite"); player.chooseDrawRecover(2, true); }, + ai: { + combo: "mubing" + }, derivation: "mubing_rewrite", }, refenyin_wufan: { audio: 2 }, diff --git a/character/standard.js b/character/standard.js index 0e8a9e9946..6f2226595a 100755 --- a/character/standard.js +++ b/character/standard.js @@ -279,6 +279,9 @@ game.import("character", function () { evt.targets.remove(trigger.target); evt.targets.push(player); }, + ai: { + neg: true + }, }, hujia: { audio: 2, @@ -2492,6 +2495,7 @@ game.import("character", function () { trigger.source.chooseDrawRecover(true); }, ai: { + halfneg: true, effect: { target(card, player, target, current) { if (card.name == "sha" && get.color(card) == "red") { diff --git a/character/tw.js b/character/tw.js index 9c1cc61cd0..e4e72e3109 100644 --- a/character/tw.js +++ b/character/tw.js @@ -18750,7 +18750,9 @@ game.import("character", function () { audio: 2, enable: "phaseUse", usable: 1, - filterTarget: lib.filter.notMe, + filterTarget: function (card, player, target) { + return target.hp >= player.hp; + }, content: function () { "step 0"; var str = get.translation(target); diff --git a/character/xianding.js b/character/xianding.js index aa1b34a2c7..efbc5c73b7 100644 --- a/character/xianding.js +++ b/character/xianding.js @@ -19631,7 +19631,7 @@ game.import("character", function () { zhugemengxue: "诸葛梦雪", dcjichun: "寄春", dcjichun_info: - "出牌阶段限一次,你可以展示一张手牌并选择一项:①将此牌交给一名手牌数小于你的角色,然后摸X张牌。②弃置此牌并弃置一名手牌数大于你的角色区域里至多X张牌。(X为此牌牌名字数)", + "出牌阶段限一次,你可以展示一张牌并选择一项:①将此牌交给一名手牌数小于你的角色,然后摸X张牌。②弃置此牌并弃置一名手牌数大于你的角色区域里至多X张牌。(X为此牌牌名字数)", dchanying: "寒英", dchanying_info: "准备阶段,你可以亮出牌堆里的一张非赠物装备牌,然后令一名手牌数等于你的角色使用此牌。", diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000000..127cec053a --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,39 @@ +import js from "@eslint/js"; +import globals from "globals"; + +export default [ + js.configs.recommended, + { + rules: { + "no-console": 0, + "no-constant-condition": [ + "error", + { + checkLoops: false, + }, + ], + "no-irregular-whitespace": [ + "error", + { + skipStrings: true, + skipTemplates: true, + }, + ], + "no-redeclare": 0, + "no-undef": 0, + "no-unused-vars": 0, + "require-yield": 0, + }, + languageOptions: { + ecmaVersion: 13, + sourceType: "module", + globals: { + ...globals.browser, + ...globals.es2015, + ...globals.node, + ...globals.serviceworker, + ...globals.worker, + }, + }, + }, +]; diff --git a/game/update.js b/game/update.js index 3ad3d7dbe6..374e6f21fa 100644 --- a/game/update.js +++ b/game/update.js @@ -1,13 +1,9 @@ window.noname_update = { - version: "1.10.11.1", + version: "1.10.11.2", update: "NULL", //新版本更新文件较多,直接强制进行全量更新 changeLog: [ - "整合@Rintim @mengxinzxz @nonameShijian @lieren2023 @itsnoteasytonameaccount @kuangshen04 @IceCola97 @PZ157 @universe-st @Iking123 @copcap @nineMangos 的Pull Request", - "OL族王广、族王明山、界王异、刘辟、SP孙策;十周年曹芳、武关羽、神华佗、SP甄姬", - "手杀SP毌丘俭、曹髦、成济、李昭&焦伯;海外服颜良、文丑、袁谭", - "添加“无限火力”单挑模式", - "拆分“技能的消耗”和“技能的效果”,加入“按点卖血”等同时机多次发动技能的机制,逐步淘汰direct:true的写法", - "其他AI优化与bug修复", + "整合@Rintim @nonameShijian @copcap @PZ157 @mengxinzxz @lieren2023 的Pull Request", + "bug修复", ], files: [], }; diff --git a/mode/versus.js b/mode/versus.js index 952c2dc8c0..8a1967da4f 100644 --- a/mode/versus.js +++ b/mode/versus.js @@ -1248,14 +1248,14 @@ game.import("mode", function (lib, game, ui, get, ai, _status) { next.setContent(function () { "step 0"; ui.arena.classList.add("choose-character"); - for (var i in lib.skill) { - if (lib.skill[i].changeSeat) { - lib.skill[i] = {}; - if (lib.translate[i + "_info"]) { - lib.translate[i + "_info"] = "此模式下不可用"; - } - } - } + // for (var i in lib.skill) { + // if (lib.skill[i].changeSeat) { + // lib.skill[i] = {}; + // if (lib.translate[i + "_info"]) { + // lib.translate[i + "_info"] = "此模式下不可用"; + // } + // } + // } var bool = Math.random() < 0.5; var bool2 = Math.random() < 0.5; var ref = game.players[0]; diff --git a/node_modules/@types/noname-typings/cordova-plugin-android-permissions.d.ts b/node_modules/@types/noname-typings/cordova-plugin-android-permissions.d.ts new file mode 100644 index 0000000000..7c8af5f8b5 --- /dev/null +++ b/node_modules/@types/noname-typings/cordova-plugin-android-permissions.d.ts @@ -0,0 +1,197 @@ +// from npm @types/cordova-plugin-android-permissions + +interface PermissionStatus { + hasPermission: boolean; +} + +interface Permissions { + ACCESS_CHECKIN_PROPERTIES: "android.permission.ACCESS_CHECKIN_PROPERTIES"; + ACCESS_BACKGROUND_LOCATION: "android.permission.ACCESS_BACKGROUND_LOCATION"; + ACCESS_COARSE_LOCATION: "android.permission.ACCESS_COARSE_LOCATION"; + ACCESS_FINE_LOCATION: "android.permission.ACCESS_FINE_LOCATION"; + ACCESS_LOCATION_EXTRA_COMMANDS: "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"; + ACCESS_MOCK_LOCATION: "android.permission.ACCESS_MOCK_LOCATION"; + ACCESS_NETWORK_STATE: "android.permission.ACCESS_NETWORK_STATE"; + ACCESS_SURFACE_FLINGER: "android.permission.ACCESS_SURFACE_FLINGER"; + ACCESS_WIFI_STATE: "android.permission.ACCESS_WIFI_STATE"; + ACCOUNT_MANAGER: "android.permission.ACCOUNT_MANAGER"; + ACTIVITY_RECOGNITION: "android.permission.ACTIVITY_RECOGNITION"; + ADD_VOICEMAIL: "com.android.voicemail.permission.ADD_VOICEMAIL"; + AUTHENTICATE_ACCOUNTS: "android.permission.AUTHENTICATE_ACCOUNTS"; + BATTERY_STATS: "android.permission.BATTERY_STATS"; + BIND_ACCESSIBILITY_SERVICE: "android.permission.BIND_ACCESSIBILITY_SERVICE"; + BIND_APPWIDGET: "android.permission.BIND_APPWIDGET"; + BIND_CARRIER_MESSAGING_SERVICE: "android.permission.BIND_CARRIER_MESSAGING_SERVICE"; + BIND_DEVICE_ADMIN: "android.permission.BIND_DEVICE_ADMIN"; + BIND_DREAM_SERVICE: "android.permission.BIND_DREAM_SERVICE"; + BIND_INPUT_METHOD: "android.permission.BIND_INPUT_METHOD"; + BIND_NFC_SERVICE: "android.permission.BIND_NFC_SERVICE"; + BIND_NOTIFICATION_LISTENER_SERVICE: "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"; + BIND_PRINT_SERVICE: "android.permission.BIND_PRINT_SERVICE"; + BIND_REMOTEVIEWS: "android.permission.BIND_REMOTEVIEWS"; + BIND_TEXT_SERVICE: "android.permission.BIND_TEXT_SERVICE"; + BIND_TV_INPUT: "android.permission.BIND_TV_INPUT"; + BIND_VOICE_INTERACTION: "android.permission.BIND_VOICE_INTERACTION"; + BIND_VPN_SERVICE: "android.permission.BIND_VPN_SERVICE"; + BIND_WALLPAPER: "android.permission.BIND_WALLPAPER"; + BLUETOOTH: "android.permission.BLUETOOTH"; + BLUETOOTH_ADMIN: "android.permission.BLUETOOTH_ADMIN"; + BLUETOOTH_ADVERTISE: "android.permission.BLUETOOTH_ADVERTISE"; + BLUETOOTH_CONNECT: "android.permission.BLUETOOTH_CONNECT"; + BLUETOOTH_PRIVILEGED: "android.permission.BLUETOOTH_PRIVILEGED"; + BLUETOOTH_SCAN: "android.permission.BLUETOOTH_SCAN"; + BODY_SENSORS: "android.permission.BODY_SENSORS"; + BRICK: "android.permission.BRICK"; + BROADCAST_PACKAGE_REMOVED: "android.permission.BROADCAST_PACKAGE_REMOVED"; + BROADCAST_SMS: "android.permission.BROADCAST_SMS"; + BROADCAST_STICKY: "android.permission.BROADCAST_STICKY"; + BROADCAST_WAP_PUSH: "android.permission.BROADCAST_WAP_PUSH"; + CALL_PHONE: "android.permission.CALL_PHONE"; + CALL_PRIVILEGED: "android.permission.CALL_PRIVILEGED"; + CAMERA: "android.permission.CAMERA"; + CAPTURE_AUDIO_OUTPUT: "android.permission.CAPTURE_AUDIO_OUTPUT"; + CAPTURE_SECURE_VIDEO_OUTPUT: "android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"; + CAPTURE_VIDEO_OUTPUT: "android.permission.CAPTURE_VIDEO_OUTPUT"; + CHANGE_COMPONENT_ENABLED_STATE: "android.permission.CHANGE_COMPONENT_ENABLED_STATE"; + CHANGE_CONFIGURATION: "android.permission.CHANGE_CONFIGURATION"; + CHANGE_NETWORK_STATE: "android.permission.CHANGE_NETWORK_STATE"; + CHANGE_WIFI_MULTICAST_STATE: "android.permission.CHANGE_WIFI_MULTICAST_STATE"; + CHANGE_WIFI_STATE: "android.permission.CHANGE_WIFI_STATE"; + CLEAR_APP_CACHE: "android.permission.CLEAR_APP_CACHE"; + CLEAR_APP_USER_DATA: "android.permission.CLEAR_APP_USER_DATA"; + CONTROL_LOCATION_UPDATES: "android.permission.CONTROL_LOCATION_UPDATES"; + DELETE_CACHE_FILES: "android.permission.DELETE_CACHE_FILES"; + DELETE_PACKAGES: "android.permission.DELETE_PACKAGES"; + DEVICE_POWER: "android.permission.DEVICE_POWER"; + DIAGNOSTIC: "android.permission.DIAGNOSTIC"; + DISABLE_KEYGUARD: "android.permission.DISABLE_KEYGUARD"; + DUMP: "android.permission.DUMP"; + EXPAND_STATUS_BAR: "android.permission.EXPAND_STATUS_BAR"; + FACTORY_TEST: "android.permission.FACTORY_TEST"; + FLASHLIGHT: "android.permission.FLASHLIGHT"; + FORCE_BACK: "android.permission.FORCE_BACK"; + GET_ACCOUNTS: "android.permission.GET_ACCOUNTS"; + GET_PACKAGE_SIZE: "android.permission.GET_PACKAGE_SIZE"; + GET_TASKS: "android.permission.GET_TASKS"; + GET_TOP_ACTIVITY_INFO: "android.permission.GET_TOP_ACTIVITY_INFO"; + GLOBAL_SEARCH: "android.permission.GLOBAL_SEARCH"; + HARDWARE_TEST: "android.permission.HARDWARE_TEST"; + INJECT_EVENTS: "android.permission.INJECT_EVENTS"; + INSTALL_LOCATION_PROVIDER: "android.permission.INSTALL_LOCATION_PROVIDER"; + INSTALL_PACKAGES: "android.permission.INSTALL_PACKAGES"; + INSTALL_SHORTCUT: "com.android.launcher.permission.INSTALL_SHORTCUT"; + INTERNAL_SYSTEM_WINDOW: "android.permission.INTERNAL_SYSTEM_WINDOW"; + INTERNET: "android.permission.INTERNET"; + KILL_BACKGROUND_PROCESSES: "android.permission.KILL_BACKGROUND_PROCESSES"; + LOCATION_HARDWARE: "android.permission.LOCATION_HARDWARE"; + MANAGE_ACCOUNTS: "android.permission.MANAGE_ACCOUNTS"; + MANAGE_APP_TOKENS: "android.permission.MANAGE_APP_TOKENS"; + MANAGE_DOCUMENTS: "android.permission.MANAGE_DOCUMENTS"; + MASTER_CLEAR: "android.permission.MASTER_CLEAR"; + MEDIA_CONTENT_CONTROL: "android.permission.MEDIA_CONTENT_CONTROL"; + MODIFY_AUDIO_SETTINGS: "android.permission.MODIFY_AUDIO_SETTINGS"; + MODIFY_PHONE_STATE: "android.permission.MODIFY_PHONE_STATE"; + MOUNT_FORMAT_FILESYSTEMS: "android.permission.MOUNT_FORMAT_FILESYSTEMS"; + MOUNT_UNMOUNT_FILESYSTEMS: "android.permission.MOUNT_UNMOUNT_FILESYSTEMS"; + NFC: "android.permission.NFC"; + PERSISTENT_ACTIVITY: "android.permission.PERSISTENT_ACTIVITY"; + POST_NOTIFICATIONS: "android.permission.POST_NOTIFICATIONS"; + PROCESS_OUTGOING_CALLS: "android.permission.PROCESS_OUTGOING_CALLS"; + READ_CALENDAR: "android.permission.READ_CALENDAR"; + READ_CALL_LOG: "android.permission.READ_CALL_LOG"; + READ_CONTACTS: "android.permission.READ_CONTACTS"; + READ_EXTERNAL_STORAGE: "android.permission.READ_EXTERNAL_STORAGE"; + READ_FRAME_BUFFER: "android.permission.READ_FRAME_BUFFER"; + READ_HISTORY_BOOKMARKS: "com.android.browser.permission.READ_HISTORY_BOOKMARKS"; + READ_INPUT_STATE: "android.permission.READ_INPUT_STATE"; + READ_LOGS: "android.permission.READ_LOGS"; + READ_MEDIA_AUDIO: "android.permission.READ_MEDIA_AUDIO"; + READ_MEDIA_IMAGES: "android.permission.READ_MEDIA_IMAGES"; + READ_MEDIA_VIDEO: "android.permission.READ_MEDIA_VIDEO"; + READ_PHONE_STATE: "android.permission.READ_PHONE_STATE"; + READ_PROFILE: "android.permission.READ_PROFILE"; + READ_SMS: "android.permission.READ_SMS"; + READ_SOCIAL_STREAM: "android.permission.READ_SOCIAL_STREAM"; + READ_SYNC_SETTINGS: "android.permission.READ_SYNC_SETTINGS"; + READ_SYNC_STATS: "android.permission.READ_SYNC_STATS"; + READ_USER_DICTIONARY: "android.permission.READ_USER_DICTIONARY"; + READ_VOICEMAIL: "com.android.voicemail.permission.READ_VOICEMAIL"; + REBOOT: "android.permission.REBOOT"; + RECEIVE_BOOT_COMPLETED: "android.permission.RECEIVE_BOOT_COMPLETED"; + RECEIVE_MMS: "android.permission.RECEIVE_MMS"; + RECEIVE_SMS: "android.permission.RECEIVE_SMS"; + RECEIVE_WAP_PUSH: "android.permission.RECEIVE_WAP_PUSH"; + RECORD_AUDIO: "android.permission.RECORD_AUDIO"; + REORDER_TASKS: "android.permission.REORDER_TASKS"; + RESTART_PACKAGES: "android.permission.RESTART_PACKAGES"; + SEND_RESPOND_VIA_MESSAGE: "android.permission.SEND_RESPOND_VIA_MESSAGE"; + SEND_SMS: "android.permission.SEND_SMS"; + SET_ACTIVITY_WATCHER: "android.permission.SET_ACTIVITY_WATCHER"; + SET_ALARM: "com.android.alarm.permission.SET_ALARM"; + SET_ALWAYS_FINISH: "android.permission.SET_ALWAYS_FINISH"; + SET_ANIMATION_SCALE: "android.permission.SET_ANIMATION_SCALE"; + SET_DEBUG_APP: "android.permission.SET_DEBUG_APP"; + SET_ORIENTATION: "android.permission.SET_ORIENTATION"; + SET_POINTER_SPEED: "android.permission.SET_POINTER_SPEED"; + SET_PREFERRED_APPLICATIONS: "android.permission.SET_PREFERRED_APPLICATIONS"; + SET_PROCESS_LIMIT: "android.permission.SET_PROCESS_LIMIT"; + SET_TIME: "android.permission.SET_TIME"; + SET_TIME_ZONE: "android.permission.SET_TIME_ZONE"; + SET_WALLPAPER: "android.permission.SET_WALLPAPER"; + SET_WALLPAPER_HINTS: "android.permission.SET_WALLPAPER_HINTS"; + SIGNAL_PERSISTENT_PROCESSES: "android.permission.SIGNAL_PERSISTENT_PROCESSES"; + STATUS_BAR: "android.permission.STATUS_BAR"; + SUBSCRIBED_FEEDS_READ: "android.permission.SUBSCRIBED_FEEDS_READ"; + SUBSCRIBED_FEEDS_WRITE: "android.permission.SUBSCRIBED_FEEDS_WRITE"; + SYSTEM_ALERT_WINDOW: "android.permission.SYSTEM_ALERT_WINDOW"; + TRANSMIT_IR: "android.permission.TRANSMIT_IR"; + UNINSTALL_SHORTCUT: "com.android.launcher.permission.UNINSTALL_SHORTCUT"; + UPDATE_DEVICE_STATS: "android.permission.UPDATE_DEVICE_STATS"; + USE_CREDENTIALS: "android.permission.USE_CREDENTIALS"; + USE_SIP: "android.permission.USE_SIP"; + VIBRATE: "android.permission.VIBRATE"; + WAKE_LOCK: "android.permission.WAKE_LOCK"; + WRITE_APN_SETTINGS: "android.permission.WRITE_APN_SETTINGS"; + WRITE_CALENDAR: "android.permission.WRITE_CALENDAR"; + WRITE_CALL_LOG: "android.permission.WRITE_CALL_LOG"; + WRITE_CONTACTS: "android.permission.WRITE_CONTACTS"; + WRITE_EXTERNAL_STORAGE: "android.permission.WRITE_EXTERNAL_STORAGE"; + WRITE_GSERVICES: "android.permission.WRITE_GSERVICES"; + WRITE_HISTORY_BOOKMARKS: "com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"; + WRITE_PROFILE: "android.permission.WRITE_PROFILE"; + WRITE_SECURE_SETTINGS: "android.permission.WRITE_SECURE_SETTINGS"; + WRITE_SETTINGS: "android.permission.WRITE_SETTINGS"; + WRITE_SMS: "android.permission.WRITE_SMS"; + WRITE_SOCIAL_STREAM: "android.permission.WRITE_SOCIAL_STREAM"; + WRITE_SYNC_SETTINGS: "android.permission.WRITE_SYNC_SETTINGS"; + WRITE_USER_DICTIONARY: "android.permission.WRITE_USER_DICTIONARY"; + WRITE_VOICEMAIL: "com.android.voicemail.permission.WRITE_VOICEMAIL"; + + checkPermission: ( + permission: string, + successCallback: (status: PermissionStatus) => void, + errorCallback: () => void + ) => void; + + requestPermission: ( + permission: string, + successCallback: (status: PermissionStatus) => void, + errorCallback: () => void + ) => void; + + requestPermissions: ( + permissions: string[], + successCallback: (status: PermissionStatus) => void, + errorCallback: () => void + ) => void; + + hasPermission: ( + permission: string, + successCallback: (status: PermissionStatus) => void, + errorCallback: () => void + ) => void; +} + +interface CordovaPlugins { + permissions: Permissions; +} \ No newline at end of file diff --git a/node_modules/@types/noname-typings/cordova-plugin-device.d.ts b/node_modules/@types/noname-typings/cordova-plugin-device.d.ts new file mode 100644 index 0000000000..7b6a2b5ba0 --- /dev/null +++ b/node_modules/@types/noname-typings/cordova-plugin-device.d.ts @@ -0,0 +1,35 @@ +// Type definitions for cordova-plugin-device +// Project: https://github.com/apache/cordova-plugin-device +// Definitions by: Microsoft Open Technologies Inc +// Tim Brust +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/** + * This plugin defines a global device object, which describes the device's hardware and software. + * Although the object is in the global scope, it is not available until after the deviceready event. + */ +interface Device { + /** Get the version of Cordova running on the device. */ + cordova: string; + /** Indicates that Cordova initialize successfully. */ + available: boolean; + /** + * The device.model returns the name of the device's model or product. The value is set + * by the device manufacturer and may be different across versions of the same product. + */ + model: string; + /** Get the device's operating system name. */ + platform: string; + /** Get the device's Universally Unique Identifier (UUID). */ + uuid: string; + /** Get the operating system version. */ + version: string; + /** Get the device's manufacturer. */ + manufacturer: string; + /** Whether the device is running on a simulator. */ + isVirtual: boolean; + /** Get the device hardware serial number. */ + serial: string; +} + +declare var device: Device; \ No newline at end of file diff --git a/node_modules/@types/noname-typings/index.d.ts b/node_modules/@types/noname-typings/index.d.ts index 387ebd5ce6..c89de0bb47 100644 --- a/node_modules/@types/noname-typings/index.d.ts +++ b/node_modules/@types/noname-typings/index.d.ts @@ -9,6 +9,8 @@ /// /// /// +/// +/// /// /// /// diff --git a/node_modules/@types/noname-typings/windowEx.d.ts b/node_modules/@types/noname-typings/windowEx.d.ts index fca9c3721b..f089f64781 100644 --- a/node_modules/@types/noname-typings/windowEx.d.ts +++ b/node_modules/@types/noname-typings/windowEx.d.ts @@ -70,4 +70,6 @@ declare interface Window { initReadWriteFunction?(game: Game): Promise; bannedKeyWords: string[]; + + device: Device; } diff --git a/noname/game/index.js b/noname/game/index.js index 74b898be0d..002c12b422 100644 --- a/noname/game/index.js +++ b/noname/game/index.js @@ -7308,7 +7308,7 @@ export class Game { for (let i = 0; i < event.config.size; i++) { ui.window.appendChild(event.nodes[i]); } - ("step 1"); + "step 1"; let rand1 = event.config.first; if (rand1 == "rand") { rand1 = Math.random() < 0.5; @@ -7350,7 +7350,7 @@ export class Game { } game.delay(); lib.init.onfree(); - ("step 2"); + "step 2"; if (event.checkredo()) return; if (event._skiprest) return; if (event.side < 2) { @@ -7366,7 +7366,7 @@ export class Game { event.aiMove(); game.delay(); } - ("step 3"); + "step 3"; if (typeof event.fast == "number" && get.time() - event.fast <= 1000) { event.fast = true; } else { @@ -7401,7 +7401,7 @@ export class Game { game.delay(); } } - ("step 4"); + "step 4"; if (event.checkredo()) return; if (event.skipnode) event.skipnode.delete(); if (event.replacenode) event.replacenode.delete(); @@ -7423,7 +7423,7 @@ export class Game { } } game.delay(); - ("step 5"); + "step 5"; event.prompt("选择" + get.cnNumber(event.config.num) + "名出场武将"); event.enemylist = []; for (let i = 0; i < event.avatars.length; i++) { @@ -7453,7 +7453,7 @@ export class Game { event.nodes[i].hide(); } game.pause(); - ("step 6"); + "step 6"; event.promptbar.delete(); if (ui.cardPileButton) ui.cardPileButton.style.display = ""; lib.onresize.remove(event.resize); diff --git a/noname/gnc/index.js b/noname/gnc/index.js index 99460f6ca9..7cbdcebd99 100644 --- a/noname/gnc/index.js +++ b/noname/gnc/index.js @@ -8,45 +8,49 @@ export class GNC { * @returns */ of(fn) { - return this.is.generatorFunc(fn) - ? /** - * @param {Parameters} args - * @returns {Promise>} - */ - function genCoroutine(...args) { - let gen = fn.apply(this, args); - gen.status = "next"; - gen.state = undefined; - const callback = (resolve, reject) => { - let result, - nexts = resolve, - throws = reject; - try { - result = gen[gen.status](gen.state); - } catch (error) { - reject(error); - return; - } - if (!result.done) { - nexts = (item) => { - gen.state = item; - gen.status = "next"; - callback(resolve, reject); - }; - throws = (err) => { - gen.state = err; - gen.status = "throw"; - callback(resolve, reject); - }; - } - result = result.value; - Promise.resolve(result).then(nexts, throws); + /** + * @param {Parameters} args + * @returns {Promise>} + */ + function genCoroutine(...args) { + /** + * @type {Generator & { status: "next" | "throw" , state?: any}} + */ + // @ts-expect-error Must Ok + let gen = fn.apply(this, args); + gen.status = "next"; + gen.state = undefined; + const callback = (resolve, reject) => { + let result, + nexts = resolve, + throws = reject; + try { + result = gen[gen.status](gen.state); + } catch (error) { + reject(error); + return; + } + if (!result.done) { + nexts = (item) => { + gen.state = item; + gen.status = "next"; + callback(resolve, reject); }; - return new Promise(callback); - } - : (() => { - throw new TypeError("gnc.of needs a GeneratorFunction."); - })(); + throws = (err) => { + gen.state = err; + gen.status = "throw"; + callback(resolve, reject); + }; + } + result = result.value; + Promise.resolve(result).then(nexts, throws); + }; + return new Promise(callback); + } + + if (!this.is.generatorFunc(fn)) throw new TypeError("gnc.of needs a GeneratorFunction."); + + return genCoroutine; } is = new Is(); } diff --git a/noname/init/cordova.js b/noname/init/cordova.js index 73e8904b28..da48c7f7e1 100644 --- a/noname/init/cordova.js +++ b/noname/init/cordova.js @@ -1,10 +1,10 @@ -// @ts-nocheck import { get } from "../get/index.js"; import { lib } from "../library/index.js"; import { game } from "../game/index.js"; import { _status } from "../status/index.js"; import { ui } from "../ui/index.js"; import { nonameInitialized } from "../util/index.js"; +import { checkVersion } from "../library/update.js"; export async function cordovaReady() { if (lib.device == "android") { @@ -49,21 +49,33 @@ export async function cordovaReady() { if ("cordova" in window && "plugins" in window.cordova && "permissions" in window.cordova.plugins) { const permissions = cordova.plugins.permissions; const requests = ["WRITE_EXTERNAL_STORAGE", "READ_EXTERNAL_STORAGE"]; - requests.forEach((request) => { - permissions.checkPermission( - permissions[request], - (status) => { - if (!status.hasPermission) { - permissions.requestPermission( - permissions[request], - lib.other.ignore, - lib.other.ignore - ); - } - }, + if (typeof device == 'object') { + // 安卓13或以上 + if (checkVersion(device.version, "13") >= 0) { + requests.length = 0; + requests.push('READ_MEDIA_IMAGES', 'READ_MEDIA_VIDEO', 'READ_MEDIA_AUDIO'); + } + } + Promise.all(requests.map(request => { + return new Promise((resolve, reject) => { + permissions.checkPermission(permissions[request], status => { + resolve({ + request: request, + hasPermission: status.hasPermission + }); + }, reject); + }); + })).then(shouldRequestPermissions => { + return shouldRequestPermissions + .filter(({ hasPermission }) => !hasPermission) + .map(({ request }) => permissions[request] || `android.permission.${request}`); + }).then(willRequestPermissions => { + permissions.requestPermissions( + willRequestPermissions, + lib.other.ignore, lib.other.ignore ); - }); + }).catch(console.log); } } game.download = function (url, folder, onsuccess, onerror, dev, onprogress) { diff --git a/noname/library/element/content.js b/noname/library/element/content.js index 7ed9cb15c0..0cd1bda8a0 100644 --- a/noname/library/element/content.js +++ b/noname/library/element/content.js @@ -5296,6 +5296,16 @@ export const Content = { bool: true, links: [], }; + } else if (event.autochoose()) { + event.result = { + bool: true, + autochoose: true, + cards: player.getCards(event.position), + confirm: "ok", + buttons: [], + targets: [], + links: [], + }; } else { if (event.isMine()) { game.check(); diff --git a/noname/library/element/player.js b/noname/library/element/player.js index a032847db0..4212473106 100644 --- a/noname/library/element/player.js +++ b/noname/library/element/player.js @@ -4522,7 +4522,9 @@ export class Player extends HTMLDivElement { next.autochoose = function () { if (!this.forced) return false; if (typeof this.selectCard == "function") return false; + if (this.complexCard || this.complexSelect || this.filterOk) return false; var cards = this.player.getCards(this.position); + if (cards.some(card => !this.filterCard(card, this))) return false; var num = cards.length; for (var i = 0; i < cards.length; i++) { if (!lib.filter.cardDiscardable(cards[i], this.player, this)) num--; @@ -4776,6 +4778,14 @@ export class Player extends HTMLDivElement { if (next.filterCard == undefined) next.filterCard = lib.filter.all; if (next.selectCard == undefined) next.selectCard = [1, 1]; if (next.ai == undefined) next.ai = get.unuseful3; + next.autochoose = function () { + if (!this.forced) return false; + if (typeof this.selectCard == "function") return false; + if (this.complexCard || this.complexSelect || this.filterOk) return false; + var cards = this.player.getCards(this.position); + if (cards.some(card => !this.filterCard(card, this))) return false; + return get.select(this.selectCard)[0] >= this.player.countCards(this.position); + }; next.setContent("chooseCard"); next._args = Array.from(arguments); return next; diff --git a/noname/ui/create/menu/pages/exetensionMenu.js b/noname/ui/create/menu/pages/exetensionMenu.js index 4d670eef61..df9bd3cb31 100644 --- a/noname/ui/create/menu/pages/exetensionMenu.js +++ b/noname/ui/create/menu/pages/exetensionMenu.js @@ -426,6 +426,13 @@ export const extensionMenu = function (connectMenu) { 'import { lib, game, ui, get, ai, _status } from "../../noname.js";\ngame.import("extension",function(){\n\treturn ' + str + "\n});", + "info.json": JSON.stringify({ + name: page.currentExtension, + author: authorExtLine.querySelector("input").value || "", + diskURL: diskExtLine.querySelector("input").value || "", + forumURL: forumExtLine.querySelector("input").value || "", + version: versionExtLine.querySelector("input").value || "" + }), }; for (var i in dash1.content.image) { extension[i] = dash1.content.image[i]; diff --git a/noname/ui/create/menu/pages/otherMenu.js b/noname/ui/create/menu/pages/otherMenu.js index a36c1c3238..627c44a8b5 100644 --- a/noname/ui/create/menu/pages/otherMenu.js +++ b/noname/ui/create/menu/pages/otherMenu.js @@ -349,7 +349,7 @@ export const otherMenu = function (/** @type { boolean | undefined } */ connectM } } const str = - versionResult > 0 + versionResult < 0 ? `有新版本${description.name}可用,是否下载?` : `本地版本${lib.version}高于或等于github版本${description.name},是否强制下载?`; const str2 = description.body; @@ -454,7 +454,7 @@ export const otherMenu = function (/** @type { boolean | undefined } */ connectM const result = await asyncFilter(files.flat(), async v => { return game.promises.readFile(v.path).then(data => { return v.size != data.byteLength; - }) + }).catch(()=>true) }).then(arr => arr.map((v) => v.path)); console.log("需要更新的文件有:", result); diff --git a/prettier.config.mjs b/prettier.config.mjs new file mode 100644 index 0000000000..e8760a4fde --- /dev/null +++ b/prettier.config.mjs @@ -0,0 +1,13 @@ +/** @type {import("prettier").Config} */ +export default { + arrowParens: "always", + bracketSpacing: true, + endOfLine: "lf", + printWidth: 110, + proseWrap: "preserve", + quoteProps: "as-needed", + semi: true, + tabWidth: 4, + trailingComma: "es5", + useTabs: true, +};