diff --git a/noname/status/ai.d.ts b/noname/game-status/ai.d.ts similarity index 100% rename from noname/status/ai.d.ts rename to noname/game-status/ai.d.ts diff --git a/noname/status/ai.js b/noname/game-status/ai.js similarity index 100% rename from noname/status/ai.js rename to noname/game-status/ai.js diff --git a/noname/status/card-tag.d.ts b/noname/game-status/card-tag.d.ts similarity index 100% rename from noname/status/card-tag.d.ts rename to noname/game-status/card-tag.d.ts diff --git a/noname/status/card-tag.js b/noname/game-status/card-tag.js similarity index 100% rename from noname/status/card-tag.js rename to noname/game-status/card-tag.js diff --git a/noname/status/global-history.d.ts b/noname/game-status/global-history.d.ts similarity index 100% rename from noname/status/global-history.d.ts rename to noname/game-status/global-history.d.ts diff --git a/noname/status/post-reconnect.js b/noname/game-status/post-reconnect.js similarity index 100% rename from noname/status/post-reconnect.js rename to noname/game-status/post-reconnect.js diff --git a/noname/gnc.js b/noname/gnc.js index b149621ed..69eeba414 100644 --- a/noname/gnc.js +++ b/noname/gnc.js @@ -1,8 +1,12 @@ -import { Is } from "./gnc/is.js"; +const GeneratorFunction = (function* () { }).constructor; -export const gnc = { - of(fn) { - return Is.generatorFunc(fn) ? function genCoroutine() { +export class GNC { + constructor() { + throw new TypeError(`${new.target.name} is not a constructor`); + } + + static of(fn) { + return this.isGeneratorFunc(fn) ? function genCoroutine() { let gen = fn.apply(this, arguments); gen.status = "next"; gen.state = undefined; @@ -33,6 +37,20 @@ export const gnc = { } return new Promise(callback); } : (() => { throw new TypeError("gnc.of needs a GeneratorFunction.") })(); - }, - is: Is -}; + } + + static isCoroutine(item) { + return typeof item == "function" && item.name == "genCoroutine"; + } + + /** + * @returns {item is GeneratorFunction} + */ + static isGeneratorFunc(item) { + return item instanceof GeneratorFunction; + } + + static isGenerator(item) { + return typeof item == "object" && "constructor" in item && item.constructor && "constructor" in item.constructor && item.constructor.constructor === GeneratorFunction; + } +} diff --git a/noname/gnc/is.js b/noname/gnc/is.js deleted file mode 100644 index b0715d035..000000000 --- a/noname/gnc/is.js +++ /dev/null @@ -1,18 +0,0 @@ -const GeneratorFunction = (function* () { }).constructor; - -export class Is { - static coroutine(item) { - return typeof item == "function" && item.name == "genCoroutine"; - } - - /** - * @returns {item is GeneratorFunction} - */ - static generatorFunc(item) { - return item instanceof GeneratorFunction; - } - - static generator(item) { - return typeof item == "object" && "constructor" in item && item.constructor && "constructor" in item.constructor && item.constructor.constructor === GeneratorFunction; - } -} diff --git a/noname/internal/internal-library.js b/noname/internal/internal-library.js new file mode 100644 index 000000000..10496c084 --- /dev/null +++ b/noname/internal/internal-library.js @@ -0,0 +1 @@ +export { Library as InternalLibrary } from "../library.js"; diff --git a/noname/library.js b/noname/library.js index 957725c5c..7841dba0b 100644 --- a/noname/library.js +++ b/noname/library.js @@ -1,7 +1,13 @@ +import { Game } from "./game.js"; +import { Get } from "./get.js"; +import { GNC } from "./gnc.js"; +import { InternalLibrary } from "./internal/internal-library.js"; import { animate } from "./library/animate.js"; import { announce } from "./library/announce.js"; import { cardPack } from "./library/card-pack.js"; +import { cardPile } from "./library/card-pile.js"; import { cardType } from "./library/card-type.js"; +import { card } from "./library/card.js"; import { Channel } from "./library/channel.js"; import { CharacterDialogGroup } from "./library/character-dialog-group.js"; import { characterFilter } from "./library/character-filter.js"; @@ -10,21 +16,45 @@ import { characterPack } from "./library/character-pack.js"; import { characterReplace } from "./library/character-replace.js"; import { characterSort } from "./library/character-sort.js"; import { characterTitle } from "./library/character-title.js"; +import { character } from "./library/character.js"; +import { Cheat } from "./library/cheat.js"; +import { color } from "./library/color.js"; +import { Comparator } from "./library/comparator.js"; import { CONFIGURATION_MENU } from "./library/configuration-menu.js"; +import { configuration } from "./library/configuration.js"; +import { Creation } from "./library/creation.js"; import { dynamicTranslate } from "./library/dynamic-translate.js"; import { element } from "./library/element.js"; import { emotionList } from "./library/emotion-list.js"; import { extensionMenu } from "./library/extension-menu.js"; import { extensionPack } from "./library/extension-pack.js"; +import { Filter } from "./library/filter.js"; +import { groupNature } from "./library/group-nature.js"; +import { HELP } from "./library/help.js"; import { hookMap } from "./library/hook-map.js"; import { hook } from "./library/hook.js"; import { hooks } from "./library/hooks.js"; import { imported } from "./library/imported.js"; +import { Initialization } from "./library/initialization.js"; +import { internalStatus } from "./library/internal-status.js"; +import { linq } from "./library/linq.js"; +import { message } from "./library/message.js"; +import { MODE } from "./library/mode.js"; +import { natureAudio } from "./library/nature-audio.js"; +import { Other } from "./library/other.js"; +import { perfectPair } from "./library/perfect-pair.js"; import { pinyins } from "./library/pinyins.js"; +import { skill } from "./library/skill.js"; import { skin } from "./library/skin.js"; +import { Sort } from "./library/sort.js"; import { stratagemBuff } from "./library/stratagem-buff.js"; +import { translate } from "./library/translate.js"; import { updateURLs } from "./library/update-urls.js"; import { yingbian } from "./library/yingbian.js"; +import { status } from "./status.js"; +import { UI } from "./ui.js"; +import { Click } from "./ui/click.js"; +import { Create } from "./ui/create.js"; const nonameInitialized = localStorage.getItem("noname_inited"); @@ -75,7 +105,6 @@ export class Library { static cardType = cardType; static hook = hook; static hooks = hooks; - static element = element; static Channel = Channel; /** * @todo Waiting for [Rintim](https://github.com/Rintim)’s pull request. @@ -103,6 +132,349 @@ export class Library { static characterDialogGroup = CharacterDialogGroup; static configMenu = CONFIGURATION_MENU; static extensionMenu = extensionMenu; + static mode = MODE; + static status = internalStatus; + static help = HELP; + /** + * @type {import("path")} + */ + // @ts-ignore + static path = {}; + static gnc = GNC; + static comparator = Comparator; + static creation = Creation; + static linq = linq; + static init = Initialization; + static cheat = Cheat; + static translate = translate; + static element = element; + static card = card; + static filter = Filter; + static sort = Sort; + static skill = skill; + static character = character; + static perfectPair = perfectPair; + static cardPile = cardPile; + static message = message; + static suit = ["club", "spade", "diamond", "heart"]; + static suits = ["club", "spade", "diamond", "heart", "none"]; + static color = color; + static group = ["wei", "shu", "wu", "qun", "jin", "shen"]; + /** + * 数值代表各元素在名称中排列的先后顺序 + */ + static nature = new Map([ + ["fire", 20], + ["thunder", 30], + ["kami", 60], + ["ice", 40], + ["stab", 10], + ["poison", 50] + ]); + static natureAudio = natureAudio; + static linked = ["fire", "thunder", "kami", "ice"]; + static natureBg = new Map([ + ["stab", "image/card/cisha.png"] + ]); + static natureSeparator = "|"; + static namePrefix = new Map([ + ["界", { + color: "#fdd559", + nature: "soilmm", + }], + ["谋", { + color: "#def7ca", + nature: "woodmm", + }], + ["武", { + color: "#fd8359", + nature: "soilmm", + }], + ["乐", { + color: "#f7f4fc", + nature: "keymm", + }], + ["神", { + color: "#faecd1", + nature: "orangemm", + }], + ["族", { + color: "#ee9ac7", + nature: "firemm", + }], + ["晋", { + color: "#f3c5ff", + nature: "blackmm", + }], + ["侠", { + color: "#eeeeee", + nature: "qunmm", + }], + ["起", { + color: "#c3f9ff", + nature: "thundermm", + }], + ["承", { + color: "#c3f9ff", + nature: "thundermm", + }], + ["转", { + color: "#c3f9ff", + nature: "thundermm", + }], + ["梦", { + color: "#6affe2", + nature: "watermm", + }], + ["用间", { + color: "#c3f9ff", + nature: "thundermm", + }], + ["战役篇", { + color: "#c3f9ff", + nature: "thundermm", + showName: "战", + }], + ["武将传", { + color: "#c3f9ff", + nature: "thundermm", + showName: "传", + }], + ["将", { + nature: "firemm", + }], + ["新杀", { + color: "#fefedc", + nature: "metalmm", + showName: "新", + }], + ["旧", { + color: "#a4a4a4", + nature: "black", + }], + ["旧界", { + color: "#a4a4a4", + nature: "black", + }], + ["节钺", { + color: "#a4a4a4", + nature: "black", + }], + ["毅重", { + color: "#a4a4a4", + nature: "black", + }], + ["★SP", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("SP")}` + }], + ["☆SP", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("SP")}` + }], + ["J.SP", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("SP")}` + }], + ["K系列", { + showName: "K", + }], + ["经典", { + showName: "典", + }], + ["君", { + color: "#fefedc", + nature: "shenmm", + }], + ["骰子", { + getSpan: () => { + const span = document.createElement("span"); + span.style.fontFamily = "NonameSuits"; + span.textContent = "🎲"; + return span.outerHTML; + } + }], + ["SP", { + getSpan: () => { + const span = document.createElement("span"), style = span.style; + style.writingMode = style.webkitWritingMode = "horizontal-tb"; + style.fontFamily = "MotoyaLMaru"; + style.transform = "scaleY(0.85)"; + span.textContent = "SP"; + return span.outerHTML; + }, + }], + ["OL", { + getSpan: () => { + const span = document.createElement("span"), style = span.style; + style.writingMode = style.webkitWritingMode = "horizontal-tb"; + style.fontFamily = "MotoyaLMaru"; + style.transform = "scaleY(0.85)"; + span.textContent = "OL"; + return span.outerHTML; + }, + }], + ["RE", { + getSpan: () => { + const span = document.createElement("span"), style = span.style; + style.writingMode = style.webkitWritingMode = "horizontal-tb"; + style.fontFamily = "MotoyaLMaru"; + style.transform = "scaleY(0.85)"; + span.textContent = "RE"; + return span.outerHTML; + }, + }], + ["手杀", { + getSpan: (prefix, name) => { + const simple = configuration.buttoncharacter_prefix == "simple", span = document.createElement("span"); + if (characterPack.shiji && name in characterPack.shiji) { + for (const entry of Object.entries(characterSort.shiji)) { + if (!entry[1].includes(name)) continue; + prefix = Get.translation(entry[0]).slice(-1); + break; + } + if (!simple) { + span.style.color = "#def7ca"; + span.dataset.nature = "watermm"; + } + span.innerHTML = prefix; + } + else if (simple) span.textContent = "手杀"; + else { + span.style.fontFamily = "NonameSuits"; + span.textContent = "📱"; + } + return span.outerHTML; + }, + }], + ["TW", { + getSpan: () => { + const span = document.createElement("span"), style = span.style; + style.writingMode = style.webkitWritingMode = "horizontal-tb"; + style.fontFamily = "MotoyaLMaru"; + style.transform = "scaleY(0.85)"; + span.textContent = "TW"; + return span.outerHTML; + }, + }], + ["TW神", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("TW")}${Get.prefixSpan("神")}` + }], + ["TW将", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("TW")}${Get.prefixSpan("将")}` + }], + ["OL神", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("OL")}${Get.prefixSpan("神")}` + }], + ["旧神", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("旧")}${Get.prefixSpan("神")}` + }], + ["旧晋", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("旧")}${Get.prefixSpan("晋")}` + }], + ["新杀SP", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("新杀")}${Get.prefixSpan("SP")}` + }], + ["界SP", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("界")}${Get.prefixSpan("SP")}` + }], + ["S特神", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("★")}${Get.prefixSpan("神")}` + }], + ["手杀界", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("手杀")}${Get.prefixSpan("界")}` + }], + ["战役篇神", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("战役篇")}${Get.prefixSpan("神")}` + }], + ["星", { + color: "#ffd700", + nature: "glodenmm", + }], + ["OL界", { + /** + * @returns {string} + */ + getSpan: () => `${Get.prefixSpan("OL")}${Get.prefixSpan("界")}` + }] + ]); + static groupnature = groupNature; + static lineColor = new Map([ + ["fire", [255, 146, 68]], + ["yellow", [255, 255, 122]], + ["blue", [150, 202, 255]], + ["green", [141, 255, 216]], + ["ice", [59, 98, 115]], + ["thunder", [141, 216, 255]], + ["kami", [90, 118, 99]], + ["white", [255, 255, 255]], + ["poison", [104, 221, 127]], + ["brown", [195, 161, 223]], + ["legend", [233, 131, 255]] + ]); + static phaseName = ["phaseZhunbei", "phaseJudge", "phaseDraw", "phaseUse", "phaseDiscard", "phaseJieshu"]; + static quickVoice = [ + "我从未见过如此厚颜无耻之人!", + "这波不亏", + "请收下我的膝盖", + "你咋不上天呢", + "放开我的队友,冲我来", + "你随便杀,闪不了算我输", + "见证奇迹的时刻到了", + "能不能快一点啊,兵贵神速啊", + "主公,别开枪,自己人", + "小内再不跳,后面还怎么玩儿啊", + "你们忍心,就这么让我酱油了?", + "我,我惹你们了吗", + "姑娘,你真是条汉子", + "三十六计,走为上,容我去去便回", + "人心散了,队伍不好带啊", + "昏君,昏君啊!", + "风吹鸡蛋壳,牌去人安乐", + "小内啊,您老悠着点儿", + "不好意思,刚才卡了", + "你可以打得再烂一点吗", + "哥们,给力点儿行嘛", + "哥哥,交个朋友吧", + "妹子,交个朋友吧", + ]; + static other = Other; constructor() { throw new TypeError(`${new.target.name} is not a constructor`); @@ -123,4 +495,540 @@ export class Library { }); } } + + static getErrorTip(msg) { + if (typeof msg != "string") { + try { + msg = msg.toString(); + if (typeof msg != "string") throw "err"; + } catch (_) { + throw `传参错误:${msg}`; + } + } + if (msg.startsWith("Uncaught ")) msg = msg.slice(9); + let newMessage = msg; + if (/RangeError/.test(newMessage)) { + if (newMessage.includes("Maximum call stack size exceeded")) { + newMessage = "堆栈溢出"; + } else if (/argument must be between 0 and 20/.test(newMessage)) { + let funName = newMessage.slice(newMessage.indexOf("RangeError: ") + 12, newMessage.indexOf(")") + 1); + newMessage = funName + "参数必须在0和20之间"; + } else { + newMessage = "传递错误值到数值计算方法"; + } + } else if (/ReferenceError/.test(newMessage)) { + let messageName; + if (newMessage.includes("is not defined")) { + messageName = newMessage.replace("ReferenceError: ", "").replace(" is not defined", ""); + newMessage = "引用了一个未定义的变量:" + messageName; + } else if (newMessage.includes("invalid assignment left-hand side")) { + newMessage = "赋值运算符或比较运算符不匹配"; + } else if (newMessage.includes("Octal literals are not allowed in strict mode")) { + newMessage = "八进制字面量与八进制转义序列语法已经被废弃"; + } else if (newMessage.includes("Illegal \x27use strict\x27 directive in function with non-simple parameter list")) { + newMessage = "\x27use strict\x27指令不能使用在带有‘非简单参数’列表的函数"; + } else if (newMessage.includes("Invalid left-hand side in assignment")) { + newMessage = "赋值中的左侧无效,即number,string等不可赋值的非变量数据"; + } + } else if (/SyntaxError/.test(newMessage)) { + let messageName; + if (newMessage.includes("Unexpected token ")) { + messageName = newMessage.replace("SyntaxError: Unexpected token ", ""); + newMessage = "使用了未定义或错误的语法 : (" + messageName + ")"; + } else if (newMessage.includes( + "Block-scoped declarations (let, const, function, class) not yet supported outside strict mode")) { + newMessage = "请在严格模式下运行let,const,class"; + } else if (newMessage.includes("for-of loop variable declaration may not have an initializer.")) { + newMessage = "for...of 循环的头部包含有初始化表达式"; + } else if (newMessage.includes("for-in loop variable declaration may not have an initializer.")) { + newMessage = "for...in 循环的头部包含有初始化表达式"; + } else if (newMessage.includes("Delete of an unqualified identifier in strict mode.")) { + newMessage = "普通变量不能通过 delete 操作符来删除"; + } else if (newMessage.includes("Unexpected identifier")) { + newMessage = "不合法的标识符或错误的语法"; + } else if (newMessage.includes("Invalid or unexpected token")) { + newMessage = "非法的或者不期望出现的标记符号出现在不该出现的位置"; + } else if (newMessage.includes("Invalid regular expression flags")) { + newMessage = "无效的正则表达式的标记"; + } else if (newMessage.includes("missing ) after argument list")) { + newMessage = "参数列表后面缺少“)” (丢失运算符或者转义字符等)"; + } else if (newMessage.includes("Invalid shorthand property initializer")) { + newMessage = "在定义一个{}对象时,应该使用“:”而不是“=”"; + } else if (newMessage.includes("Missing initializer in const declaration")) { + newMessage = "在使用const定义一个对象时,必须指定初始值"; + } else if (newMessage.includes("Unexpected number") || newMessage.includes("Unexpected string")) { + newMessage = "在定义函数时,函数参数必须为合法标记符"; + } else if (newMessage.includes("Unexpected end of input")) { + newMessage = "遗漏了符号或符号顺序不对(小括号,花括号等)"; + } else if (newMessage.includes("has already been declared")) { + messageName = newMessage.replace("SyntaxError: Identifier ", "").replace(" has already been declared", ""); + newMessage = messageName + "变量已经被声明过,不能被重新声明"; + } else if (newMessage.includes("Duplicate parameter name not allowed in this context")) { + newMessage = "参数名不允许重复"; + } else if (newMessage.includes("Unexpected reserved word") || newMessage.includes( + "Unexpected strict mode reserved word")) { + newMessage = "保留字被用作标记符"; + } + } else if (/TypeError/.test(newMessage)) { + let messageName; + if (newMessage.includes(" is not a function")) { + messageName = newMessage.replace("TypeError: ", "").replace(" is not a function", ""); + newMessage = messageName + "不是一个函数"; + } else if (newMessage.includes(" is not a constructor")) { + messageName = newMessage.replace("TypeError: ", "").replace(" is not a constructor", ""); + newMessage = messageName + "不是一个构造函数"; + } else if (newMessage.includes("Cannot read property")) { + messageName = newMessage.replace("TypeError: Cannot read property ", "").replace(" of null", "").replace(" of undefined", ""); + let ofName = newMessage.slice(newMessage.indexOf(" of ") + 4); + newMessage = `无法读取“${ofName}”的属性值${messageName}`; + } else if (newMessage.includes("Cannot read properties")) { + messageName = newMessage.slice(newMessage.indexOf("reading \x27") + 9, -2); + let ofName = newMessage.slice(newMessage.indexOf(" of ") + 4, newMessage.indexOf("(") - 1); + newMessage = `无法读取“${ofName}”的属性值${messageName}`; + } else if (newMessage.includes("Property description must be an object")) { + messageName = newMessage.replace("TypeError: Property description must be an object: ", ""); + newMessage = messageName + "是非对象类型的值"; + } else if (newMessage.includes("Cannot assign to read only property ")) { + messageName = newMessage.slice(47, newMessage.lastIndexOf(" of ") + 1); + newMessage = messageName + "属性禁止写入"; + } else if (newMessage.includes("Object prototype may only be an Object or null")) { + newMessage = messageName + "对象原型只能是对象或null"; + } else if (newMessage.includes("Cannot create property")) { + messageName = newMessage.slice(newMessage.indexOf("\x27") + 1); + messageName = messageName.slice(0, messageName.indexOf("\x27")); + let obj = newMessage.slice(newMessage.indexOf(messageName) + 16); + newMessage = `${obj}不能添加或修改“${messageName}”属性,任何 Primitive 值都不允许有property`; + } else if (newMessage.includes("Can\x27t add property") && newMessage.includes("is not extensible")) { + newMessage = "对象不可添加属性(不可扩展)"; + } else if (newMessage.includes("Cannot redefine property")) { + messageName = newMessage.slice(37); + newMessage = messageName + "不可配置"; + } else if (newMessage.includes("Converting circular structure to JSON")) { + messageName = newMessage.slice(37); + newMessage = "JSON.stringify() 方法处理循环引用结构的JSON会失败"; + } else if (newMessage.includes("Cannot use \x27in\x27 operator to search for ")) { + newMessage = "in不能用来在字符串、数字或者其他基本类型的数据中进行检索"; + } else if (newMessage.includes("Right-hand side of \x27instanceof\x27 is not an object")) { + newMessage = "instanceof 操作符 希望右边的操作数为一个构造对象,即一个有 prototype 属性且可以调用的对象"; + } else if (newMessage.includes("Assignment to constant variable")) { + newMessage = "const定义的变量不可修改"; + } else if (newMessage.includes("Cannot delete property")) { + newMessage = "不可配置的属性不能删除"; + } else if (newMessage.includes("which has only a getter")) { + newMessage = "仅设置了getter特性的属性不可被赋值"; + } else if (newMessage.includes("called on incompatible receiver undefined")) { + newMessage = "this提供的绑定对象与预期的不匹配"; + } + } else if (/URIError/.test(newMessage)) { + newMessage = "一个不合法的URI"; + } else if (/EvalError/.test(newMessage)) { + newMessage = "非法调用 eval()"; + } else if (/InternalError/.test(newMessage)) { + if (newMessage.includes("too many switch cases")) { + newMessage = "过多case子句"; + } else if (newMessage.includes("too many parentheses in regular expression")) { + newMessage = "正则表达式中括号过多"; + } else if (newMessage.includes("array initializer too large")) { + newMessage = "超出数组大小的限制"; + } else if (newMessage.includes("too much recursion")) { + newMessage = "递归过深"; + } + } + if (newMessage != msg) { + return newMessage; + } + } + + static codeMirrorReady(node, editor) { + UI.window.appendChild(node); + node.style.fontSize = `${20 / Game.documentZoom}px`; + const mirror = window.CodeMirror(editor, { + value: node.code, + mode: "javascript", + lineWrapping: !configuration.touchscreen && configuration.mousewheel, + lineNumbers: true, + indentUnit: 4, + autoCloseBrackets: true, + fixedGutter: false, + hintOptions: { completeSingle: false }, + theme: configuration.codeMirror_theme || "mdn-like", + extraKeys: { + "Ctrl-Z": "undo",//撤销 + "Ctrl-Y": "redo",//恢复撤销 + //"Ctrl-A":"selectAll",//全选 + }, + }); + InternalLibrary.setScroll(editor.querySelector(".CodeMirror-scroll")); + node.aced = true; + node.editor = mirror; + setTimeout(() => mirror.refresh(), 0); + node.editor.on("change", (e, change) => { + let code; + if (node.editor) { + code = node.editor.getValue(); + } else if (node.textarea) { + code = node.textarea.value; + } + //动态绑定文本 + if (code.length && change.origin == "+input" && + /{|}|\s|=|;|:|,|,|。|?|!|!|\?|&|#|%|@|‘|’|;/.test(change.text[0]) == false && + change.text.length == 1) { + //输入了代码,并且不包括空格,{},=, ; , : , 逗号等,才可以自动提示 + node.editor.showHint(); + } + }); + //防止每次输出字符都创建以下元素 + const event = status.event; + const trigger = status.event; + const player = Create.player().init("sunce"); + const target = player; + const targets = [player]; + const source = player; + const card = Game.createCard(); + const cards = [card]; + const result = { bool: true }; + function forEach(arr, f) { + Array.from(arr).forEach(v => f(v)); + } + function forAllProps(obj, callback) { + if (!Object.getOwnPropertyNames || !Object.getPrototypeOf) { + for (let name in obj) callback(name); + } else { + for (let o = obj; o; o = Object.getPrototypeOf(o)) Object.getOwnPropertyNames(o).forEach(callback); + } + } + function scriptHint(editor, keywords, getToken, options) { + //Find the token at the cursor + let cur = editor.getCursor(), token = editor.getTokenAt(cur); + if (/\b(?:string|comment)\b/.test(token.type)) return; + const innerMode = CodeMirror.innerMode(editor.getMode(), token.state); + if (innerMode.mode.helperType === "json") return; + token.state = innerMode.state; + //If it’s not a “word-style” token, ignore the token. + if (!/^[\w$_]*$/.test(token.string)) { + token = { + start: cur.ch, + end: cur.ch, + string: "", + state: token.state, + type: token.string == "." ? "property" : null + }; + } else if (token.end > cur.ch) { + token.end = cur.ch; + token.string = token.string.slice(0, cur.ch - token.start); + } + let tprop = token, context; + //If it is a property, find out what it is a property of. + while (tprop.type == "property") { + tprop = editor.getTokenAt(CodeMirror.Pos(cur.line, tprop.start)); + if (tprop.string != ".") return; + tprop = editor.getTokenAt(CodeMirror.Pos(cur.line, tprop.start)); + if (!context) context = []; + context.push(tprop); + } + const list = []; + let obj; + if (Array.isArray(context)) { + try { + const code = context.length == 1 ? context[0].string : context.reduceRight((pre, cur) => `${pre.string || pre}.${cur.string}`); + obj = eval(code); + if (![null, undefined].includes(obj)) { + const keys = Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(obj))).filter(key => key.startsWith(token.string)); + list.addArray(keys); + } + } catch (_) { return; } + } else if (token && typeof token.string == "string") { + //非开发者模式下,提示这些单词 + list.addArray(["player", "card", "cards", "result", "trigger", "source", "target", "targets", "lib", "game", "ui", "get", "ai", "_status"]); + } + return { + list: [...new Set(getCompletions(token, context, keywords, options).concat(list))] + .filter(key => key.startsWith(token.string)) + .sort((a, b) => `${a}`.localeCompare(`${b}`)) + .map(text => { + return { + render(elt, data, cur) { + var icon = document.createElement("span"); + var className = "cm-completionIcon cm-completionIcon-"; + if (obj) { + const type = typeof obj[text]; + if (type == "function") { + className += "function"; + } + else if (type == "string") { + className += "text"; + } + else if (type == "boolean") { + className += "variable"; + } + else { + className += "namespace"; + } + } else { + if (javascriptKeywords.includes(text)) { + className += "keyword"; + } + else if (window[text]) { + const type = typeof window[text]; + if (type == "function") { + className += "function"; + } + else if (type == "string") { + className += "text"; + } + else if (text == "window" || type == "boolean") { + className += "variable"; + } + else { + className += "namespace"; + } + } else { + className += "namespace"; + } + } + icon.className = className; + elt.appendChild(icon); + elt.appendChild(document.createTextNode(text)); + }, + displayText: text, + text: text, + } + }), + from: CodeMirror.Pos(cur.line, token.start), + to: CodeMirror.Pos(cur.line, token.end) + }; + } + function javascriptHint(editor, options) { + return scriptHint(editor, javascriptKeywords, function (e, cur) { return e.getTokenAt(cur); }, options); + } + //覆盖原本的javascript提示 + CodeMirror.registerHelper("hint", "javascript", javascriptHint); + const stringProps = Object.getOwnPropertyNames(String.prototype); + const arrayProps = Object.getOwnPropertyNames(Array.prototype); + const funcProps = Object.getOwnPropertyNames(Array.prototype); + const javascriptKeywords = ("break case catch class const continue debugger default delete do else export extends from false finally for function " + + "if in import instanceof let new null return super switch this throw true try typeof var void while with yield").split(" "); + function getCompletions(token, context, keywords, options) { + let found = [], start = token.string, global = options && options.globalScope || window; + function maybeAdd(str) { + if (str.lastIndexOf(start, 0) == 0 && !found.includes(str)) found.push(str); + } + function gatherCompletions(obj) { + if (typeof obj == "string") forEach(stringProps, maybeAdd); + else if (obj instanceof Array) forEach(arrayProps, maybeAdd); + else if (obj instanceof Function) forEach(funcProps, maybeAdd); + forAllProps(obj, maybeAdd); + } + if (context && context.length) { + //If this is a property, see if it belongs to some object we can + //find in the current environment. + let obj = context.pop(), base; + if (obj.type && obj.type.indexOf("variable") === 0) { + if (options && options.additionalContext) + base = options.additionalContext[obj.string]; + if (!options || options.useGlobalScope !== false) + base = base || global[obj.string]; + } else if (obj.type == "string") { + base = ""; + } else if (obj.type == "atom") { + base = 1; + } else if (obj.type == "function") { + if (global.jQuery != null && (obj.string == "$" || obj.string == "jQuery") && (typeof global.jQuery == "function")) + base = global.jQuery(); + else if (global._ != null && (obj.string == "_") && (typeof global._ == "function")) + base = global._(); + } + while (base != null && context.length) + base = base[context.pop().string]; + if (base != null) gatherCompletions(base); + } else { + //If not, just look in the global object, any local scope, and optional additional-context + //(reading into JS mode internals to get at the local and global variables) + for (let v = token.state.localVars; v; v = v.next) maybeAdd(v.name); + for (let c = token.state.context; c; c = c.prev) for (let v = c.vars; v; v = v.next) maybeAdd(v.name) + for (let v = token.state.globalVars; v; v = v.next) maybeAdd(v.name); + if (options && options.additionalContext != null) for (let key in options.additionalContext) maybeAdd(key); + if (!options || options.useGlobalScope !== false) gatherCompletions(global); + forEach(keywords, maybeAdd); + } + return found.sort((a, b) => `${a}`.localeCompare(`${b}`)); + } + } + + static setIntro(node, func, left) { + if (configuration.touchscreen) { + if (left) { + node.listen(Click.touchintro); + } + else { + InternalLibrary.setLongPress(node, Click.intro); + } + } + else { + if (left) { + node.listen(Click.intro); + } + if (configuration.hover_all && !InternalLibrary.device) { + InternalLibrary.setHover(node, Click.hoverplayer); + } + if (configuration.right_info) { + node.oncontextmenu = Click.rightplayer; + } + } + if (func) { + node._customintro = func; + } + } + + static setPopped(node, func, width, height, forceclick, paused2) { + node._poppedfunc = func; + node._poppedwidth = width; + node._poppedheight = height; + if (forceclick) { + node.forceclick = true; + } + if (configuration.touchscreen || forceclick) { + node.listen(Click.hoverpopped); + } + else { + node.addEventListener("mouseenter", Click.hoverpopped); + } + if (paused2) { + node._paused2 = true; + } + } + + static placePoppedDialog(dialog, e) { + if (dialog._place_text) { + if (dialog._place_text.firstChild.offsetWidth >= 190 || dialog._place_text.firstChild.offsetHeight >= 30) { + dialog._place_text.style.marginLeft = "14px"; + dialog._place_text.style.marginRight = "14px"; + dialog._place_text.style.textAlign = "left"; + dialog._place_text.style.width = "calc(100% - 28px)"; + } + } + if (e.touches && e.touches[0]) { + e = e.touches[0]; + } + var height = Math.min(UI.window.offsetHeight - 20, dialog.content.scrollHeight); + if (dialog._mod_height) { + height += dialog._mod_height; + } + dialog.style.height = `${height}px`; + if (e.clientX / Game.documentZoom < UI.window.offsetWidth / 2) { + dialog.style.left = `${e.clientX / Game.documentZoom + 10}px`; + } + else { + dialog.style.left = `${e.clientX / Game.documentZoom - dialog.offsetWidth - 10}px`; + } + var idealtop = (e.clientY || 0) / Game.documentZoom - dialog.offsetHeight / 2; + if (typeof idealtop != "number" || isNaN(idealtop) || idealtop <= 5) { + idealtop = 5; + } + else if (idealtop + dialog.offsetHeight + 10 > UI.window.offsetHeight) { + idealtop = UI.window.offsetHeight - 10 - dialog.offsetHeight; + } + dialog.style.top = `${idealtop}px`; + } + + static setHover(node, func, hoveration, width) { + node._hoverfunc = func; + if (typeof hoveration == "number") { + node._hoveration = hoveration; + } + if (typeof width == "number") { + node._hoverwidth = width + } + node.addEventListener("mouseenter", Click.mouseenter); + node.addEventListener("mouseleave", Click.mouseleave); + node.addEventListener("mousedown", Click.mousedown); + node.addEventListener("mousemove", Click.mousemove); + return node; + } + + static setScroll(node) { + node.ontouchstart = Click.touchStart; + node.ontouchmove = Click.touchScroll; + node.style.webkitOverflowScrolling = "touch"; + return node; + } + + static setMousewheel(node) { + if (configuration.mousewheel) node.onmousewheel = Click.mousewheel; + } + + static setLongPress(node, func) { + node.addEventListener("touchstart", Click.longpressdown); + node.addEventListener("touchend", Click.longpresscancel); + node._longpresscallback = func; + return node; + } + + static updateCanvas(time) { + if (InternalLibrary.canvasUpdates.length === 0) { + internalStatus.canvas = false; + return false; + } + UI.canvas.width = UI.arena.offsetWidth; + UI.canvas.height = UI.arena.offsetHeight; + var ctx = UI.ctx; + ctx.shadowBlur = 5; + ctx.shadowColor = "rgba(0,0,0,0.3)"; + ctx.strokeStyle = "white"; + ctx.lineWidth = 3; + ctx.save(); + for (var i = 0; i < InternalLibrary.canvasUpdates.length; i++) { + ctx.restore(); + ctx.save(); + var update = InternalLibrary.canvasUpdates[i]; + if (!update.starttime) { + update.starttime = time; + } + if (update(time - update.starttime, ctx) === false) { + InternalLibrary.canvasUpdates.splice(i--, 1); + } + } + } + + static run(time) { + internalStatus.time = time; + for (var i = 0; i < InternalLibrary.updates.length; i++) { + if (!Object.prototype.hasOwnProperty.call(InternalLibrary.updates[i], "_time")) { + InternalLibrary.updates[i]._time = time; + } + if (InternalLibrary.updates[i](time - InternalLibrary.updates[i]._time - internalStatus.delayed) === false) { + InternalLibrary.updates.splice(i--, 1); + } + } + if (InternalLibrary.updates.length) { + internalStatus.frameId = requestAnimationFrame(InternalLibrary.run); + } + else { + internalStatus.time = 0; + internalStatus.delayed = 0; + } + } + + static getUTC(date) { + return date.getTime(); + } + + static saveVideo() { + if (status.videoToSave) { + Game.export(Initialization.encode(JSON.stringify(status.videoToSave)), + `无名杀 - 录像 - ${status.videoToSave.name[0]} - ${status.videoToSave.name[1]}`); + } + } + + static genAsync(fn) { + return GNC.of(fn); + } + + static genAwait(item) { + return GNC.isGenerator(item) ? GNC.of(function* () { + for (const content of item) { + yield content; + } + })() : Promise.resolve(item); + } } diff --git a/noname/library/card-pile.js b/noname/library/card-pile.js new file mode 100644 index 000000000..f0ba7bfca --- /dev/null +++ b/noname/library/card-pile.js @@ -0,0 +1 @@ +export const cardPile = {}; diff --git a/noname/library/card.js b/noname/library/card.js new file mode 100644 index 000000000..06163d873 --- /dev/null +++ b/noname/library/card.js @@ -0,0 +1,93 @@ +export const card = { + list: [], + cooperation_damage: { + fullskin: true + }, + cooperation_draw: { + fullskin: true, + cardimage: "cooperation_damage" + }, + cooperation_discard: { + fullskin: true, + cardimage: "cooperation_damage" + }, + cooperation_use: { + fullskin: true, + cardimage: "cooperation_damage" + }, + pss_paper: { + type: "pss", + fullskin: true + }, + pss_scissor: { + type: "pss", + fullskin: true, + }, + pss_stone: { + type: "pss", + fullskin: true + }, + feichu_equip1: { + type: "equip", + subtype: "equip1" + }, + feichu_equip2: { + type: "equip", + subtype: "equip2" + }, + feichu_equip3: { + type: "equip", + subtype: "equip3" + }, + feichu_equip4: { + type: "equip", + subtype: "equip4" + }, + feichu_equip5: { + type: "equip", + subtype: "equip5" + }, + feichu_equip6: { + type: "equip", + subtype: "equip6" + }, + zhengsu_leijin: {}, + zhengsu_mingzhi: {}, + zhengsu_bianzhen: {}, + disable_judge: {}, + group_wei: { + fullskin: true + }, + group_shu: { + fullskin: true + }, + group_wu: { + fullskin: true + }, + group_qun: { + fullskin: true + }, + group_key: { + fullskin: true + }, + group_jin: { + fullskin: true + }, + + db_atk1: { + type: "db_atk", + fullimage: true + }, + db_atk2: { + type: "db_atk", + fullimage: true + }, + db_def1: { + type: "db_def", + fullimage: true + }, + db_def2: { + type: "db_def", + fullimage: true + } +}; diff --git a/noname/library/character.js b/noname/library/character.js new file mode 100644 index 000000000..111324fc9 --- /dev/null +++ b/noname/library/character.js @@ -0,0 +1 @@ +export const character = {}; diff --git a/noname/library/cheat.js b/noname/library/cheat.js index f66f2b755..8ac06961d 100644 --- a/noname/library/cheat.js +++ b/noname/library/cheat.js @@ -1 +1,693 @@ -export class Cheat { } +export class Cheat { + constructor() { + throw new TypeError(`${new.target.name} is not a constructor`); + } + + static i() { + window.cheat = lib.cheat; + window.game = game; + window.ui = ui; + window.get = get; + window.ai = ai; + window.lib = lib; + window._status = _status; + } + + static dy() { + var next = game.me.next; + for (var i = 0; i < 10; i++) { + if (next.identity != "zhu") { + break; + } + next = next.next; + } + next.die(); + } + + static x() { + var gl = function (dir, callback) { + var files = [], folders = []; + dir = "/Users/widget/Documents/extension/" + dir; + lib.node.fs.readdir(dir, function (err, filelist) { + for (var i = 0; i < filelist.length; i++) { + if (filelist[i][0] != "." && filelist[i][0] != "_") { + if (lib.node.fs.statSync(dir + "/" + filelist[i]).isDirectory()) { + folders.push(filelist[i]); + } + else { + files.push(filelist[i]); + } + } + } + callback(folders, files); + }); + } + var args = Array.from(arguments); + for (var i = 0; i < args.length; i++) { + args[i] = args[i][0]; + } + gl("", function (list) { + if (args.length) { + for (var i = 0; i < list.length; i++) { + if (!args.contains(list[i][0])) { + list.splice(i--, 1); + } + } + } + if (list.length) { + for (var i = 0; i < list.length; i++) { + (function (str) { + gl(str, function (folders, files) { + if (files.length > 1) { + for (var i = 0; i < files.length; i++) { + if (files[i].includes("extension.js")) { + files.splice(i--, 1); + } + else { + if (i % 5 == 0) { + str += "\n\t\t\t"; + } + str += `"${files[i]}",`; + } + } + console.log(str.slice(0, str.length - 1)); + } + }); + }(list[i])); + } + } + }); + } + + static cfg() { + var mode = lib.config.all.mode.slice(0); + mode.remove("connect"); + mode.remove("brawl"); + var banned = ["shen_guanyu", "shen_caocao", "caopi", "re_daqiao", "caorui", + "daqiao", "lingcao", "liuzan", "lusu", "luxun", "yanwen", "zhouyu", "ns_wangyue", "gw_yenaifa", + "old_caozhen", "swd_jiangziya", "xuhuang", "maliang", "guojia", "simayi", "swd_kangnalishi", "hs_siwangzhiyi", "hs_nozdormu", "old_zhuzhi"]; + var bannedcards = ["zengbin"]; + var favs = ["hs_tuoqi", "hs_siwangxianzhi", "hs_xukongzhiying", "hs_hsjiasha", "gjqt_xieyi", "gjqt_yunwuyue", "gjqt_beiluo", + "gjqt_cenying", "shen_lvmeng", "shen_zhaoyun", "shen_zhugeliang", "ow_ana", "chenlin", "ns_guanlu", "hs_guldan", "swd_guyue", + "pal_jiangyunfan", "mtg_jiesi", "swd_lanyin", "pal_liumengli", "swd_muyun", "pal_nangonghuang", "swd_muyue", "pal_murongziying", + "swd_qiner", "pal_shenqishuang", "hs_taisi", "wangji", "pal_xingxuan", "xunyou", "hs_yelise", "pal_yuejinzhao", "pal_yueqi", + "gjqt_yuewuyi", "swd_yuxiaoxue", "ow_zhaliya", "zhangchunhua", "hs_zhihuanhua", "swd_zhiyin", "old_zhonghui", "gjqt_bailitusu", + "hs_barnes", "ow_dva", "swd_hengai", "pal_jushifang", "hs_kazhakusi", "hs_lafamu", "ow_liekong", "hs_lreno", "pal_mingxiu", + "swd_murongshi", "gw_oudimu", "gjqt_ouyangshaogong", "hs_pyros", "qinmi", "gw_sanhanya", "hs_selajin", "swd_shuwaner", + "swd_situqiang", "hs_xialikeer", "pal_xuejian", "swd_yuchiyanhong", "swd_yuwentuo", "swd_zhaoyun", "zhugeliang", "gw_aigeleisi", + "gw_aimin", "gjqt_aruan", "hs_aya", "swd_cheyun", "swd_chenjingchou", "gw_diandian", "swd_huzhongxian", "hs_jinglinglong", + "hs_kaituozhe", "hs_kalimosi", "gw_linjing", "ow_luxiao", "re_luxun", "hs_morgl", "swd_sikongyu", "hs_sthrall", "sunquan", + "sunshangxiang", "gw_yioufeisisp", "gw_yisilinni", "hs_yogg", "hs_ysera", "pal_yuntianhe", "zhugejin", "zhugeke", "gw_zhuoertan", + "hs_anduin", "swd_anka", "ow_banzang", "ow_chanyata", "diaochan", "swd_duguningke", "sp_diaochan", "hetaihou", "ns_huamulan", + "swd_huanglei", "swd_huanyuanzhi", "re_huatuo", "gw_huoge", "pal_jiangcheng", "yj_jushou", "swd_kendi", "yxs_libai", + "mtg_lilianna", "xin_liru", "liuxie", "pal_lixiaoyao", "pal_longkui", "ns_nanhua", "swd_qi", "swd_septem", "gw_shasixiwusi", + "ow_tianshi", "swd_weida", "gjqt_xiayize", "swd_xiyan", "hs_xsylvanas", "hs_yelinlonghou", "ow_yuanshi", "zuoci"]; + var vintage = ["tianjian", "shuiyun", "zhuyue", "zhimeng", "poyun", "qianfang", "xfenxin", "danqing", "ywuhun", "tianwu", "xuelu", + "shahun", "yuling", "duhun", "liaoyuan", "touxi", "wangchen", "poyue", "kunlunjing", "huanhun", "yunchou", "tuzhen", "cyqiaoxie", + "mufeng", "duanyi", "guozao", "yaotong", "pozhen", "tanlin", "susheng", "jikong", "shouyin", "jilve", "hxunzhi", "huodan", "shanxian", + "ziyu", "kuoyin", "feiren", "zihui", "jidong", "baoxue", "aqianghua", "maoding", "bfengshi", "zhongdun", "pingzhang", "maichong", + "guozai", "jingxiang", "yuelu", "liechao", "fengnu", "hanshuang", "enze", "malymowang", "xshixin", "qingzun"]; + var favmodes = ["versus|three", "versus|four", "versus|two", "chess|combat"]; + for (var i = 0; i < mode.length; i++) { + game.saveConfig(mode[i] + "_banned", banned); + game.saveConfig(mode[i] + "_bannedcards", bannedcards); + } + var characters = lib.config.all.characters.slice(0); + characters.remove("standard"); + characters.remove("old"); + game.saveConfig("vintageSkills", vintage); + game.saveConfig("favouriteCharacter", favs); + game.saveConfig("favouriteMode", favmodes); + game.saveConfig("theme", "simple"); + game.saveConfig("player_border", "slim"); + game.saveConfig("cards", lib.config.all.cards); + game.saveConfig("characters", characters); + game.saveConfig("change_skin", false); + game.saveConfig("show_splash", "off"); + game.saveConfig("show_favourite", false); + game.saveConfig("animation", false); + game.saveConfig("hover_all", false); + game.saveConfig("asset_version", "v1.9"); + // game.saveConfig("characters",lib.config.all.characters); + // game.saveConfig("cards",lib.config.all.cards); + game.saveConfig("plays", ["cardpile"]); + game.saveConfig("skip_shan", false); + game.saveConfig("tao_enemy", true); + game.saveConfig("layout", "long2"); + game.saveConfig("hp_style", "ol"); + game.saveConfig("background_music", "music_off"); + game.saveConfig("background_audio", false); + game.saveConfig("background_speak", false); + game.saveConfig("show_volumn", false); + game.saveConfig("show_replay", true); + game.saveConfig("autostyle", true); + game.saveConfig("debug", true); + game.saveConfig("dev", true); + if (!lib.device) { + game.saveConfig("sync_speed", false); + } + game.reload(); + } + + static o() { + ui.arena.classList.remove("observe"); + } + + static pt() { + var list = Array.from(arguments); + while (list.length) { + var card = cheat.gn(list.pop()); + if (card) ui.cardPile.insertBefore(card, ui.cardPile.firstChild); + } + } + + static q() { + if (arguments.length == 0) { + var style = ui.css.card_style; + if (lib.config.card_style != "simple") { + lib.config.card_style = "simple"; + ui.css.card_style = lib.init.css(lib.assetURL + "theme/style/card", "simple"); + } + else { + lib.config.card_style = "default"; + ui.css.card_style = lib.init.css(lib.assetURL + "theme/style/card", "default"); + } + style.remove(); + } + else { + for (var i = 0; i < arguments.length; i++) { + cheat.g(arguments[i]); + } + } + ui.arena.classList.remove("selecting"); + ui.arena.classList.remove("tempnoe"); + } + + static p(name, i, skin) { + var list = ["swd", "hs", "pal", "gjqt", "ow", "gw"]; + if (!lib.character[name]) { + for (var j = 0; j < list.length; j++) { + if (lib.character[list[j] + "_" + name]) { + name = list[j] + "_" + name; break; + } + } + } + if (skin) { + lib.config.skin[name] = skin + } + var target; + if (typeof i == "number") { + target = game.players[i]; + } + else { + target = game.me.next; + } + if (!lib.character[name]) { + target.node.avatar.setBackground(name, "character"); + target.node.avatar.show(); + } + else { + target.init(name); + } + if (i === true) { + if (lib.config.layout == "long2") { + lib.init.layout("mobile"); + } + else { + lib.init.layout("long2"); + } + } + } + + static e() { + var cards = [], target; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + target = arguments[i]; + } + else { + cards.push(game.createCard(arguments[i])); + } + } + if (!cards.length) { + cards.push(game.createCard("qilin")); + cards.push(game.createCard("bagua")); + cards.push(game.createCard("dilu")); + cards.push(game.createCard("chitu")); + cards.push(game.createCard("muniu")); + } + target = target || game.me; + for (var i = 0; i < cards.length; i++) { + var card = target.getEquip(cards[i]); + if (card) { + card.discard(); + target.removeEquipTrigger(card); + } + target.$equip(cards[i]); + } + } + + static c() { + (function () { + var a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0; + var sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0, sg = 0; + for (var i in lib.character) { + switch (lib.character[i][1]) { + case "wei": a++; if (lib.config.banned.contains(i)) sa++; break; + case "shu": b++; if (lib.config.banned.contains(i)) sb++; break; + case "wu": c++; if (lib.config.banned.contains(i)) sc++; break; + case "qun": d++; if (lib.config.banned.contains(i)) sd++; break; + case "jin": g++; if (lib.config.banned.contains(i)) sg++; break; + case "western": e++; if (lib.config.banned.contains(i)) se++; break; + case "key": f++; if (lib.config.banned.contains(i)) sf++; break; + } + } + console.log("魏:" + (a - sa) + "/" + a); + console.log("蜀:" + (b - sb) + "/" + b); + console.log("吴:" + (c - sc) + "/" + c); + console.log("群:" + (d - sd) + "/" + d); + console.log("晋:" + (g - sg) + "/" + g); + console.log("西:" + (e - se) + "/" + e); + console.log("键:" + (f - sf) + "/" + f); + console.log("已启用:" + ((a + b + c + d + e + f) - (sa + sb + sc + sd + se + sf)) + "/" + (a + b + c + d + e + f)); + }()); + (function () { + var a = 0, b = 0, c = 0, d = 0; + var aa = 0, bb = 0, cc = 0, dd = 0; + var sa = 0, sb = 0, sc = 0, sd = 0; + var sha = 0, shan = 0, tao = 0, jiu = 0, wuxie = 0, heisha = 0, hongsha = 0; + var num = { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 10: 0, 11: 0, 12: 0, 13: 0 }; + for (var i in lib.card) { + if (get.objtype(lib.card[i]) == "object" && lib.translate[i + "_info"]) { + switch (lib.card[i].type) { + case "basic": a++; break; + case "trick": b++; break; + case "equip": c++; break; + default: d++; break; + } + } + } + for (var i = 0; i < lib.card.list.length; i++) { + if (typeof lib.card[lib.card.list[i][2]] == "object") { + switch (lib.card[lib.card.list[i][2]].type) { + case "basic": aa++; break; + case "trick": case "delay": bb++; break; + case "equip": cc++; break; + default: dd++; break; + } + switch (lib.card.list[i][0]) { + case "heart": sa++; break; + case "diamond": sb++; break; + case "club": sc++; break; + case "spade": sd++; break; + } + if (lib.card.list[i][2] == "sha") { + sha++; + if (lib.card.list[i][0] == "club" || lib.card.list[i][0] == "spade") { + heisha++; + } + else { + hongsha++; + } + } + if (lib.card.list[i][2] == "shan") { + shan++; + } + if (lib.card.list[i][2] == "tao") { + tao++; + } + if (lib.card.list[i][2] == "jiu") { + jiu++; + } + if (lib.card.list[i][2] == "wuxie") { + wuxie++; + } + num[lib.card.list[i][1]]++; + } + } + var str = "基本牌" + aa + "; " + "锦囊牌" + bb + "; " + "装备牌" + cc + "; " + "其它牌" + dd + console.log(str); + str = "红桃牌" + sa + "; " + "方片牌" + sb + "; " + "梅花牌" + sc + "; " + "黑桃牌" + sd + console.log(str); + str = "杀" + sha + "; " + "黑杀" + heisha + "; " + "红杀" + hongsha + "; " + "闪" + shan + "; " + "桃" + tao + "; " + "酒" + jiu + "; " + "无懈" + wuxie + console.log(str); + if (arguments[1]) { + for (var i = 1; i <= 13; i++) { + if (i < 10) { + console.log(i + " ", num[i]); + } + else { + console.log(i, num[i]); + } + } + } + var arr = []; + for (var i = 1; i <= 13; i++) { + arr.push(num[i]); + } + console.log((a + b + c + d) + "/" + (aa + bb + cc + dd), ...arr) + }()); + } + + static id() { + game.showIdentity(); + } + + static b() { + if (!ui.dialog || !ui.dialog.buttons) return; + for (var i = 0; i < Math.min(arguments.length, ui.dialog.buttons.length); i++) { + ui.dialog.buttons[i].link = arguments[i]; + } + } + + static uy(me) { + if (me) { + game.me.useCard({ name: "spell_yexinglanghun" }, game.me); + } + else { + var enemy = game.me.getEnemy(); + enemy.useCard({ name: "spell_yexinglanghun" }, enemy); + } + } + + static gs(name, act) { + var card = game.createCard("spell_" + (name || "yexinglanghun")); + game.me.node.handcards1.appendChild(card); + if (!act) { + game.me.actused = -99; + } + ui.updatehl(); + delete _status.event._cardChoice; + delete _status.event._targetChoice; + delete _status.event._skillChoice; + setTimeout(game.check, 300); + } + + static gc(name, act) { + var card = game.createCard("stone_" + (name || "falifulong") + "_stonecharacter"); + game.me.node.handcards1.appendChild(card); + if (!act) { + game.me.actused = -99; + } + ui.updatehl(); + delete _status.event._cardChoice; + delete _status.event._targetChoice; + delete _status.event._skillChoice; + setTimeout(game.check, 300); + } + + static a(bool) { + if (lib.config.test_game) { + game.saveConfig("test_game"); + } + else { + if (bool) { + if (typeof bool === "string") { + game.saveConfig("test_game", bool); + } + else { + game.saveConfig("test_game", "_"); + } + } + else { + game.saveConfig("test_game", true); + } + } + game.reload(); + } + + static as() { + ui.window.classList.remove("testing"); + var bg = ui.window.querySelector(".pausedbg"); + if (bg) { + bg.remove(); + } + } + + static uj() { + cheat.e("qilin"); + game.me.next.useCard({ name: "jiedao" }, [game.me, game.me.previous]); + } + + static u() { + var card = { name: "sha" }, source = game.me.next, targets = []; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + source = arguments[i]; + } + else if (Array.isArray(arguments[i])) { + targets = arguments[i]; + } + else if (typeof arguments[i] == "object" && arguments[i]) { + card = arguments[i]; + } + else if (typeof arguments[i] == "string") { + card = { name: arguments[i] } + } + } + if (!targets.length) targets.push(game.me); + source.useCard(game.createCard(card.name, card.suit, card.number, card.nature), targets); + } + + static r(bool) { + var list = ["s", "ap", "a", "am", "bp", "b", "bm", "c", "d"]; + var str = ""; + for (var i = 0; i < list.length; i++) { + if (str) str += " 、 "; + str += list[i] + "-" + lib.rank[list[i]].length; + } + console.log(str); + for (var i in lib.characterPack) { + if (!bool && lib.config.all.sgscharacters.contains(i)) continue; + var map = {}; + var str = ""; + for (var j in lib.characterPack[i]) { + var rank = get.rank(j); + if (!map[rank]) { + map[rank] = 1; + } + else { + map[rank]++; + } + } + for (var j = 0; j < list.length; j++) { + if (map[list[j]]) { + if (str) str += " 、 "; + str += list[j] + "-" + map[list[j]]; + } + } + if (str) { + console.log(lib.translate[i + "_character_config"] + ":" + str); + } + } + + var list = lib.rank.s.concat(lib.rank.ap).concat(lib.rank.a).concat(lib.rank.am). + concat(lib.rank.bp).concat(lib.rank.b).concat(lib.rank.bm).concat(lib.rank.c).concat(lib.rank.d); + Object.keys(lib.character).forEach(key => { + if (!lib.config.forbidai.includes(key) && !key.startsWith("boss_") && !key.startsWith("tafang_") && !list.includes(key)) console.log(get.translation(key), key); + }); + } + + static h(player) { + console.log(get.translation(player.getCards("h"))); + } + + static g() { + for (var i = 0; i < arguments.length; i++) { + if (i > 0 && typeof arguments[i] == "number") { + for (var j = 0; j < arguments[i] - 1; j++) { + cheat.gx(arguments[i - 1]); + } + } + else { + cheat.gx(arguments[i]); + } + } + } + + static ga(type) { + for (var i in lib.card) { + if (lib.card[i].type == type || lib.card[i].subtype == type) { + cheat.g(i); + } + } + } + + static gg() { + for (var i = 0; i < game.players.length; i++) { + for (var j = 0; j < arguments.length; j++) { + cheat.gx(arguments[j], game.players[i]); + } + } + } + + static gx(name, target) { + target = target || game.me; + var card = cheat.gn(name); + if (!card) return; + target.node.handcards1.appendChild(card); + delete _status.event._cardChoice; + delete _status.event._targetChoice; + delete _status.event._skillChoice; + game.check(); + target.update(); + ui.updatehl(); + } + + static gn(name) { + var nature = null; + var suit = null; + var suits = ["club", "spade", "diamond", "heart"]; + for (var i = 0; i < suits.length; i++) { + if (name.startsWith(suits[i])) { + suit = suits[i]; + name = name.slice(suits[i].length); + break; + } + } + if (name.startsWith("red")) { + name = name.slice(3); + suit = ["diamond", "heart"].randomGet(); + } + if (name.startsWith("black")) { + name = name.slice(5); + suit = ["spade", "club"].randomGet(); + } + + if (name == "huosha") { + name = "sha"; + nature = "fire"; + } + else if (name == "leisha") { + name = "sha"; + nature = "thunder"; + } + if (!lib.card[name]) { + return null; + } + return game.createCard(name, suit, null, nature); + } + + static ge(target) { + if (target) { + cheat.gx("zhuge", target); + cheat.gx("qinglong", target); + cheat.gx("bagua", target); + cheat.gx("dilu", target); + cheat.gx("chitu", target); + cheat.gx("muniu", target); + } + else { + cheat.g("zhuge"); + cheat.g("qinglong"); + cheat.g("bagua"); + cheat.g("dilu"); + cheat.g("chitu"); + cheat.g("muniu"); + } + } + + static gj() { + cheat.g("shandian"); + cheat.g("huoshan"); + cheat.g("hongshui"); + cheat.g("lebu"); + cheat.g("bingliang"); + cheat.g("guiyoujie"); + } + + static gf() { + for (var i in lib.card) { + if (lib.card[i].type == "food") { + cheat.g(i); + } + } + } + + static d(num, target) { + if (num == undefined) num = 1; + var cards = get.cards(num); + for (var i = 0; i < num; i++) { + var card = cards[i]; + game.me.node.handcards1.appendChild(card); + delete _status.event._cardChoice; + delete _status.event._targetChoice; + delete _status.event._skillChoice; + game.check(); + game.me.update(); + ui.updatehl(); + } + } + + static s() { + for (var i = 0; i < arguments.length; i++) { + game.me.addSkill(arguments[i], true); + } + delete _status.event._cardChoice; + delete _status.event._targetChoice; + delete _status.event._skillChoice; + game.check(); + } + + static t(num) { + if (game.players.contains(num)) { + num = game.players.indexOf(num); + } + if (num == undefined) { + for (var i = 0; i < game.players.length; i++) cheat.t(i); + return; + } + var player = game.players[num]; + var cards = player.getCards("hej"); + for (var i = 0; i < cards.length; i++) { + cards[i].discard(); + } + player.removeEquipTrigger(); + player.update(); + } + + static to() { + for (var i = 0; i < game.players.length; i++) { + if (game.players[i] != game.me) { + cheat.t(i); + } + } + } + + static tm() { + for (var i = 0; i < game.players.length; i++) { + if (game.players[i] == game.me) { + cheat.t(i); + } + } + } + + static k(i) { + if (i == undefined) i = 1; + game.players[i].hp = 1; + cheat.t(i); + cheat.g("juedou"); + } + + static z(name) { + switch (name) { + case "cc": name = "re_caocao"; break; + case "lb": name = "re_liubei"; break; + case "sq": name = "sunquan"; break; + case "dz": name = "dongzhuo"; break; + case "ys": name = "re_yuanshao"; break; + case "zj": name = "sp_zhangjiao"; break; + case "ls": name = "liushan"; break; + case "sc": name = "sunce"; break; + case "cp": name = "caopi"; break; + case "cr": name = "caorui"; break; + case "sx": name = "sunxiu"; break; + case "lc": name = "liuchen"; break; + case "sh": name = "sunhao"; break; + } + game.zhu.init(name); + game.zhu.maxHp++; + game.zhu.hp++; + game.zhu.update(); + } +} diff --git a/noname/library/color.js b/noname/library/color.js new file mode 100644 index 000000000..09d92642e --- /dev/null +++ b/noname/library/color.js @@ -0,0 +1,5 @@ +export const color = { + black: ["club", "spade"], + red: ["diamond", "heart"], + none: ["none"] +}; diff --git a/noname/library/comparator.js b/noname/library/comparator.js new file mode 100644 index 000000000..9d73cea8b --- /dev/null +++ b/noname/library/comparator.js @@ -0,0 +1,41 @@ +export class Comparator { + constructor() { + throw new TypeError(`${new.target.name} is not a constructor`); + } + + static equals() { + if (arguments.length == 0) return false; + if (arguments.length == 1) return true; + for (let i = 1; i < arguments.length; ++i) if (arguments[i] !== arguments[0]) return false; + return true; + } + + static equalAny() { + if (arguments.length == 0) return false; + if (arguments.length == 1) return true; + for (let i = 1; i < arguments.length; ++i) if (arguments[i] === arguments[0]) return true; + return false; + } + + static notEquals() { + if (arguments.length == 0) return false; + if (arguments.length == 1) return true; + for (let i = 1; i < arguments.length; ++i) if (arguments[i] === arguments[0]) return false; + return true; + } + + static notEqualAny() { + if (arguments.length == 0) return false; + if (arguments.length == 1) return true; + for (let i = 1; i < arguments.length; ++i) if (arguments[i] !== arguments[0]) return true; + return false; + } + + static typeEquals() { + if (arguments.length == 0) return false; + if (arguments.length == 1) return arguments[0] !== null; + const type = typeof arguments[0]; + for (let i = 1; i < arguments.length; ++i) if (type !== arguments[i]) return false; + return true; + } +} diff --git a/noname/library/configuration-menu/appearance/configuration/theme.js b/noname/library/configuration-menu/appearance/configuration/theme.js index 80b3f6b11..2d8c0be8e 100644 --- a/noname/library/configuration-menu/appearance/configuration/theme.js +++ b/noname/library/configuration-menu/appearance/configuration/theme.js @@ -1,5 +1,5 @@ import { Game } from "../../../../game.js"; -import { gnc } from "../../../../gnc.js"; +import { GNC } from "../../../../gnc.js"; import { Library } from "../../../../library.js"; import { UI } from "../../../../ui.js"; import { Create } from "../../../../ui/create.js"; @@ -19,7 +19,7 @@ export const THEME = { node.menu = Create.div(node, "", "
"); } }, - onclick: gnc.of(function* (theme) { + onclick: GNC.of(function* (theme) { Game.saveConfig("theme", theme); UI.arena.hide(); Initialization.background(); diff --git a/noname/library/creation.js b/noname/library/creation.js new file mode 100644 index 000000000..6b6f7a85a --- /dev/null +++ b/noname/library/creation.js @@ -0,0 +1,21 @@ +export class Creation { + constructor() { + throw new TypeError(`${new.target.name} is not a constructor`); + } + + static get array() { + return []; + } + + static get object() { + return {}; + } + + static get nullObject() { + return Object.create(null); + } + + static get string() { + return ""; + } +} diff --git a/noname/library/element.js b/noname/library/element.js index 2b1a49366..fbee217db 100644 --- a/noname/library/element.js +++ b/noname/library/element.js @@ -1,9 +1,8212 @@ +import { Button } from "./element/button.js"; +import { Card } from "./element/card.js"; +import { Client } from "./element/client.js"; +import { Control } from "./element/control.js"; +import { Dialog } from "./element/dialog.js"; +import { GameEventPromise } from "./element/game-event-promise.js"; import { GameEvent } from "./element/game-event.js"; +import { NodeWS } from "./element/node-ws.js"; import { Player } from "./element/player.js"; import { VCard } from "./element/v-card.js"; +import { WS } from "./element/ws.js"; export const element = { + content: { + emptyEvent: function () { + event.trigger(event.name); + }, + //增加明置手牌 + addShownCards: () => { + var hs = player.getCards("h"), showingCards = event._cards.filter(showingCard => hs.includes(showingCard)), shown = player.getShownCards(); + event.gaintag.forEach(tag => player.addGaintag(showingCards, tag)); + if (!(event.cards = showingCards.filter(showingCard => !shown.includes(showingCard))).length) return; + game.log(player, "明置了", event.cards); + if (event.animate != false) player.$give(event.cards, player, false); + event.trigger("addShownCardsAfter"); + }, + //隐藏明置手牌 + hideShownCards: () => { + var shown = player.getShownCards(), hidingCards = event._cards.filter(hidingCard => shown.includes(hidingCard)); + if (!hidingCards.length) return; + if (event.gaintag.length) event.gaintag.forEach(tag => player.removeGaintag(tag, hidingCards)); + else { + var map = hidingCards.reduce((constructingMap, hidingCard) => { + hidingCard.gaintag.forEach(tag => { + if (!tag.startsWith("visible_")) return; + if (!constructingMap[tag]) constructingMap[tag] = []; + constructingMap[tag].push(hidingCard); + }); + return constructingMap; + }, {}); + Object.keys(map).forEach(key => player.removeGaintag(key, map[key])); + } + hidingCards.removeArray(player.getShownCards()); + if (!hidingCards.length) return; + game.log(player, "取消明置了", event.cards = hidingCards); + if (event.animate != false) player.$give(hidingCards, player, false); + event.trigger("hideShownCardsAfter"); + }, + //Execute the delay card effect + //执行延时锦囊牌效果 + executeDelayCardEffect: () => { + "step 0" + target.$phaseJudge(card); + event.cancelled = false; + event.trigger("executeDelayCardEffect"); + event.cardName = card.viewAs || card.name; + target.popup(event.cardName, "thunder"); + if (!lib.card[event.cardName].effect) { + game.delay(); + event.finish(); + } + else if (!lib.card[event.cardName].judge) { + game.delay(); + event.nojudge = true; + } + "step 1" + if (event.cancelled || event.nojudge) return; + var next = player.judge(card), judge = event.judge; + if (typeof judge == "function") next.judge = judge; + var judge2 = event.judge2; + if (typeof judge2 == "function") next.judge2 = judge2; + "step 2" + if (event.excluded) delete event.excluded; + else { + var cardName = event.cardName; + if (event.cancelled && !event.direct) { + var cardCancel = lib.card[cardName].cancel; + if (cardCancel) { + var next = game.createEvent(`${cardName}Cancel`); + next.setContent(cardCancel); + next.cards = [card]; + if (!card.viewAs) { + var autoViewAs = next.card = get.autoViewAs(card); + autoViewAs.expired = card.expired; + } + else { + var autoViewAs = next.card = get.autoViewAs({ + name: cardName + }, next.cards); + autoViewAs.expired = card.expired; + } + next.player = player; + } + } + else { + var next = game.createEvent(cardName); + next.setContent(lib.card[cardName].effect); + next._result = result; + next.cards = [card]; + if (!card.viewAs) { + var autoViewAs = next.card = get.autoViewAs(card); + autoViewAs.expired = card.expired; + } + else { + var autoViewAs = next.card = get.autoViewAs({ + name: cardName + }, next.cards); + autoViewAs.expired = card.expired; + } + next.player = player; + } + } + ui.clear(); + card.delete(); + }, + //Gift + //赠予 + gift: () => { + "step 0" + event.num = 0; + "step 1" + if (num < cards.length) { + event.card = cards[num]; + event.trigger("gift"); + } + else { + game.delayx(); + event.finish(); + } + "step 2" + if (event.deniedGifts.includes(card)) { + game.log(target, "拒绝了", player, "赠予的", card); + event.trigger("giftDeny"); + player.loseToDiscardpile(card).log = false; + event.trigger("giftDenied"); + return; + } + game.log(player, "将", card, "赠予了", target); + player.$give(card, target, false); + game.delay(0.5); + event.trigger("giftAccept"); + if (get.type(card, false) == "equip") target.equip(card).log = false; + else target.gain(card, player).visible = true; + event.trigger("giftAccepted"); + "step 3" + event.num++; + event.goto(1); + }, + //Recast + //重铸 + recast: () => { + "step 0" + game.log(player, "重铸了", cards); + if (typeof event.recastingLose != "function") return; + event.trigger("recastingLose"); + event.recastingLose(player, cards); + event.trigger("recastingLost"); + event.recastingLosingEvents.push(...event.next.filter(value => value.name != "arrangeTrigger")); + "step 1" + event.trigger("recast"); + "step 2" + if (typeof event.recastingGain != "function") return; + event.trigger("recastingGain"); + event.recastingGain(player, cards); + event.trigger("recastingGained"); + event.recastingGainingEvents.push(...event.next.filter(value => value.name != "arrangeTrigger")); + }, + //装备栏相关 + disableEquip: function () { + "step 0" + event.cards = []; + event.num = 0; + event.slotsx = []; + if (get.is.mountCombined()) { + event.slots.forEach(type => { + if (type == "equip3" || type == "equip4") event.slotsx.add("equip3_4"); + else event.slotsx.add(type) + }); + } + else { + event.slotsx.addArray(event.slots); + } + event.slotsx.sort(); + if (!event.slots.length) event.finish(); + "step 1" + var slot = event.slotsx[event.num]; + var slot_key = slot; + var left = player.countEnabledSlot(slot), lose; + if (slot == "equip3_4") { + lose = Math.min(left, Math.max(get.numOf(event.slots, "equip3"), get.numOf(event.slots, "equip4"))); + slot_key = "equip3"; + } + else lose = Math.min(left, get.numOf(event.slots, slot)); + if (lose <= 0) event.goto(3); + else { + game.log(player, "废除了" + get.cnNumber(lose) + "个", "#g" + get.translation(slot) + "栏"); + if (!player.disabledSlots) player.disabledSlots = {}; + if (!player.disabledSlots[slot_key]) player.disabledSlots[slot_key] = 0; + player.disabledSlots[slot_key] += lose; + var cards = player.getEquips(slot).filter(card => !event.cards.contains(card)); + if (cards.length > 0) { + if (lose >= left) { + event._result = { bool: true, links: cards }; + } + else if (cards.length > (left - lose)) { + var source = event.source, num = (cards.length - (left - lose)); + if (!source || !source.isIn()) source = player; + source.chooseButton([ + "选择" + (player == source ? "你" : get.translation(player)) + "的" + get.cnNumber(num) + "张" + get.translation(slot) + "牌置入弃牌堆", + cards, + ], true, [1, num]).set("filterOk", function () { + var evt = _status.event; + return ui.selected.buttons.reduce(function (num, button) { + if (evt.slot == "equip3_4") return num + Math.max(get.numOf(get.subtypes(button.link, false), "equip3"), get.numOf(get.subtypes(button.link, false), "equip4")); + return num + get.numOf(get.subtypes(button.link, false), evt.slot) + }, 0) == evt.required; + }).set("required", num).set("slot", slot) + } + else event.goto(3); + } + else event.goto(3) + } + "step 2" + if (result.bool) event.cards.addArray(result.links); + "step 3" + event.num++; + if (event.num < event.slotsx.length) event.goto(1); + else { + player.$syncDisable(); + if (cards.length > 0) player.loseToDiscardpile(cards); + } + }, + enableEquip: function () { + if (!event.slots.length) return; + var slotsx = [...new Set(event.slots)].sort(); + for (var slot of slotsx) { + var lost = player.countDisabledSlot(slot), gain = Math.min(lost, get.numOf(event.slots, slot)); + if (lost <= 0) continue; + else { + game.log(player, "恢复了" + get.cnNumber(gain) + "个", "#g" + get.translation(slot) + "栏"); + if (!player.disabledSlots) player.disabledSlots = {}; + if (!player.disabledSlots[slot]) player.disabledSlots[slot] = 0; + player.disabledSlots[slot] -= gain; + } + } + player.$syncDisable(); + }, + expandEquip: function () { + if (!event.slots.length) return; + var slotsx = []; + if (get.is.mountCombined()) { + event.slots.forEach(type => { + if (type == "equip3" || type == "equip4") slotsx.add("equip3_4"); + else slotsx.add(type) + }); + } + else { + slotsx.addArray(event.slots); + } + slotsx.sort(); + for (var slot of slotsx) { + var expand = get.numOf(event.slots, slot), slot_key = slot; + if (slot == "equip3_4") { + expand = Math.max(get.numOf(event.slots, "equip3"), get.numOf(event.slots, "equip4")); + slot_key = "equip3"; + } + game.log(player, "获得了" + get.cnNumber(expand) + "个额外的", "#g" + get.translation(slot) + "栏"); + if (!player.expandedSlots) player.expandedSlots = {}; + if (!player.expandedSlots[slot_key]) player.expandedSlots[slot_key] = 0; + player.expandedSlots[slot_key] += expand; + } + player.$syncExpand(); + }, + //选择顶装备要顶的牌 + replaceEquip: function () { + "step 0" + event.cards = []; + var types = get.subtypes(card, false); + if (types.length) { + var info = get.info(card, false); + if (info.customSwap) { + event.cards.addArray(player.getCards("e", function (card) { + return info.customSwap(card); + })); + event.goto(4); + } + else { + event.num = 0; + event.slots = types; + event.slotsx = []; + if (get.is.mountCombined()) { + event.slots.forEach(type => { + if (type == "equip3" || type == "equip4") event.slotsx.add("equip3_4"); + else event.slotsx.add(type) + }); + } + else { + event.slotsx.addArray(event.slots); + } + event.slotsx.sort(); + } + } + else event.goto(4); + "step 1" + var slot = event.slotsx[event.num]; + var left = player.countEquipableSlot(slot), lose; + if (slot == "equip3_4") lose = Math.min(left, Math.max(get.numOf(event.slots, "equip3"), get.numOf(event.slots, "equip4"))); + else lose = Math.min(left, get.numOf(event.slots, slot)); + if (lose <= 0) event.goto(3); + else { + var cards = player.getEquips(slot).filter(card => { + return !event.cards.contains(card) && lib.filter.canBeReplaced(card, player); + }); + if (cards.length > 0) { + if (lose >= left) { + event._result = { bool: true, links: cards }; + } + else if (cards.length > (left - lose)) { + var source = event.source, num = (cards.length - (left - lose)); + if (!source || !source.isIn()) source = player; + source.chooseButton([ + "选择替换掉" + get.cnNumber(num) + "张" + get.translation(slot) + "牌", + cards, + ], true, [1, num]).set("filterOk", function () { + var evt = _status.event; + return ui.selected.buttons.reduce(function (num, button) { + if (evt.slot == "equip3_4") return num + Math.max(get.numOf(get.subtypes(button.link, false), "equip3"), get.numOf(get.subtypes(button.link, false), "equip4")); + return num + get.numOf(get.subtypes(button.link, false), evt.slot) + }, 0) == evt.required; + }).set("required", num).set("slot", slot) + } + else event.goto(3); + } + else event.goto(3) + } + "step 2" + if (result.bool) event.cards.addArray(result.links); + "step 3" + event.num++; + if (event.num < event.slotsx.length) event.goto(1); + "step 4" + event.result = cards; + }, + //装备牌 + equip: function () { + "step 0" + var owner = get.owner(card) + if (owner) { + event.owner = owner; + owner.lose(card, ui.special, "visible").set("type", "equip").set("getlx", false); + } + else if (get.position(card) == "c") event.updatePile = true; + "step 1" + if (event.cancelled) { + event.finish(); + return; + } + if (card.willBeDestroyed("equip", player, event)) { + card.selfDestroy(event); + event.finish(); + return; + } + else if (event.owner) { + if (event.owner.getCards("hejsx").contains(card)) { + event.finish(); + return; + } + } + if (event.draw) { + game.delay(0, 300); + player.$draw(card); + } + "step 2" + if (card.clone) { + game.broadcast(function (card, player) { + if (card.clone) { + card.clone.moveDelete(player); + } + }, card, player); + card.clone.moveDelete(player); + game.addVideo("gain2", player, get.cardsInfo([card.clone])); + } + player.equiping = true; + "step 3" + var info = get.info(card, false); + var next = game.createEvent("replaceEquip"); + next.player = player; + next.card = card; + next.setContent(info.replaceEquip || "replaceEquip"); + "step 4" + var info = get.info(card, false); + if (get.itemtype(result) == "cards") { + player.lose(result, "visible").set("type", "equip").set("getlx", false).swapEquip = true; + if (info.loseThrow) { + player.$throw(result, 1000); + } + event.swapped = true; + } + "step 5" + //if(player.isMin() || player.countCards("e",{subtype:get.subtype(card)})){ + if (player.isMin() || !player.canEquip(card)) { + event.finish(); + game.cardsDiscard(card); + delete player.equiping; + return; + } + var subtype = get.subtype(card); + if (subtype == "equip6") subtype = "equip3"; + game.broadcastAll(function (type) { + if (lib.config.background_audio) { + game.playAudio("effect", type); + } + }, subtype); + player.$equip(card); + game.addVideo("equip", player, get.cardInfo(card)); + if (event.log != false) game.log(player, "装备了", card); + if (event.updatePile) game.updateRoundNumber(); + "step 6" + var info = get.info(card, false); + if (info.onEquip && (!info.filterEquip || info.filterEquip(card, player))) { + if (Array.isArray(info.onEquip)) { + for (var i = 0; i < info.onEquip.length; i++) { + var next = game.createEvent("equip_" + card.name); + next.setContent(info.onEquip[i]); + next.player = player; + next.card = card; + } + } + else { + var next = game.createEvent("equip_" + card.name); + next.setContent(info.onEquip); + next.player = player; + next.card = card; + } + if (info.equipDelay != false) game.delayx(); + } + delete player.equiping; + if (event.delay) { + game.delayx(); + } + }, + //装备栏 END + changeGroup: function () { + "step 0" + event.originGroup = player.group; + if (!event.group) event.group = player.group; + var group = event.group; + player.getHistory("custom").push(event); + if (event.broadcast !== false) { + game.broadcast(function (player, group) { + player.group = group; + player.node.name.dataset.nature = get.groupnature(group); + }, player, group); + } + player.group = group; + player.node.name.dataset.nature = get.groupnature(group); + if (event.log !== false) game.log(player, "将势力变为了", "#y" + get.translation(group + 2)); + }, + chooseToDebate: function () { + "step 0" + event.targets = event.list.filter(function (i) { + return i.countCards("h") > 0; + }); + if (!event.targets.length) event.result = { bool: false }; + else { + var next = player.chooseCardOL(event.targets, get.translation(player) + "发起了议事,请选择展示的手牌", true).set("type", "debate").set("source", player).set("ai", event.ai || function (card) { + return Math.random(); + }).set("aiCard", event.aiCard || function (target) { + var hs = target.getCards("h"); + return { bool: true, cards: [hs.randomGet()] }; + }); + next._args.remove("glow_result"); + } + "step 1" + var red = [], black = []; + event.videoId = lib.status.videoId++; + for (var i = 0; i < event.targets.length; i++) { + var card = result[i].cards[0], target = event.targets[i]; + if (get.color(card, target) == "red") red.push([target, card]); + else black.push([target, card]); + } + event.red = red; event.black = black; + if (red.length) { + game.log(red.map(function (i) { + return i[0]; + }), `意见为红色,展示了`, red.map(function (i) { + return i[1]; + })); + } + else game.log("#b无人", `意见为红色`); + if (black.length) { + game.log(black.map(function (i) { + return i[0]; + }), "意见为", "#g黑色", ",展示了", black.map(function (i) { + return i[1]; + })); + } + else game.log("#b无人", "意见为", "#g黑色"); + game.broadcastAll(function (name, id, redArgs, blackArgs) { + var dialog = ui.create.dialog(name + "发起了议事", "hidden", "forcebutton"); + dialog.videoId = id; + dialog.classList.add("scroll1"); + dialog.classList.add("scroll2"); + dialog.classList.add("fullwidth"); + dialog.classList.add("fullheight"); + dialog.buttonss = []; + + var list = ["意见为红色的角色", "意见为黑色的角色"] + for (var i = 0; i < list.length; i++) { + dialog.add(`
${list[i]}
`); + var buttons = ui.create.div(".buttons", dialog.content); + dialog.buttonss.push(buttons); + buttons.classList.add("popup"); + buttons.classList.add("guanxing"); + } + var func = function (target) { + if (target._tempTranslate) return target._tempTranslate; + var name = target.name; + if (lib.translate[name + "_ab"]) return lib.translate[name + "_ab"]; + return get.translation(name); + }; + for (var i = 0; i < redArgs.length; i++) { + var list = redArgs[i]; + var button = ui.create.button(list[1], "card", dialog.buttonss[0]); + button.querySelector(".info").innerHTML = func(list[0]); + } + for (var i = 0; i < blackArgs.length; i++) { + var list = blackArgs[i]; + var button = ui.create.button(list[1], "card", dialog.buttonss[1]); + button.querySelector(".info").innerHTML = func(list[0]); + } + dialog.open(); + }, get.translation(player), event.videoId, red, black); + game.delay(4); + "step 2" + game.broadcastAll("closeDialog", event.videoId); + var opinion = null; + if (event.red.length > event.black.length) opinion = "red"; + else if (event.red.length < event.black.length) opinion = "black"; + if (opinion) game.log(player, "本次发起的议事结果为", opinion == "red" ? `红色` : "#g黑色"); + else game.log(player, "本次发起的议事无结果"); + event.result = { + bool: true, + opinion: opinion, + red: event.red, + black: event.black, + targets: event.targets + } + "step 3" + if (event.callback) { + var next = game.createEvent("debateCallback", false); + next.player = player; + next.debateResult = get.copy(event.result); + next.setContent(event.callback); + } + }, + delay: function () { + game[event.name].apply(game, event._args) + }, + chooseCooperationFor: function () { + "step 0" + var next = player.chooseButton([ + "选择和" + get.translation(target) + "的协力方式", + [event.cardlist, "vcard"], + ], true); + next.set("ai", event.ai || function () { + return Math.random(); + }); + "step 1" + if (result.bool) { + player.cooperationWith(target, result.links[0][2].slice(12), event.reason); + } + }, + chooseToPlayBeatmap: function () { + "step 0" + if (game.online) return; + if (_status.connectMode) event.time = lib.configOL.choose_timeout; + event.videoId = lib.status.videoId++; + //给其他角色看的演奏框 + game.broadcastAll(function (player, id, beatmap) { + if (_status.connectMode) lib.configOL.choose_timeout = (Math.ceil((beatmap.timeleap[beatmap.timeleap.length - 1] + beatmap.speed * 100 + (beatmap.current || 0)) / 1000) + 5).toString(); + if (player == game.me) return; + var str = get.translation(player) + "正在演奏《" + beatmap.name + "》..."; + if (!_status.connectMode) str += "
(点击屏幕可以跳过等待AI操作)"; + ui.create.dialog(str).videoId = id; + if (ui.backgroundMusic) ui.backgroundMusic.pause(); + if (lib.config.background_audio) { + if (beatmap.filename.startsWith("ext:")) game.playAudio(beatmap.filename); + else game.playAudio("effect", beatmap.filename); + } + }, player, event.videoId, event.beatmap); + "step 1" + var beatmap = event.beatmap; + if (event.isMine()) { + var timeleap = beatmap.timeleap.slice(0); + var current = beatmap.current; + //获取两个音符的时间间隔 + var getTimeout = function () { + var time = timeleap.shift(); + var out = time - current; + current = time; + return out; + }; + //初始化一堆变量 + var score = 0; + var added = timeleap.length; + var number_of_tracks = beatmap.number_of_tracks || 6; + var custom_mapping = Array.isArray(beatmap.mapping); + var mapping = custom_mapping ? beatmap.mapping.slice() : beatmap.mapping; + var hitsound = beatmap.hitsound || "hitsound.wav"; + if (hitsound.startsWith("ext:")) hitsound = lib.assetURL + "extension/" + hitsound.slice(4); + else hitsound = lib.assetURL + "audio/effect/" + hitsound; + var hitsound_audio = new Audio(hitsound); + hitsound_audio.volume = 0.25; + var abs = 1; + var node_pos = 0; + if (custom_mapping) { + node_pos = mapping.shift(); + } + else if (mapping == "random") { + abs = get.rand(number_of_tracks); + node_pos = abs; + } + var combo = 0; + var max_combo = 0; + var nodes = []; + var roundmenu = false; + //隐藏菜单按钮 + if (ui.roundmenu && ui.roundmenu.display != "none") { + roundmenu = true; + ui.roundmenu.style.display = "none"; + } + if (ui.backgroundMusic) ui.backgroundMusic.pause(); + var event = _status.event; + event.settleed = false; + //建个框框 + var dialog = ui.create.dialog("forcebutton", "hidden"); + event.dialog = dialog; + event.dialog.textPrompt = event.dialog.add(`
${beatmap.prompt || "在音符滑条和底部判定区重合时点击屏幕!"}
`); + event.switchToAuto = function () { }; + event.dialog.classList.add("fixed"); + event.dialog.classList.add("scroll1"); + event.dialog.classList.add("scroll2"); + event.dialog.classList.add("fullwidth"); + event.dialog.classList.add("fullheight"); + event.dialog.classList.add("noupdate"); + event.dialog.style.overflow = "hidden"; + //结束后操作 + event.settle = function () { + if (event.settleed) return; + event.settleed = true; + //评分 + var acc = Math.floor(score / (added * 5) * 100); + if (!Array.isArray(lib.config.choose_to_play_beatmap_accuracies)) lib.config.choose_to_play_beatmap_accuracies = []; + lib.config.choose_to_play_beatmap_accuracies.push(acc); + if (lib.config.choose_to_play_beatmap_accuracies.length > 5) lib.config.choose_to_play_beatmap_accuracies.shift(); + game.saveConfigValue("choose_to_play_beatmap_accuracies"); + var rank; + if (acc == 100) rank = ["SS", "metal"]; + else if (acc >= 94) rank = ["S", "orange"]; + else if (acc >= 87) rank = ["A", "wood"]; + else if (acc >= 80) rank = ["B", "water"]; + else if (acc >= 65) rank = ["C", "thunder"]; + else rank = ["D", "fire"]; + event.dialog.textPrompt.innerHTML = `
演奏结束!
最大连击数:${max_combo} 精准度:${acc}%
`; + game.me.$fullscreenpop(`演奏评级:${rank[0]}`, null, null, false); + //返回结果并继续游戏 + setTimeout(function () { + event._result = { + bool: true, + accuracy: acc, + rank: rank, + }; + event.dialog.close(); + game.resume(); + _status.imchoosing = false; + if (roundmenu) ui.roundmenu.style.display = ""; + if (ui.backgroundMusic) ui.backgroundMusic.play(); + hitsound_audio.remove(); + }, 1000); + }; + event.dialog.open(); + //操作容差 + var height = event.dialog.offsetHeight; + var width = event.dialog.offsetWidth; + var range1 = (beatmap.range1 || [90, 110]); + var range2 = (beatmap.range2 || [93, 107]); + var range3 = (beatmap.range3 || [96, 104]); + var speed = (beatmap.speed || 25); + //初始化底部的条子 + var judger = ui.create.div(""); + judger.style["background-image"] = (beatmap.judgebar_color || "linear-gradient(rgba(240, 235, 3, 1), rgba(230, 225, 5, 1))"); + judger.style["border-radius"] = "3px"; + judger.style.position = "absolute"; + judger.style.opacity = "0.3"; + var heightj = Math.ceil(height * (beatmap.judgebar_height || 0.1)); + judger.style.height = heightj + "px"; + judger.style.width = width + "px"; + judger.style.left = "0px"; + judger.style.top = (height - heightj) + "px"; + event.dialog.appendChild(judger); + //生成每个音符 + var addNode = function () { + var node = ui.create.div(""); + nodes.push(node); + node.style["background-image"] = (beatmap.node_color || "linear-gradient(rgba(120, 120, 240, 1), rgba(100, 100, 230, 1))"); + node.style["border-radius"] = "3px"; + node.style.position = "absolute"; + node.style.height = Math.ceil(height / 10) + "px"; + node.style.width = Math.ceil(width / number_of_tracks) - 10 + "px"; + node._position = get.utc(); + event.dialog.appendChild(node); + + node.style.left = Math.ceil(width * node_pos / number_of_tracks + 5) + "px"; + node.style.top = "-" + (Math.ceil(height / 10)) + "px"; + ui.refresh(node); + node.style.transition = "all " + speed * 110 + "ms linear"; + node.style.transform = "translateY(" + Math.ceil(height * 1.1) + "px)"; + node.timeout = setTimeout(function () { + if (nodes.contains(node)) { + nodes.remove(node); + player.popup("Miss", "fire", false); + if (player.damagepopups.length) player.$damagepop(); + combo = 0; + } + }, speed * 110); + + if (custom_mapping) { + node_pos = mapping.shift(); + } + else if (mapping == "random") { + while (node_pos == abs) { + node_pos = get.rand(number_of_tracks); + } + abs = node_pos; + } + else { + node_pos += abs; + if (node_pos > number_of_tracks - 1) { + abs = -1; + node_pos = number_of_tracks - 2; + } + else if (node_pos < 0) { + abs = 1; + node_pos = 1; + } + } + if (timeleap.length) { + setTimeout(function () { + addNode(); + }, getTimeout()); + } + else { + setTimeout(function () { + event.settle(); + }, speed * 110 + 100) + } + } + //点击时的判断操作 + var click = function () { + if (!nodes.length) return; + for (var node of nodes) { + //用生成到点击的时间差来判断距离 + var time = get.utc(); + var top = (time - node._position) / speed; + if (top > range1[1]) continue; + else if (top < range1[0]) return; + nodes.remove(node); + clearTimeout(node.timeout); + node.style.transform = ""; + node.style.transition = "all 0s"; + node.style.top = (height * ((top - 10) / 100)) + "px"; + ui.refresh(node); + node.style.transition = "all 0.5s"; + node.style.transform = "scale(1.2)"; + node.delete(); + if (top >= range3[0] && top < range3[1]) { + score += 5; + player.popup("Perfect", "orange", false); + } + else if (top >= range2[0] && top < range2[1]) { + score += 3; + player.popup("Great", "wood", false); + } + else { + score += 1; + player.popup("Good", "soil", false); + } + if (player.damagepopups.length) player.$damagepop(); + combo++; + max_combo = Math.max(combo, max_combo); + hitsound_audio.currentTime = 0; + if (hitsound_audio.paused) Promise.resolve(hitsound_audio.play()).catch(() => void 0); + break; + } + }; + document.addEventListener(lib.config.touchscreen ? "touchstart" : "mousedown", click); + + game.pause(); + game.countChoose(); + setTimeout(() => { + if (!lib.config.background_audio) return; + if (beatmap.filename.startsWith("ext:")) game.playAudio(beatmap.filename); + else game.playAudio("effect", beatmap.filename); + }, Math.floor(speed * 100 * (0.9 + beatmap.judgebar_height)) + beatmap.current); + setTimeout(function () { + addNode(); + }, getTimeout()); + } + else if (event.isOnline()) { + event.send(); + } + else { + game.pause(); + game.countChoose(); + var settle = function () { + _status.imchoosing = false; + //Algorithm: Generate the random number range using the mean and the half standard deviation of accuracies of the player"s last 5 plays + //算法:用玩家的上5次游玩的准确率的平均数和半标准差生成随机数范围 + var choose_to_play_beatmap_accuracies = (lib.config.choose_to_play_beatmap_accuracies || []).concat(Array.from({ + length: 6 - (lib.config.choose_to_play_beatmap_accuracies || []).length + }, () => get.rand(70, 100))); + var mean = Math.round(choose_to_play_beatmap_accuracies.reduce((previousValue, currentValue) => previousValue + currentValue) / choose_to_play_beatmap_accuracies.length); + var half_standard_deviation = Math.round(Math.sqrt(choose_to_play_beatmap_accuracies.reduce((previousValue, currentValue) => previousValue + Math.pow(currentValue - mean, 2), 0)) / 2); + var acc = Math.min(Math.max(get.rand.apply(get, beatmap.aiAcc || [mean - half_standard_deviation - get.rand(0, half_standard_deviation), mean + half_standard_deviation + get.rand(0, half_standard_deviation)]), 0), 100); + var rank; + if (acc == 100) rank = ["SS", "metal"]; + else if (acc >= 94) rank = ["S", "orange"]; + else if (acc >= 87) rank = ["A", "green"]; + else if (acc >= 80) rank = ["B", "water"]; + else if (acc >= 65) rank = ["C", "thunder"]; + else rank = ["D", "fire"]; + event._result = { + bool: true, + accuracy: acc, + rank: rank, + }; + if (event.dialog) event.dialog.close(); + if (event.control) event.control.close(); + game.resume(); + }; + var song_duration = beatmap.timeleap[beatmap.timeleap.length - 1] + beatmap.speed * 100 + 1000 + (beatmap.current || 0); + var settle_timeout = setTimeout(settle, song_duration); + if (!_status.connectMode) { + var skip_timeout; + var skip = () => { + settle(); + Array.from(ui.window.getElementsByTagName("audio")).forEach(audio => { + if (audio.currentSrc.includes(beatmap.filename.startsWith("ext:") ? beatmap.name : beatmap.filename)) audio.remove(); + }); + document.removeEventListener(lib.config.touchscreen ? "touchend" : "click", skip); + clearTimeout(settle_timeout); + clearTimeout(skip_timeout); + }; + document.addEventListener(lib.config.touchscreen ? "touchend" : "click", skip); + skip_timeout = setTimeout(() => document.removeEventListener(lib.config.touchscreen ? "touchend" : "click", skip), song_duration); + } + } + "step 2" + game.broadcastAll(function (id, time) { + if (_status.connectMode) lib.configOL.choose_timeout = time; + var dialog = get.idDialog(id); + if (dialog) { + dialog.close(); + } + if (ui.backgroundMusic) ui.backgroundMusic.play(); + }, event.videoId, event.time); + var result = event.result || result; + event.result = result; + }, + chooseToMove: function () { + "step 0" + if (event.chooseTime && _status.connectMode && !game.online) { + event.time = lib.configOL.choose_timeout; + game.broadcastAll(function (time) { + lib.configOL.choose_timeout = time; + }, event.chooseTime); + } + if (event.isMine()) { + delete ui.selected.guanxing_button; + var list = event.list, filterMove = event.filterMove, filterOk = event.filterOk; + _status.imchoosing = true; + var event = _status.event; + event.settleed = false; + event.dialog = ui.create.dialog(event.prompt || "请选择要操作的牌", "hidden", "forcebutton"); + event.switchToAuto = function () { + if (!filterOk(event.moved)) { + if (!event.forced) event._result = { bool: false }; + else event._result = "ai"; + } + else { + event._result = { + bool: true, + moved: event.moved, + }; + } + event.dialog.close(); + if (ui.confirm) ui.confirm.close(); + game.resume(); + _status.imchoosing = false; + setTimeout(function () { + ui.arena.classList.remove("choose-to-move"); + }, 500); + }; + event.dialog.classList.add("scroll1"); + event.dialog.classList.add("scroll2"); + event.dialog.classList.add("fullwidth"); + if (list.length > 1) { + ui.arena.classList.add("choose-to-move"); + event.dialog.classList.add("fullheight"); + } + + event.moved = []; + var buttonss = []; + event.buttonss = buttonss; + var updateButtons = function () { + for (var i of buttonss) { + event.moved[i._link] = get.links(Array.from(i.childNodes)); + if (i.textPrompt) i.previousSibling.innerHTML = `
${i.textPrompt(event.moved[i._link])}
`; + } + if (filterOk(event.moved)) { + ui.create.confirm("o"); + } + else { + if (!event.forced) ui.create.confirm("c"); + else if (ui.confirm) ui.confirm.close(); + } + }; + var clickButtons = function () { + if (!ui.selected.guanxing_button) return; + if (ui.selected.guanxing_button.parentNode == this) return; + if (!filterMove(ui.selected.guanxing_button, this._link, event.moved)) return; + ui.selected.guanxing_button.classList.remove("glow2"); + this.appendChild(ui.selected.guanxing_button); + delete ui.selected.guanxing_button; + updateButtons(); + }; + + for (var i = 0; i < list.length; i++) { + var tex = event.dialog.add(`
${list[i][0]}
`); + tex.classList.add("choosetomove"); + var buttons = ui.create.div(".buttons", event.dialog.content, clickButtons); + buttonss.push(buttons); + buttons.classList.add("popup"); + buttons.classList.add("guanxing"); + buttons._link = i; + if (list[i][1]) { + if (get.itemtype(list[i][1]) == "cards") { + var cardsb = ui.create.buttons(list[i][1], "card", buttons); + if (list[i][2] && typeof list[i][2] == "string") { + for (var ij of cardsb) ij.node.gaintag.innerHTML = get.translation(list[i][2]); + } + } + else if (list[i][1].length == 2) { + ui.create.buttons(list[i][1][0], list[i][1][1], buttons); + } + } + if (list[i][2] && typeof list[i][2] == "function") buttons.textPrompt = list[i][2]; + } + var tex = event.dialog.add(`
点击两张牌以交换位置;点击一张牌并点击其他区域以移动卡牌
`); + tex.classList.add("choosetomove"); + + event.dialog.open(); + updateButtons(); + + event.custom.replace.button = function (button) { + var node = button.parentNode; + if (!buttonss.contains(node)) return; + if (!ui.selected.guanxing_button) { + ui.selected.guanxing_button = button; + button.classList.add("glow2"); + return; + } + if (ui.selected.guanxing_button == button) { + button.classList.remove("glow2"); + delete ui.selected.guanxing_button; + return; + } + if (!filterMove(button, ui.selected.guanxing_button, event.moved)) return; + var par1 = ui.selected.guanxing_button.parentNode, ind1 = ui.selected.guanxing_button.nextSibling, par2 = button.parentNode, ind2 = button.nextSibling; + ui.selected.guanxing_button.classList.remove("glow2"); + par1.insertBefore(button, ind1); + par2.insertBefore(ui.selected.guanxing_button, ind2); + delete ui.selected.guanxing_button; + updateButtons(); + } + event.custom.replace.confirm = function (bool) { + if (bool) event._result = { + bool: true, + moved: event.moved, + }; + else event._result = { bool: false }; + event.dialog.close(); + if (ui.confirm) ui.confirm.close(); + game.resume(); + _status.imchoosing = false; + setTimeout(function () { + ui.arena.classList.remove("choose-to-move"); + }, 500); + }; + + game.pause(); + game.countChoose(); + event.choosing = true; + } + else if (event.isOnline()) { + event.send(); + } + else { + event.result = "ai"; + } + "step 1" + if (event.time) game.broadcastAll(function (time) { + lib.configOL.choose_timeout = time; + }, event.time); + var result = event.result || result; + if ((!result || result == "ai" || (event.forced && !result.bool)) && event.processAI) { + var moved = event.processAI(event.list); + if (moved) result = { + bool: true, + moved: moved, + } + else result = { bool: false }; + } + event.result = result; + }, + showCharacter: function () { + "step 0" + event.trigger("showCharacterEnd"); + "step 1" + event.trigger("showCharacterAfter"); + if (get.mode() == "identity" && player.isZhu) event.trigger("zhuUpdate"); + }, + removeCharacter: function () { + player.$removeCharacter(event.num); + }, + chooseUseTarget: function () { + "step 0" + if (get.is.object(card) && !event.viewAs) card.isCard = true; + if (cards && get.itemtype(card) != "card") { + card = get.copy(card); + card.cards = cards.slice(0); + event.card = card; + } + if (!lib.filter.cardEnabled(card, player) || (event.addCount !== false && !lib.filter.cardUsable(card, player))) { + event.result = { bool: false }; + event.finish(); + return; + } + var info = get.info(card); + var range; + if (!info.notarget) { + var select = get.copy(info.selectTarget); + range = get.select(select); + if (event.selectTarget) range = get.select(event.selectTarget); + game.checkMod(card, player, range, "selectTarget", player); + } + if (info.notarget || range[1] <= -1) { + if (!info.notarget && range[1] <= -1) { + for (var i = 0; i < targets.length; i++) { + if (event.filterTarget) { + if (!event.filterTarget(card, player, targets[i])) { + targets.splice(i--, 1); + } + } + else if (!player.canUse(card, targets[i], event.nodistance ? false : null, event.addCount === false ? null : true)) { + targets.splice(i--, 1); + } + } + if (targets.length) { + event.targets2 = targets; + } + else { + event.finish(); + return; + } + } + else event.targets2 = []; + if (event.forced) { + event._result = { bool: true }; + return; + } + else { + var next = player.chooseBool(); + next.set("prompt", event.prompt || ("是否" + (event.targets2.length ? "对" : "") + get.translation(event.targets2) + "使用" + get.translation(card) + "?")); + if (event.hsskill) next.setHiddenSkill(event.hsskill); + if (event.prompt2) next.set("prompt2", event.prompt2); + next.ai = function () { + var eff = 0; + for (var i = 0; i < event.targets2.length; i++) { + eff += get.effect(event.targets2[i], card, player, player); + } + return eff > 0; + }; + } + } + else { + if (event.filterTarget) { + var targets = game.filterPlayer(function (current) { + return event.filterTarget(card, player, current); + }); + if (targets.length < range[0]) { + event._result = { bool: false }; + return; + } + else if (!info.complexTarget && targets.length == range[0] && range[0] == range[1]) { + event.targets2 = targets; + event._result = { bool: true }; + return; + } + } + var next = player.chooseTarget(); + next.set("_get_card", card); + next.set("filterTarget", event.filterTarget || function (card, player, target) { + if (!_status.event.targets.contains(target)) return false; + if (!_status.event.nodistance && !lib.filter.targetInRange(card, player, target)) return false; + return lib.filter.targetEnabledx(card, player, target); + }); + next.set("ai", event.ai || get.effect_use); + next.set("selectTarget", event.selectTarget || lib.filter.selectTarget); + if (event.nodistance) next.set("nodistance", true); + if (event.forced) next.set("forced", true); + if (event.addCount !== false) next.set("addCount_extra", true); + next.set("targets", targets); + next.set("prompt", event.prompt || ("选择" + get.translation(card) + "的目标")); + if (event.prompt2) next.set("prompt2", event.prompt2); + if (event.hsskill) next.setHiddenSkill(event.hsskill); + } + "step 1" + if (result.bool) { + event.result = { + bool: true, + targets: event.targets2 || result.targets, + }; + var args = [card, event.targets2 || result.targets]; + if (cards) args.push(cards.slice()); + var next = player.useCard(...args); + next.oncard = event.oncard; + if (cards) next.cards = cards.slice(0); + if (event.nopopup) next.nopopup = true; + if (event.animate === false) next.animate = false; + if (event.throw === false) next.throw = false; + if (event.addCount === false) next.addCount = false; + if (event.noTargetDelay) next.targetDelay = false; + if (event.nodelayx) next.delayx = false; + if (event.logSkill) { + if (typeof event.logSkill == "string") { + next.skill = event.logSkill; + } + else if (Array.isArray(event.logSkill)) { + player.logSkill.apply(player, event.logSkill); + } + } + } + else event.result = { bool: false }; + }, + chooseToDuiben: function () { + "step 0" + if (!event.namelist) event.namelist = ["全军出击", "分兵围城", "奇袭粮道", "开城诱敌"]; + game.broadcastAll(function (list) { + var list2 = ["db_atk1", "db_atk2", "db_def1", "db_def2"]; + for (var i = 0; i < 4; i++) { + lib.card[list2[i]].image = "card/" + list2[i] + (list[0] == "全军出击" ? "" : "_" + list[i]); + lib.translate[list2[i]] = list[i]; + } + }, event.namelist); + if (!event.title) event.title = "对策"; + game.log(player, "向", target, "发起了", "#y" + event.title); + if (!event.ai) event.ai = function () { return 1 + Math.random() }; + if (_status.connectMode) { + player.chooseButtonOL([ + [player, [event.title + ":请选择一种策略", [[["", "", "db_def2"], ["", "", "db_def1"]], "vcard"]], true], + [target, [event.title + ":请选择一种策略", [[["", "", "db_atk1"], ["", "", "db_atk2"]], "vcard"]], true] + ], function () { }, event.ai).set("switchToAuto", function () { + _status.event.result = "ai"; + }).set("processAI", function () { + var buttons = _status.event.dialog.buttons; + return { + bool: true, + links: [buttons.randomGet().link], + } + }); + } + "step 1" + if (_status.connectMode) { + event.mes = result[player.playerid].links[0][2]; + event.tes = result[target.playerid].links[0][2]; + event.goto(4); + } + else { + player.chooseButton([event.title + ":请选择一种策略", [[["", "", "db_def2"], ["", "", "db_def1"]], "vcard"]], true).ai = event.ai; + } + "step 2" + event.mes = result.links[0][2]; + target.chooseButton([event.title + ":请选择一种策略", [[["", "", "db_atk1"], ["", "", "db_atk2"]], "vcard"]], true).ai = event.ai; + "step 3" + event.tes = result.links[0][2]; + "step 4" + game.broadcast(function () { + ui.arena.classList.add("thrownhighlight"); + }); + ui.arena.classList.add("thrownhighlight"); + game.addVideo("thrownhighlight1"); + target.$compare(game.createCard(event.tes, "", ""), player, game.createCard(event.mes, "", "")); + game.log(target, "选择的策略为", "#g" + get.translation(event.tes)); + game.log(player, "选择的策略为", "#g" + get.translation(event.mes)); + game.delay(0, 1500); + "step 5" + var mes = event.mes.slice(6); + var tes = event.tes.slice(6); + var str; + if (mes == tes) { + str = get.translation(player) + event.title + "成功"; + player.popup("胜", "wood"); + target.popup("负", "fire"); + game.log(player, "#g胜"); + event.result = { bool: true }; + } + else { + str = get.translation(player) + event.title + "失败"; + target.popup("胜", "wood"); + player.popup("负", "fire"); + game.log(target, "#g胜"); + event.result = { bool: false }; + } + event.result.player = event.mes; + event.result.target = event.tes; + game.broadcastAll(function (str) { + var dialog = ui.create.dialog(str); + dialog.classList.add("center"); + setTimeout(function () { + dialog.close(); + }, 1000); + }, str); + game.trySkillAudio(event.getParent().name + "_" + (event.result.bool ? "true" + mes : "false"), player); + game.delay(2); + "step 6" + game.broadcastAll(function () { + ui.arena.classList.remove("thrownhighlight"); + }); + game.addVideo("thrownhighlight2"); + if (event.clear !== false) { + game.broadcastAll(ui.clear); + } + }, + chooseToPSS: function () { + "step 0" + game.log(player, "对", target, "发起了猜拳"); + if (_status.connectMode) { + player.chooseButtonOL([ + [player, ["猜拳:请选择一种手势", [[["", "", "pss_stone"], ["", "", "pss_scissor"], ["", "", "pss_paper"]], "vcard"]], true], + [target, ["猜拳:请选择一种手势", [[["", "", "pss_stone"], ["", "", "pss_scissor"], ["", "", "pss_paper"]], "vcard"]], true] + ], function () { }, function () { return 1 + Math.random() }).set("switchToAuto", function () { + _status.event.result = "ai"; + }).set("processAI", function () { + var buttons = _status.event.dialog.buttons; + return { + bool: true, + links: [buttons.randomGet().link], + } + }); + } + "step 1" + if (_status.connectMode) { + event.mes = result[player.playerid].links[0][2]; + event.tes = result[target.playerid].links[0][2]; + event.goto(4); + } + else { + player.chooseButton(["猜拳:请选择一种手势", [[["", "", "pss_stone"], ["", "", "pss_scissor"], ["", "", "pss_paper"]], "vcard"]], true).ai = function () { return 1 + Math.random() }; + } + "step 2" + event.mes = result.links[0][2]; + target.chooseButton(["猜拳:请选择一种手势", [[["", "", "pss_stone"], ["", "", "pss_scissor"], ["", "", "pss_paper"]], "vcard"]], true).ai = function () { return 1 + Math.random() }; + "step 3" + event.tes = result.links[0][2]; + "step 4" + game.broadcast(function () { + ui.arena.classList.add("thrownhighlight"); + }); + ui.arena.classList.add("thrownhighlight"); + game.addVideo("thrownhighlight1"); + player.$compare(game.createCard(event.mes, "", ""), target, game.createCard(event.tes, "", "")); + game.log(player, "选择的手势为", "#g" + get.translation(event.mes)); + game.log(target, "选择的手势为", "#g" + get.translation(event.tes)); + game.delay(0, 1500); + "step 5" + var mes = event.mes.slice(4); + var tes = event.tes.slice(4); + var str; + if (mes == tes) { + str = "二人平局"; + player.popup("平", "metal"); + target.popup("平", "metal"); + game.log("猜拳的结果为", "#g平局"); + event.result = { tie: true }; + } + else { + if ({ paper: "stone", scissor: "paper", stone: "scissor" }[mes] == tes) { + str = get.translation(player) + "胜利"; + player.popup("胜", "wood"); + target.popup("负", "fire"); + game.log(player, "#g胜"); + event.result = { bool: true }; + } + else { + str = get.translation(target) + "胜利"; + target.popup("胜", "wood"); + player.popup("负", "fire"); + game.log(target, "#g胜"); + event.result = { bool: false }; + } + } + game.broadcastAll(function (str) { + var dialog = ui.create.dialog(str); + dialog.classList.add("center"); + setTimeout(function () { + dialog.close(); + }, 1000); + }, str); + game.delay(2); + "step 6" + game.broadcastAll(function () { + ui.arena.classList.remove("thrownhighlight"); + }); + game.addVideo("thrownhighlight2"); + if (event.clear !== false) { + game.broadcastAll(ui.clear); + } + }, + cardsDiscard: function () { + game.getGlobalHistory().cardMove.push(event); + var withPile = false; + for (var i = 0; i < cards.length; i++) { + if (cards[i].willBeDestroyed("discardPile", null, event)) { + cards[i].selfDestroy(event); + continue; + } + if (get.position(cards[i], true) == "c") withPile = true; + cards[i].discard(); + } + if (withPile) game.updateRoundNumber(); + }, + orderingDiscard: function () { + var cards = event.relatedEvent.orderingCards.slice(0); + for (var i = 0; i < cards.length; i++) { + if (get.position(cards[i], true) != "o") cards.splice(i--, 1); + } + if (cards.length) game.cardsDiscard(cards); + }, + cardsGotoOrdering: function () { + game.getGlobalHistory().cardMove.push(event); + var withPile = false; + for (var i = 0; i < cards.length; i++) { + if (cards[i].willBeDestroyed("ordering", null, event)) { + cards[i].selfDestroy(event); + continue; + } + if (get.position(cards[i], true) == "c") withPile = true; + cards[i].fix(); + ui.ordering.appendChild(cards[i]); + } + if (withPile) game.updateRoundNumber(); + var evt = event.relatedEvent || event.getParent(); + if (!evt.orderingCards) evt.orderingCards = []; + if (!evt.noOrdering && !evt.cardsOrdered) { + evt.cardsOrdered = true; + var next = game.createEvent("orderingDiscard", false, evt.getParent()); + next.relatedEvent = evt; + next.setContent("orderingDiscard"); + } + if (!evt.noOrdering) evt.orderingCards.addArray(cards); + }, + cardsGotoSpecial: function () { + game.getGlobalHistory().cardMove.push(event); + var withPile = false; + for (var i = 0; i < cards.length; i++) { + if (cards[i].willBeDestroyed("special", null, event)) { + cards[i].selfDestroy(event); + continue; + } + if (get.position(cards[i], true) == "c") withPile = true; + cards[i].fix(); + ui.special.appendChild(cards[i]); + } + if (withPile) game.updateRoundNumber(); + if (event.toRenku) { + _status.renku.addArray(cards); + if (_status.renku.length > 6) { + var cards = _status.renku.splice(0, _status.renku.length - 6); + game.log(cards, "从仁库进入了弃牌堆"); + game.cardsDiscard(cards).set("outRange", true).fromRenku = true; + } + game.updateRenku(); + } + }, + cardsGotoPile: function () { + if (event.washCard) { + event.trigger("washCard") + for (var i = 0; i < lib.onwash.length; i++) { + if (lib.onwash[i]() == "remove") { + lib.onwash.splice(i--, 1); + } + } + } + game.getGlobalHistory().cardMove.push(event); + if (!event._triggeronly) game.$cardsGotoPile(event); + }, + chooseToEnable: function () { + "step 0" + var list = []; + for (var i = 1; i <= 5; i++) { + if (player.hasDisabledSlot(i)) list.push("equip" + i); + } + if (!list.length) event.finish(); + else if (list.length == 1) { + event.list = list; + event._result = { control: list[0] }; + } + else { + var next = player.chooseControl(list); + next.set("prompt", "请选择恢复一个装备栏"); + if (!event.ai) event.ai = function (event, player, list) { + return list.randomGet(); + } + event.ai = event.ai(event.getParent(), player, list); + next.ai = function () { + return event.ai; + }; + } + "step 1" + event.result = { control: result.control }; + player.enableEquip(result.control); + }, + chooseToDisable: function () { + "step 0" + var list = []; + for (var i = 1; i <= 5; i++) { + if (player.hasEnabledSlot(i)) list.push("equip" + i); + } + if (event.horse) { + if (list.contains("equip3") && (get.is.mountCombined() || list.contains("equip4"))) list.push("equip3_4"); + list.remove("equip3"); + list.remove("equip4"); + } + if (!list.length) event.finish(); + else if (list.length == 1) { + event.list = list; + event._result = { control: list[0] }; + } + else { + list.sort(); + event.list = list; + var next = player.chooseControl(list); + next.set("prompt", "请选择废除一个装备栏"); + if (!event.ai) event.ai = function (event, player, list) { + return list.randomGet(); + } + event.ai = event.ai(event.getParent(), player, list); + next.ai = function () { + return event.ai; + }; + } + "step 1" + event.result = { control: result.control }; + if (result.control == "equip3_4") { + player.disableEquip(3, 4); + } + else player.disableEquip(result.control); + }, + swapEquip: function () { + "step 0" + game.log(player, "和", target, "交换了装备区中的牌") + event.cards = [player.getCards("e"), target.getCards("e")]; + game.loseAsync({ + player: player, + target: target, + cards1: event.cards[0], + cards2: event.cards[1], + }).setContent("swapHandcardsx"); + "step 1" + for (var i = 0; i < event.cards[1].length; i++) { + if (get.position(event.cards[1][i], true) == "o") player.equip(event.cards[1][i]); + } + for (var i = 0; i < event.cards[0].length; i++) { + if (get.position(event.cards[0][i], true) == "o") target.equip(event.cards[0][i]); + } + }, + disableJudge: function () { + "step 0" + game.log(player, "废除了判定区"); + var js = player.getCards("j"); + if (js.length) player.discard(js); + player.storage._disableJudge = true; + //player.markSkill("_disableJudge"); + "step 1" + game.broadcastAll(function (player, card) { + player.$disableJudge(); + }, player); + }, + enableJudge: function () { + if (!player.storage._disableJudge) return; + game.log(player, "恢复了判定区"); + game.broadcastAll(function (player) { + player.$enableJudge(); + }, player); + }, + /*----分界线----*/ + phasing: function () { + "step 0" + while (ui.dialogs.length) { + ui.dialogs[0].close(); + } + game.phaseNumber++; + player.phaseNumber++; + game.broadcastAll(function (player, player2, num, popup) { + if (lib.config.glow_phase) { + if (player2) player2.classList.remove("glow_phase"); + player.classList.add("glow_phase"); + } + player.phaseNumber = num; + if (popup && lib.config.show_phase_prompt) player.popup("回合开始", null, false); + }, player, _status.currentPhase, player.phaseNumber, !player.noPhaseDelay); + _status.currentPhase = player; + _status.discarded = []; + game.syncState(); + game.addVideo("phaseChange", player); + if (game.phaseNumber == 1) { + delete player._start_cards; + if (lib.configOL.observe) { + lib.configOL.observeReady = true; + game.send("server", "config", lib.configOL); + } + } + game.log(); + game.log(player, "的回合开始"); + player._noVibrate = true; + if (get.config("identity_mode") != "zhong" && get.config("identity_mode") != "purple" && !_status.connectMode) { + var num; + switch (get.config("auto_identity")) { + case "one": num = 1; break; + case "two": num = 2; break; + case "three": num = 3; break; + case "always": num = -1; break; + default: num = 0; break; + } + if (num && !_status.identityShown && game.phaseNumber > game.players.length * num && game.showIdentity) { + if (!_status.video) player.popup("显示身份"); + _status.identityShown = true; + game.showIdentity(false); + } + } + player.ai.tempIgnore = []; + if (ui.land && ui.land.player == player) { + game.addVideo("destroyLand"); + ui.land.destroy(); + } + "step 1" + event.trigger("phaseBeginStart"); + }, + toggleSubPlayer: function () { + "step 0" + var list = event.list || player.storage.subplayer.skills.slice(0); + list.remove(player.storage.subplayer.name2); + event.list = list; + if (!event.directresult) { + if (list.length > 1) { + var dialog = ui.create.dialog("更换一个随从", "hidden"); + dialog.add([list, "character"]); + player.chooseButton(dialog, true); + } + else if (list.length == 1) { + event.directresult = list[0]; + } + else { + event.finish(); + } + } + else { + if (!list.contains(event.directresult)) { + event.finish(); + } + } + "step 1" + if (!event.directresult) { + if (result && result.bool && result.links[0]) { + event.directresult = result.links[0]; + } + else { + event.finish(); + return; + } + } + if (player.storage.subplayer) { + var current = player.storage.subplayer.name2; + if (event.directresult == current) { + event.finish(); + return; + } + player.storage[current].hp = player.hp; + player.storage[current].maxHp = player.maxHp; + player.storage[current].hs = player.getCards("h"); + player.storage[current].es = player.getCards("e"); + player.lose(player.getCards("he"), ui.special)._triggered = null; + + var cfg = player.storage[event.directresult]; + player.storage.subplayer.name2 = event.directresult; + player.reinit(current, event.directresult, [ + cfg.hp, + cfg.maxHp + ]); + if (cfg.hs.length) player.directgain(cfg.hs); + if (cfg.es.length) player.directequip(cfg.es); + } + }, + exitSubPlayer: function () { + "step 0" + if (player.storage.subplayer) { + var current = player.storage.subplayer.name2; + if (event.remove) { + player.lose(player.getCards("he"), ui.discardPile)._triggered = null; + } + else { + player.storage[current].hp = player.hp; + player.storage[current].maxHp = player.maxHp; + player.storage[current].hs = player.getCards("h"); + player.storage[current].es = player.getCards("e"); + player.lose(player.getCards("he"), ui.special)._triggered = null; + } + player.reinit(current, player.storage.subplayer.name, [ + player.storage.subplayer.hp, + player.storage.subplayer.maxHp + ]); + player.update(); + if (event.remove) { + if (player.storage[current].onremove) { + player.storage[current].onremove(player); + } + delete player.storage[current]; + player.storage.subplayer.skills.remove(current); + game.log(player, "牺牲了随从", "#g" + current); + } + else { + game.log(player, "收回了随从", "#g" + current); + } + player.addSkill(player.storage.subplayer.skills); + } + "step 1" + if (player.storage.subplayer) { + player.directgain(player.storage.subplayer.hs); + player.directequip(player.storage.subplayer.es); + } + player.removeSkill("subplayer"); + "step 2" + if (event.remove) { + event.trigger("subPlayerDie"); + } + }, + callSubPlayer: function () { + "step 0" + var list = player.getSubPlayers(event.tag); + event.list = list; + if (!event.directresult) { + if (list.length > 1) { + var dialog = ui.create.dialog("调遣一个随从", "hidden"); + dialog.add([list, "character"]); + player.chooseButton(dialog, true); + } + else if (list.length == 1) { + event.directresult = list[0]; + } + else { + event.finish(); + } + } + else { + if (!list.contains(event.directresult)) { + event.finish(); + } + } + "step 1" + if (!event.directresult) { + if (result && result.bool && result.links[0]) { + event.directresult = result.links[0]; + } + else { + event.finish(); + return; + } + } + if (event.directresult) { + var cfg = player.storage[event.directresult]; + var source = cfg.source || player.name; + var name = event.directresult; + game.log(player, "调遣了随从", "#g" + name); + player.storage.subplayer = { + name: source, + name2: event.directresult, + hp: player.hp, + maxHp: player.maxHp, + skills: event.list.slice(0), + hs: player.getCards("h"), + es: player.getCards("e"), + intro2: cfg.intro2 + } + player.removeSkill(event.list); + player.reinit(source, name, [cfg.hp, cfg.maxHp]); + player.addSkill("subplayer"); + player.lose(player.getCards("he"), ui.special)._triggered = null; + if (cfg.hs.length) player.directgain(cfg.hs); + if (cfg.es.length) player.directequip(cfg.es); + } + "step 2" + game.delay(); + }, + addExtraTarget: function () { + "step 0" + event.num = 0; + "step 1" + var target = targets[num], info = get.info(card); + if (target == event.target && event.addedTarget) { + event.addedTargets[num] = event.addedTarget; + event._result = { bool: false }; + } + else if (game.hasPlayer(function (current) { + return info.filterAddedTarget(card, player, current, target) + })) { + var next = player.chooseTarget(get.translation(event.card) + ":选择" + get.translation(targets[num]) + "对应的指向目标", function (card, player, target) { + var card = get.card(), info = get.info(card); + return info.filterAddedTarget(card, player, target, _status.event.preTarget) + }, true); + next.set("_get_card", card); + next.set("preTarget", targets[num]); + next.set("ai", target => get.effect(target, get.card(), player, _status.event.player)); + } + else { + event.addedTargets[num] = false; + event._result = { bool: false }; + } + "step 2" + if (result.bool) { + event.addedTargets[num] = result.targets[0]; + player.line2([targets[num], result.targets[0]]); + } + event.num++; + if (event.num < targets.length) event.goto(1); + }, + reverseOrder: function () { + "step 0" + game.delay(); + "step 1" + var choice; + if (get.tag(card, "multineg")) { + choice = (player.previous.side == player.side) ? "逆时针" : "顺时针"; + } + else { + choice = (player.next.side == player.side) ? "逆时针" : "顺时针"; + } + player.chooseControl("顺时针", "逆时针", function (event, player) { + return _status.event.choice || "逆时针"; + }).set("prompt", "选择" + get.translation(card) + "的结算方向").set("choice", choice).set("forceDie", true); + "step 2" + if (result && result.control == "顺时针") { + var evt = event.getParent(), sorter = (_status.currentPhase || player); + evt.fixedSeat = true; + evt.targets.sortBySeat(sorter); + evt.targets.reverse(); + if (evt.targets[evt.targets.length - 1] == sorter) { + evt.targets.unshift(evt.targets.pop()); + } + } + }, + addJudgeCard: function () { + if (lib.filter.judge(card, player, target) && cards.length && get.position(cards[0], true) == "o") target.addJudge(card, cards); + }, + equipCard: function () { + if (cards.length && get.position(cards[0], true) == "o") target.equip(cards[0]); + }, + gameDraw: function () { + "step 0" + if (_status.brawl && _status.brawl.noGameDraw) { + event.finish(); + return; + } + var end = player; + var numx = num; + do { + if (typeof num == "function") { + numx = num(player); + } + if (player.getTopCards) player.directgain(player.getTopCards(numx)); + else player.directgain(get.cards(numx)); + if (player.singleHp === true && get.mode() != "guozhan" && (lib.config.mode != "doudizhu" || _status.mode != "online")) { + player.doubleDraw(); + } + player._start_cards = player.getCards("h"); + player = player.next; + } + while (player != end); + event.changeCard = get.config("change_card"); + if (_status.connectMode || (lib.config.mode == "doudizhu" && _status.mode == "online") || lib.config.mode != "identity" && lib.config.mode != "guozhan" && lib.config.mode != "doudizhu") { + event.changeCard = "disabled"; + } + "step 1" + if (event.changeCard != "disabled" && !_status.auto) { + event.dialog = ui.create.dialog("是否使用手气卡?"); + ui.create.confirm("oc"); + event.custom.replace.confirm = function (bool) { + _status.event.bool = bool; + game.resume(); + } + } + else { + event.finish(); + } + "step 2" + if (event.changeCard == "once") { + event.changeCard = "disabled"; + } + else if (event.changeCard == "twice") { + event.changeCard = "once"; + } + else if (event.changeCard == "disabled") { + event.bool = false; + return; + } + _status.imchoosing = true; + event.switchToAuto = function () { + _status.event.bool = false; + game.resume(); + } + game.pause(); + "step 3" + _status.imchoosing = false; + if (event.bool) { + if (game.changeCoin) { + game.changeCoin(-3); + } + var hs = game.me.getCards("h"); + game.addVideo("lose", game.me, [get.cardsInfo(hs), [], [], []]); + for (var i = 0; i < hs.length; i++) { + hs[i].discard(false); + } + game.me.directgain(get.cards(hs.length)); + event.goto(2); + } + else { + if (event.dialog) event.dialog.close(); + if (ui.confirm) ui.confirm.close(); + game.me._start_cards = game.me.getCards("h"); + event.finish(); + } + }, + phaseLoop: function () { + "step 0" + var num = 1, current = player; + while (current.getSeatNum() == 0) { + current.setSeatNum(num); + current = current.next; + num++; + } + "step 1" + for (var i = 0; i < lib.onphase.length; i++) { + lib.onphase[i](); + } + player.phase(); + "step 2" + if (!game.players.contains(event.player.next)) { + event.player = game.findNext(event.player.next); + } + else { + event.player = event.player.next; + } + event.goto(1); + }, + loadPackage: function () { + "step 0" + if (event.packages.length) { + window.game = game; + var pack = event.packages.shift().split("/"); + lib.init.js(lib.assetURL + pack[0], pack[1], game.resume); + game.pause(); + } + else { + event.finish(); + } + "step 1" + if (!lib.config.dev) delete window.game; + var character = lib.imported.character; + var card = lib.imported.card; + var i, j, k; + for (i in character) { + if (character[i].character) { + var characterPack = lib.characterPack[i]; + if (characterPack) Object.assign(characterPack, character[i].character); + else lib.characterPack[i] = character[i].character; + } + if (character[i].forbid && character[i].forbid.contains(lib.config.mode)) continue; + if (character[i].mode && character[i].mode.contains(lib.config.mode) == false) continue; + + if (Array.isArray(lib[j]) && Array.isArray(character[i][j])) { + lib[j].addArray(character[i][j]); + continue; + } + for (j in character[i]) { + if (j == "mode" || j == "forbid" || j == "characterSort") continue; + for (k in character[i][j]) { + if (j == "character") { + if (!character[i][j][k][4]) { + character[i][j][k][4] = []; + } + if (character[i][j][k][4].contains("boss") || + character[i][j][k][4].contains("hiddenboss")) { + lib.config.forbidai.add(k); + } + if (lib.config.forbidai_user && lib.config.forbidai_user.contains(k)) { + lib.config.forbidai.add(k); + } + for (var l = 0; l < character[i][j][k][3].length; l++) { + lib.skilllist.add(character[i][j][k][3][l]); + } + } + if (j == "translate" && k == i) { + lib[j][k + "_character_config"] = character[i][j][k]; + } + else { + if (lib[j][k] == undefined) { + Object.defineProperty(lib[j], k, Object.getOwnPropertyDescriptor(character[i][j], k)); + } + else if (Array.isArray(lib[j][k]) && Array.isArray(character[i][j][k])) { + lib[j][k].addArray(character[i][j][k]); + } + else { + console.log( + `dublicate ${j} in character ${i}:\n${k}:\nlib.${j}.${k}`, + lib[j][k], + `\ncharacter.${i}.${j}.${k}`, + character[i][j][k] + ); + } + } + } + } + } + for (i in card) { + var cardPack = lib.cardPack[i] ? lib.cardPack[i] : lib.cardPack[i] = []; + if (card[i].card) { + for (var j in card[i].card) { + if (!card[i].card[j].hidden && card[i].translate[j + "_info"]) { + cardPack.push(j); + } + } + } + for (j in card[i]) { + if (j == "mode" || j == "forbid") continue; + if (j == "list") continue; + for (k in card[i][j]) { + if (j == "skill" && k[0] == "_" && !lib.config.cards.contains(i)) { + continue; + } + if (j == "translate" && k == i) { + lib[j][k + "_card_config"] = card[i][j][k]; + } + else { + if (lib[j][k] == undefined) Object.defineProperty(lib[j], k, Object.getOwnPropertyDescriptor(card[i][j], k)); + else { + console.log( + `dublicate ${j} in card ${i}:\n${k}\nlib.${j}.${k}`, + lib[j][k], + `\ncard.${i}.${j}.${k}`, + card[i][j][k] + ); + } + } + } + } + } + event.goto(0); + }, + loadMode: function () { + "step 0" + window.game = game; + lib.init.js(lib.assetURL + "mode", event.mode, game.resume); + game.pause(); + "step 1" + if (!lib.config.dev) delete window.game; + event.result = lib.imported.mode[event.mode]; + delete lib.imported.mode[event.mode]; + }, + forceOver: function () { + "step 0" + while (ui.controls.length) { + ui.controls[0].close(); + } + while (ui.dialogs.length) { + ui.dialogs[0].close(); + } + "step 1" + if (event.bool != "noover") { + game.over(event.bool); + } + if (event.callback) { + event.callback(); + } + }, + arrangeTrigger: function () { + "step 0" + event.noDirectUse = info => !lib.skill[info.skill].silent && lib.translate[info.skill];//是否触发同顺序选择 + "step 1" + if (event.doing && event.doing.todoList.length) return; + if (event.doingList.length) return event.doing = event.doingList.shift(); + event.finish(); + "step 2" + if (trigger.filterStop && trigger.filterStop()) return event.finish(); + const current = event.doing.todoList.find(info => lib.filter.filterTrigger(trigger, info.player, event.triggername, info.skill)); + if (!current) { + event.doing.todoList = []; + return event.goto(1); + } + event.doing.todoList = event.doing.todoList.filter(i => i.priority <= current.priority); + event.num = event.doing.todoList.indexOf(current); + if (!event.noDirectUse(current)) return event.goto(5); + event.choice = event.doing.todoList.filter(info => { + if (!lib.filter.filterTrigger(trigger, info.player, event.triggername, info.skill)) return false; + if (!event.noDirectUse(info)) return false; + if (current.skill != info.skill) return false; + if (current.player != info.player) return false; + return lib.skill.global.includes(info.skill) || current.player.hasSkill(info.skill, true); + }); + if (event.choice.length < 2) event.goto(5); + "step 3" + const next = event.choice[0].player.chooseControl(event.choice.map(i => i.skill)); + next.set("prompt", "选择下一个触发的技能"); + next.set("forceDie", true); + next.set("arrangeSkill", true); + next.set("includeOut", true); + "step 4" + if (result.control) event.num = event.doing.todoList.findIndex(info => info.skill == result.control && info.player == event.choice[0].player); + "step 5" + const info = event.doing.todoList[event.num]; + if (!info) return; + event.doing.doneList.push(info); + event.doing.todoList.splice(event.num, 1); + game.createTrigger(event.triggername, info.skill, info.player, trigger); + event.goto(1); + }, + createTrigger: function () { + "step 0" + // console.log("triggering: " + player.name+ " \"s skill: " + event.skill+" in " + event.triggername) + if (game.expandSkills(player.getSkills().concat(lib.skill.global)).includes(event.skill)) return; + var info = get.info(event.skill); + let hidden = player.hiddenSkills.slice(0); + let invisible = player.invisibleSkills.slice(0); + game.expandSkills(hidden); + game.expandSkills(invisible); + if (hidden.includes(event.skill)) { + if (!info.silent && player.hasSkillTag("nomingzhi", false, null, true)) event.finish(); + else if (!info.direct) event.trigger("triggerHidden"); + else event.skillHidden = true; + } + else if (invisible.includes(event.skill)) event.trigger("triggerInvisible"); + else if (Object.keys(player.additionalSkills).every(i => { + if (i.startsWith("hidden:")) return true; + return !game.expandSkills(player.additionalSkills[i]).includes(event.skill); + })) event.finish(); + "step 1" + if (event.cancelled) return event.finish(); + var info = get.info(event.skill); + if (event.revealed || info.forced) return; + const checkFrequent = function (info) { + if (player.hasSkillTag("nofrequent", false, event.skill)) return false; + if (typeof info.frequent == "boolean") return info.frequent; + if (typeof info.frequent == "function") return info.frequent(trigger, player); + if (info.frequent == "check" && typeof info.check == "function") return info.check(trigger, player); + return false; + } + if (info.direct) { + if (player.isUnderControl()) game.swapPlayerAuto(player); + if (player.isOnline()) void 0; + event._result = { bool: true }; + event._direct = true; + } + else { + if (checkFrequent(info)) event.frequentSkill = true; + var str; + var check = info.check; + if (info.prompt) str = info.prompt; + else if (typeof info.logTarget == "string") str = get.prompt(event.skill, trigger[info.logTarget], player); + else if (typeof info.logTarget == "function") { + const logTarget = info.logTarget(trigger, player); + if (get.itemtype(logTarget).startsWith("player")) str = get.prompt(event.skill, logTarget, player); + } + else str = get.prompt(event.skill, null, player); + if (typeof str == "function") str = str(trigger, player); + + var next = player.chooseBool(str); + if (event.frequentSkill) next.set("frequentSkill", event.skill); + next.set("forceDie", true); + next.set("includeOut", true); + next.ai = () => !check || check(trigger, player); + + if (typeof info.prompt2 == "function") next.set("prompt2", info.prompt2(trigger, player)); + else if (typeof info.prompt2 == "string") next.set("prompt2", info.prompt2); + else if (info.prompt2 != false) { + if (lib.dynamicTranslate[event.skill]) next.set("prompt2", lib.dynamicTranslate[event.skill](player, event.skill)); + else if (lib.translate[event.skill + "_info"]) next.set("prompt2", lib.translate[event.skill + "_info"]); + } + + if (trigger.skillwarn) { + if (next.prompt2) next.set("prompt2", `${trigger.skillwarn}。${next.prompt2}`); + else next.set("prompt2", trigger.skillwarn); + } + } + "step 2" + var info = get.info(event.skill); + if (!result || !result.bool) return; + var autodelay = info.autodelay; + if (typeof autodelay == "function") autodelay = autodelay(trigger, player); + if (autodelay && (info.forced || !event.isMine())) { + if (typeof autodelay == "number") game.delayx(autodelay); + else game.delayx(); + } + "step 3" + var info = get.info(event.skill); + if (result && result.bool == false) { + if (info.oncancel) info.oncancel(trigger, player); + return event.finish(); + } + if (info.popup != false && !info.direct) { + if (info.popup) { + player.popup(info.popup); + game.log(player, "发动了", "【" + get.skillTranslation(event.skill, player) + "】"); + } + else if (!info.logTarget || info.logLine === false) player.logSkill(event.skill, false, info.line); + else if (typeof info.logTarget == "string") player.logSkill(event.skill, trigger[info.logTarget], info.line); + else if (typeof info.logTarget == "function") player.logSkill(event.skill, info.logTarget(trigger, player), info.line); + } + var next = game.createEvent(event.skill); + if (typeof info.usable == "number") { + player.addSkill("counttrigger"); + if (!player.storage.counttrigger) player.storage.counttrigger = {}; + if (!player.storage.counttrigger[event.skill]) player.storage.counttrigger[event.skill] = 1; + else player.storage.counttrigger[event.skill]++; + } + next.player = player; + next._trigger = trigger; + next.triggername = event.triggername; + next.setContent(info.content); + next.skillHidden = event.skillHidden; + if (info.forceDie) next.forceDie = true; + if (info.forceOut) next.includeOut = true; + "step 4" + if (!player._hookTrigger) return; + if (player._hookTrigger.some(i => { + const info = lib.skill[i].hookTrigger; + return info && info.after && info.after(event, player, event.triggername); + })) event.trigger("triggerAfter"); + }, + playVideoContent: function () { + "step 0" + game.delay(0, 500); + "step 1" + if (!game.chess) { + ui.control.innerHTML = ""; + var nodes = []; + for (var i = 0; i < ui.arena.childNodes.length; i++) { + nodes.push(ui.arena.childNodes[i]); + } + for (var i = 0; i < nodes.length; i++) { + if (nodes[i] == ui.canvas) continue; + if (nodes[i] == ui.control) continue; + if (nodes[i] == ui.mebg) continue; + if (nodes[i] == ui.me) continue; + if (nodes[i] == ui.roundmenu) continue; + nodes[i].remove(); + } + ui.sidebar.innerHTML = ""; + ui.cardPile.innerHTML = ""; + ui.discardPile.innerHTML = ""; + ui.special.innerHTML = ""; + ui.ordering.innerHTML = ""; + } + ui.system.firstChild.innerHTML = ""; + ui.system.lastChild.innerHTML = ""; + ui.system.firstChild.appendChild(ui.config2); + if (ui.updateVideoMenu) { + ui.updateVideoMenu(); + } + _status.videoDuration = 1; + ui.create.system("返回", function () { + var mode = localStorage.getItem(lib.configprefix + "playbackmode"); + if (mode) { + game.saveConfig("mode", mode); + } + game.reload(); + }); + ui.create.system("重播", function () { + _status.replayvideo = true; + game.playVideo(_status.playback, lib.config.mode); + }); + ui.create.system("暂停", ui.click.pause, true).id = "pausebutton"; + var slow = ui.create.system("减速", function () { + _status.videoDuration *= 1.5; + updateDuration(); + }, true); + var fast = ui.create.system("加速", function () { + _status.videoDuration /= 1.5; + updateDuration(); + }, true); + var updateDuration = function () { + if (_status.videoDuration > 1) { + slow.classList.add("glow"); + } + else { + slow.classList.remove("glow"); + } + if (_status.videoDuration < 1) { + fast.classList.add("glow"); + } + else { + fast.classList.remove("glow"); + } + } + ui.system.style.display = ""; + ui.refresh(ui.system); + ui.system.show(); + ui.window.show(); + if (lib.config.mode != "versus" && lib.config.mode != "boss") { + ui.arena.style.display = ""; + ui.refresh(ui.arena); + ui.arena.show(); + } + if (!game.chess) { + game.playerMap = {}; + } + game.finishCards(); + "step 2" + if (event.video.length) { + var content = event.video.shift(); + // console.log(content); + if (content.type == "delay") { + game.delay(content.content); + } + else if (content.type == "play") { + window.play = {}; + if (!event.playtoload) { + event.playtoload = 1; + } + else { + event.playtoload++; + } + var script = lib.init.js(lib.assetURL + "play", content.name); + script.addEventListener("load", function () { + var play = window.play[content.name] + if (play && play.video) { + play.video(content.init); + } + event.playtoload--; + if (event.playtoload == 0) { + delete window.play; + } + }); + } + else if (typeof content.player == "string" && game.playerMap[content.player] && + game.playerMap[content.player].classList && + !game.playerMap[content.player].classList.contains("obstacle")) { + game.videoContent[content.type](game.playerMap[content.player], content.content); + } + else { + game.videoContent[content.type](content.content); + } + if (event.video.length) { + game.delay(0, _status.videoDuration * Math.min(2000, event.video[0].delay)); + } + event.redo(); + } + else { + _status.over = true; + ui.system.lastChild.hide(); + setTimeout(function () { + ui.system.lastChild.innerHTML = ""; + }, 500); + } + }, + waitForPlayer: function () { + "step 0" + ui.auto.hide(); + ui.pause.hide(); + + game.createServer(); + if (!lib.translate.zhu) { + lib.translate.zhu = "主"; + } + if (event.func) { + event.func(); + } + if (!lib.configOL.number) { + lib.configOL.number = parseInt(lib.configOL.player_number); + } + if (game.onlineroom) { + game.send("server", "config", lib.configOL); + } + + ui.create.connectPlayers(game.ip); + if (!window.isNonameServer) { + var me = game.connectPlayers[0]; + me.setIdentity("zhu"); + me.initOL(get.connectNickname(), lib.config.connect_avatar); + me.playerid = "1"; + game.onlinezhu = "1"; + } + _status.waitingForPlayer = true; + if (window.isNonameServer) { + document.querySelector("#server_status").innerHTML = "等待中"; + } + game.pause(); + "step 1" + _status.waitingForPlayer = false; + lib.configOL.gameStarted = true; + if (window.isNonameServer) { + document.querySelector("#server_status").innerHTML = "游戏中"; + } + if (game.onlineroom) { + game.send("server", "config", lib.configOL); + } + for (var i = 0; i < game.connectPlayers.length; i++) { + game.connectPlayers[i].delete(); + } + delete game.connectPlayers; + if (ui.roomInfo) { + ui.roomInfo.remove(); + delete ui.roomInfo; + } + if (ui.exitroom) { + ui.exitroom.remove(); + delete ui.exitroom; + } + game.broadcast("gameStart"); + game.delay(2); + ui.auto.show(); + ui.pause.show(); + if (lib.config.show_cardpile) { + ui.cardPileButton.style.display = ""; + } + }, + replaceHandcards: function () { + "step 0" + if (event.players.contains(game.me)) { + game.me.chooseBool("是否置换手牌?"); + } + else { + event.finish(); + } + "step 1" + if (result && result.bool) { + var hs = game.me.getCards("h") + for (var i = 0; i < hs.length; i++) { + hs[i].discard(false); + } + var cards = get.cards(hs.length); + game.me._start_cards = cards; + game.me.directgain(cards); + } + }, + replaceHandcardsOL: function () { + "step 0" + var send = function () { + game.me.chooseBool("是否置换手牌?"); + game.resume(); + }; + var sendback = function (result, player) { + if (result && result.bool) { + var hs = player.getCards("h") + game.broadcastAll(function (player, hs) { + game.addVideo("lose", player, [get.cardsInfo(hs), [], [], []]); + for (var i = 0; i < hs.length; i++) { + hs[i].discard(false); + } + }, player, hs); + var cards = get.cards(hs.length); + player.directgain(cards); + player._start_cards = cards; + } + }; + for (var i = 0; i < event.players.length; i++) { + if (event.players[i].isOnline()) { + event.withol = true; + event.players[i].send(send); + event.players[i].wait(sendback); + } + else if (event.players[i] == game.me) { + event.withme = true; + game.me.chooseBool("是否置换手牌?"); + game.me.wait(sendback); + } + } + "step 1" + if (event.withme) { + game.me.unwait(result); + } + "step 2" + if (event.withol && !event.resultOL) { + game.pause(); + } + }, + phase: function () { + "step 0" + //初始化阶段列表 + if (!event.phaseList) { + event.phaseList = ["phaseZhunbei", "phaseJudge", "phaseDraw", "phaseUse", "phaseDiscard", "phaseJieshu"]; + } + if (typeof event.num != "number") { + event.num = 0; + } + //规则集中的“回合开始后①”,更新游戏轮数,触发“一轮游戏开始时” + var isRound = false; + if (!event.skill) { + isRound = _status.roundSkipped; + if (_status.isRoundFilter) { + isRound = _status.isRoundFilter(event, player); + } + else if (_status.seatNumSettled) { + var seatNum = player.getSeatNum(); + if (seatNum != 0) { + if (get.itemtype(_status.lastPhasedPlayer) != "player" || seatNum < _status.lastPhasedPlayer.getSeatNum()) isRound = true; + _status.lastPhasedPlayer = player; + } + } + else if (player == _status.roundStart) isRound = true; + if (isRound) { + delete _status.roundSkipped; + game.roundNumber++; + event._roundStart = true; + game.updateRoundNumber(); + for (var i = 0; i < game.players.length; i++) { + if (game.players[i].isOut() && game.players[i].outCount > 0) { + game.players[i].outCount--; + if (game.players[i].outCount == 0 && !game.players[i].outSkills) { + game.players[i].in(); + } + } + } + event.trigger("roundStart"); + } + } + _status.globalHistory.push({ + cardMove: [], + custom: [], + useCard: [], + changeHp: [], + everything: [], + }); + var players = game.players.slice(0).concat(game.dead); + for (var i = 0; i < players.length; i++) { + var current = players[i]; + current.actionHistory.push({ useCard: [], respond: [], skipped: [], lose: [], gain: [], sourceDamage: [], damage: [], custom: [], useSkill: [] }); + current.stat.push({ card: {}, skill: {} }); + if (isRound) { + current.getHistory().isRound = true; + current.getStat().isRound = true; + } + } + if (isRound) { + game.getGlobalHistory().isRound = true; + } + "step 1" + //规则集中的“回合开始后②(1v1武将登场专用)” + event.trigger("phaseBeforeStart"); + "step 2" + //规则集中的“回合开始后③(处理“游戏开始时”的时机)” + event.trigger("phaseBefore"); + "step 3" + //规则集中的“回合开始后④(卑弥呼〖纵傀〗的时机)” + event.trigger("phaseBeforeEnd"); + "step 4" + //规则集中的“回合开始后⑤”,进行翻面检测 + if (player.isTurnedOver() && !event._noTurnOver) { + event.cancel(); + player.turnOver(); + player.phaseSkipped = true; + } + else { + player.phaseSkipped = false; + player.getHistory().isMe = true; + player.getStat().isMe = true; + } + "step 5" + //规则集中的“回合开始后⑥”,更新“当前回合角色” + while (ui.dialogs.length) { + ui.dialogs[0].close(); + } + game.phaseNumber++; + player.phaseNumber++; + game.broadcastAll(function (player, num, popup) { + if (lib.config.glow_phase) { + player.classList.add("glow_phase"); + } + player.phaseNumber = num; + _status.currentPhase = player; + if (popup && lib.config.show_phase_prompt) player.popup("回合开始", null, false); + }, player, player.phaseNumber, !player.noPhaseDelay); + _status.currentPhase = player; + _status.discarded = []; + game.syncState(); + game.addVideo("phaseChange", player); + if (game.phaseNumber == 1) { + delete player._start_cards; + if (lib.configOL.observe) { + lib.configOL.observeReady = true; + game.send("server", "config", lib.configOL); + } + } + game.log(); + game.log(player, "的回合开始"); + player._noVibrate = true; + if (get.config("identity_mode") != "zhong" && get.config("identity_mode") != "purple" && !_status.connectMode) { + var num; + switch (get.config("auto_identity")) { + case "one": num = 1; break; + case "two": num = 2; break; + case "three": num = 3; break; + case "always": num = -1; break; + default: num = 0; break; + } + if (num && !_status.identityShown && game.phaseNumber > game.players.length * num && game.showIdentity) { + if (!_status.video) player.popup("显示身份"); + _status.identityShown = true; + game.showIdentity(false); + } + } + player.ai.tempIgnore = []; + if (ui.land && ui.land.player == player) { + game.addVideo("destroyLand"); + ui.land.destroy(); + } + "step 6" + //规则集中的“回合开始后⑦”,国战武将明置武将牌 + event.trigger("phaseBeginStart"); + "step 7" + //规则集中的“回合开始后⑨”,进行当先,化身等操作 + //没有⑧ 因为⑧用不到 + event.trigger("phaseBegin"); + //阶段部分 + "step 8" + if (num < event.phaseList.length) { + //规则集中没有的新时机 可以用来插入额外阶段啥的 + if (player.isIn()) event.trigger("phaseChange") + } + else event.goto(11); + "step 9" + if (player.isIn() && num < event.phaseList.length) { + var phase = event.phaseList[num].split("|"); + event.currentPhase = phase[0]; + var next = player[event.currentPhase](); + next.phaseIndex = num; + if (phase.length > 1) { + next._extraPhaseReason = phase[1]; + } + if (event.currentPhase == "phaseDraw" || event.currentPhase == "phaseDiscard") { + if (!player.noPhaseDelay) { + if (player == game.me) { + game.delay(); + } + else { + game.delayx(); + } + } + } + } + "step 10" + if (event.currentPhase == "phaseUse") { + game.broadcastAll(function () { + if (ui.tempnowuxie) { + ui.tempnowuxie.close(); + delete ui.tempnowuxie; + } + }); + delete player._noSkill; + } + event.num++; + "step 11" + if (event.num < event.phaseList.length) { + event.goto(8); + } + else if (!event._phaseEndTriggered) { + event._phaseEndTriggered = true; + event.trigger("phaseEnd"); + event.redo(); + } + "step 12" + event.trigger("phaseAfter"); + "step 13" + //删除当前回合角色 此时处于“不属于任何角色的回合”的阶段 + game.broadcastAll(function (player) { + player.classList.remove("glow_phase"); + delete _status.currentPhase; + }, player); + }, + /** + * @deprecated + */ + phase_old: function () { + "step 0" + player.phaseZhunbei(); + "step 1" + player.phaseJudge(); + "step 2" + player.phaseDraw(); + if (!player.noPhaseDelay) { + if (player == game.me) { + game.delay(); + } + else { + game.delayx(); + } + } + "step 3" + player.phaseUse(); + "step 4" + game.broadcastAll(function () { + if (ui.tempnowuxie) { + ui.tempnowuxie.close(); + delete ui.tempnowuxie; + } + }); + player.phaseDiscard() + if (!player.noPhaseDelay) game.delayx(); + //delete player.using; + delete player._noSkill; + "step 5" + player.phaseJieshu(); + }, + phaseZhunbei: function () { + event.trigger(event.name); + game.log(player, "进入了准备阶段"); + }, + phaseJudge: function () { + "step 0" + game.log(player, "进入了判定阶段"); + event.cards = player.getCards("j"); + if (!event.cards.length) event.finish(); + "step 1" + if (cards.length && player.getCards("j").contains(cards[0])) { + event.card = cards.shift(); + if (event.card.classList.contains("removing")) { + event.card.remove(); + delete event.card; + event.redo(); + } + else if (event.card.classList.contains("feichu")) { + event.finish(); + return; + } + else { + player.lose(event.card, "visible", ui.ordering); + player.$phaseJudge(event.card); + event.cancelled = false; + event.trigger("phaseJudge"); + var name = event.card.viewAs || event.card.name; + player.popup(name, "thunder"); + if (!lib.card[name].effect) { + game.delay(); + event.redo(); + } + else if (!lib.card[name].judge) { + game.delay(); + event.nojudge = true; + } + } + } + else event.finish(); + "step 2" + if (!event.cancelled && !event.nojudge) player.judge(event.card).set("type", "phase"); + "step 3" + var name = event.card.viewAs || event.card.name; + if (event.excluded) { + delete event.excluded; + } + else if (event.cancelled && !event.direct) { + if (lib.card[name].cancel) { + var next = game.createEvent(name + "Cancel"); + next.setContent(lib.card[name].cancel); + next.cards = [event.card]; + if (!event.card.viewAs) next.card = get.autoViewAs(event.card); + else next.card = get.autoViewAs({ name: name }, next.cards); + next.player = player; + } + } + else { + var next = game.createEvent(name); + next.setContent(lib.card[name].effect); + next._result = result; + next.cards = [event.card]; + if (!event.card.viewAs) next.card = get.autoViewAs(event.card); + else next.card = get.autoViewAs({ name: name }, next.cards); + next.player = player; + } + ui.clear(); + event.goto(1); + }, + phaseDraw: function () { + "step 0" + game.log(player, "进入了摸牌阶段"); + event.trigger("phaseDrawBegin1"); + "step 1" + event.trigger("phaseDrawBegin2"); + "step 2" + if (game.modPhaseDraw) { + game.modPhaseDraw(player, event.num); + } + else { + if (event.num > 0) { + var num = event.num; + if (event.attachDraw) { + for (var i = 0; i < event.attachDraw.length; i++) { + ui.cardPile.insertBefore(event.attachDraw[i], ui.cardPile.firstChild); + } + num += event.attachDraw.length; + } + var next = player.draw(num); + if (event.attachDraw) { + next.minnum = event.attachDraw.length; + } + } + } + "step 3" + if (Array.isArray(result)) { + event.cards = result; + } + }, + phaseUse: function () { + "step 0" + if (!event.logged) { + game.log(player, "进入了出牌阶段"); + event.logged = true; + } + var next = player.chooseToUse(); + if (!lib.config.show_phaseuse_prompt) { + next.set("prompt", false); + } + next.set("type", "phase"); + "step 1" + if (result.bool && !event.skipped) { + event.goto(0); + } + game.broadcastAll(function () { + if (ui.tempnowuxie) { + ui.tempnowuxie.close(); + delete ui.tempnowuxie; + } + }); + "step 2" + var stat = player.getStat(); + for (var i in stat.skill) { + var bool = false; + var info = lib.skill[i]; + if (!info) continue; + if (info.enable != undefined) { + if (typeof info.enable == "string" && info.enable == "phaseUse") bool = true; + else if (typeof info.enable == "object" && info.enable.contains("phaseUse")) bool = true; + } + if (bool) stat.skill[i] = 0; + } + for (var i in stat.card) { + var bool = false; + var info = lib.card[i]; + if (!info) continue; + if (info.updateUsable == "phaseUse") stat.card[i] = 0; + } + }, + phaseDiscard: function () { + "step 0" + game.log(player, "进入了弃牌阶段"); + event.num = player.needsToDiscard(); + if (event.num <= 0) event.finish(); + else { + game.broadcastAll(function (player) { + if (lib.config.show_phase_prompt) { + player.popup("弃牌阶段", null, false); + } + }, player); + } + event.trigger("phaseDiscard"); + "step 1" + player.chooseToDiscard(num, true) + .set("useCache", true); + "step 2" + event.cards = result.cards; + }, + phaseJieshu: function () { + event.trigger(event.name); + game.log(player, "进入了结束阶段"); + }, + chooseToUse: function () { + "step 0" + if (event.responded) return; + if (game.modeSwapPlayer && !_status.auto && player.isUnderControl() && !lib.filter.wuxieSwap(event)) { + game.modeSwapPlayer(player); + } + var skills = player.getSkills("invisible").concat(lib.skill.global); + game.expandSkills(skills); + for (var i = 0; i < skills.length; i++) { + var info = lib.skill[skills[i]]; + if (info && info.onChooseToUse) { + info.onChooseToUse(event); + } + } + if (_status.noclearcountdown !== "direct") _status.noclearcountdown = true; + if (event.type == "phase") { + if (event.isMine()) { + event.endButton = ui.create.control("结束回合", "stayleft", function () { + var evt = _status.event; + if (evt.name != "chooseToUse" || evt.type != "phase") return; + if (evt.skill) { + ui.click.cancel(); + } + ui.click.cancel(); + }); + event.fakeforce = true; + } + else { + if (event.endButton) { + event.endButton.close(); + delete event.endButton; + } + event.fakeforce = false; + } + } + if (event.player.isUnderControl() && !_status.auto) { + event.result = { + bool: false + } + return; + } + else if (event.isMine()) { + if (event.hsskill && !event.forced && _status.prehidden_skills.contains(event.hsskill)) { + ui.click.cancel(); + return; + } + if (event.type == "wuxie") { + if (ui.tempnowuxie) { + var triggerevent = event.getTrigger(); + if (triggerevent && triggerevent.targets && triggerevent.num == triggerevent.targets.length - 1) { + ui.tempnowuxie.close(); + } + } + if (lib.filter.wuxieSwap(event)) { + event.result = { + bool: false + } + return; + } + } + var ok = game.check(); + if (!ok || !lib.config.auto_confirm) { + game.pause(); + if (lib.config.enable_vibrate && player._noVibrate) { + delete player._noVibrate; + game.vibrate(); + } + if (typeof event.prompt == "string") { + if (event.openskilldialog) { + event.skillDialog = ui.create.dialog(event.openskilldialog); + delete event.openskilldialog; + event.dialog = event.prompt; + } + else { + event.dialog = ui.create.dialog(event.prompt); + if (event.prompt2) { + event.dialog.addText(event.prompt2); + } + } + } + else if (typeof event.prompt == "function") { + event.dialog = ui.create.dialog(event.prompt(event)); + } + else if (event.prompt == undefined) { + var str; + if (typeof event.filterCard == "object") { + var filter = event.filterCard; + str = "请使用" + get.cnNumber(event.selectCard[0]) + "张" + if (filter.name) { + str += get.translation(filter.name); + } + else { + str += "牌"; + } + } + else { + str = "请选择要使用的牌"; + } + if (event.openskilldialog) { + event.skillDialog = ui.create.dialog(event.openskilldialog); + delete event.openskilldialog; + event.dialog = str; + } + else if (typeof event.skillDialog != "string") { + event.dialog = ui.create.dialog(str); + } + else { + event.dialog = str; + } + } + } + } + else if (event.isOnline()) { + event.send(); + } + else { + event.result = "ai"; + } + "step 1" + if (event.result == "ai") { + var ok = game.check(); + if (ok) { + ui.click.ok(); + } + else if (ai.basic.chooseCard(event.ai1) || forced) { + if ((ai.basic.chooseTarget(event.ai2) || forced) && (!event.filterOk || event.filterOk())) { + ui.click.ok(); + event._aiexcludeclear = true; + } + else { + if (!event.norestore) { + if (event.skill) { + var skill = event.skill; + ui.click.cancel(); + event._aiexclude.add(skill); + var info = get.info(skill); + if (info.sourceSkill) { + event._aiexclude.add(info.sourceSkill); + } + } + else { + get.card(true).aiexclude(); + game.uncheck(); + } + event.redo(); + game.resume(); + } + else { + ui.click.cancel(); + } + } + } + else if (event.skill && !event.norestore) { + var skill = event.skill; + ui.click.cancel(); + event._aiexclude.add(skill); + var info = get.info(skill); + if (info.sourceSkill) { + event._aiexclude.add(info.sourceSkill); + } + event.redo(); + game.resume(); + } + else { + ui.click.cancel(); + } + if (event.aidelay && event.result && event.result.bool) { + game.delayx(); + } + } + "step 2" + if (event.endButton) { + event.endButton.close(); + delete event.endButton; + } + event.resume(); + if (event.result) { + if (event.result._sendskill) { + lib.skill[event.result._sendskill[0]] = event.result._sendskill[1]; + } + if (event.result.skill) { + var info = get.info(event.result.skill); + if (info && info.chooseButton) { + if (event.dialog && typeof event.dialog == "object") event.dialog.close(); + var dialog = info.chooseButton.dialog(event, player); + if (info.chooseButton.chooseControl) { + var next = player.chooseControl(info.chooseButton.chooseControl(event, player)); + if (dialog.direct) next.direct = true; + if (dialog.forceDirect) next.forceDirect = true; + next.dialog = dialog; + next.set("ai", info.chooseButton.check || function () { return 0; }); + if (event.id) next._parent_id = event.id; + next.type = "chooseToUse_button"; + } + else { + var next = player.chooseButton(dialog); + if (dialog.direct) next.direct = true; + if (dialog.forceDirect) next.forceDirect = true; + next.set("ai", info.chooseButton.check || function () { return 1; }); + next.set("filterButton", info.chooseButton.filter || function () { return true; }); + next.set("selectButton", info.chooseButton.select || 1); + next.set("filterOk", info.chooseButton.filterOk || (() => true)); + if (event.id) next._parent_id = event.id; + next.type = "chooseToUse_button"; + } + event.buttoned = event.result.skill; + } + else if (info && info.precontent && !game.online && !event.nouse) { + var next = game.createEvent("pre_" + event.result.skill); + next.setContent(info.precontent); + next.set("result", event.result); + next.set("player", player); + } + } + } + "step 3" + if (event.buttoned) { + if (result.bool || result.control && result.control != "cancel2") { + var info = get.info(event.buttoned).chooseButton; + lib.skill[event.buttoned + "_backup"] = info.backup(info.chooseControl ? result : result.links, player); + lib.skill[event.buttoned + "_backup"].sourceSkill = event.buttoned; + if (game.online) { + event._sendskill = [event.buttoned + "_backup", lib.skill[event.buttoned + "_backup"]]; + } + else { + game.broadcast((skill, audio) => { + if (!lib.skill[skill]) lib.skill[skill] = {}; + lib.skill[skill].audio = audio; + }, event.buttoned + "_backup", lib.skill[event.buttoned + "_backup"].audio); + } + event.backup(event.buttoned + "_backup"); + if (info.prompt) { + event.openskilldialog = info.prompt(info.chooseControl ? result : result.links, player); + } + } + else { + ui.control.animate("nozoom", 100); + event._aiexclude.add(event.buttoned); + } + event.goto(0); + delete event.buttoned; + } + "step 4" + if (event._aiexcludeclear) { + delete event._aiexcludeclear; + event._aiexclude.length = 0; + } + delete _status.noclearcountdown; + if (event.skillDialog && get.objtype(event.skillDialog) == "div") { + event.skillDialog.close(); + } + if (event.result && event.result.bool && !game.online && !event.nouse) { + player.useResult(event.result, event); + } + else if (event._sendskill) { + event.result._sendskill = event._sendskill; + } + if ((!event.result || !event.result.bool || event.result._noHidingTimer) && (event.result.skill || event.logSkill)) { + var info = get.info(event.result.skill || event.logSkill); + if (info.direct && !info.clearTime) { + _status.noclearcountdown = "direct"; + } + } + if (event.dialog && typeof event.dialog == "object") event.dialog.close(); + if (!_status.noclearcountdown) { + game.stopCountChoose(); + } + "step 5" + if (event._result && event.result) { + event.result.result = event._result; + } + }, + chooseToRespond: function () { + "step 0" + if (event.responded) { + delete event.dialog; + return; + } + var skills = player.getSkills("invisible").concat(lib.skill.global); + game.expandSkills(skills); + for (var i = 0; i < skills.length; i++) { + var info = lib.skill[skills[i]]; + if (info && info.onChooseToRespond) { + info.onChooseToRespond(event); + } + } + if (_status.noclearcountdown !== "direct") _status.noclearcountdown = true; + if (!_status.connectMode && lib.config.skip_shan && event.autochoose && event.autochoose()) { + event.result = { bool: false }; + } + else { + if (game.modeSwapPlayer && !_status.auto && player.isUnderControl()) { + game.modeSwapPlayer(player); + } + if (event.isMine()) { + if (event.hsskill && !event.forced && _status.prehidden_skills.contains(event.hsskill)) { + ui.click.cancel(); + return; + } + var ok = game.check(); + if (!ok || !lib.config.auto_confirm) { + game.pause(); + if (event.openskilldialog) { + event.skillDialog = ui.create.dialog(event.openskilldialog); + delete event.openskilldialog; + event.dialog = event.prompt; + } + else { + if (event.prompt) event.dialog = ui.create.dialog(event.prompt); + if (event.prompt2) event.dialog.addText(event.prompt2); + } + } + } + else if (event.isOnline()) { + event.send(); + } + else { + event.result = "ai"; + } + } + "step 1" + if (event.result == "ai") { + var ok = game.check(); + if (ok) { + ui.click.ok(); + } + else if (ai.basic.chooseCard(event.ai1 || event.ai) || forced) { + if ((ai.basic.chooseTarget(event.ai2) || forced) && (!event.filterOk || event.filterOk())) { + ui.click.ok(); + event._aiexcludeclear = true; + } + else { + if (!event.norestore) { + if (event.skill) { + var skill = event.skill; + ui.click.cancel(); + event._aiexclude.add(skill); + var info = get.info(skill); + if (info.sourceSkill) { + event._aiexclude.add(info.sourceSkill); + } + } + else { + get.card(true).aiexclude(); + game.uncheck(); + } + event.redo(); + game.resume(); + } + else { + ui.click.cancel(); + } + } + } + else if (event.skill && !event.norestore) { + var skill = event.skill; + ui.click.cancel(); + event._aiexclude.add(skill); + var info = get.info(skill); + if (info.sourceSkill) { + event._aiexclude.add(info.sourceSkill); + } + event.redo(); + game.resume(); + } + else { + ui.click.cancel(); + } + if (event.aidelay && event.result && event.result.bool) { + game.delayx(); + } + } + "step 2" + event.resume(); + if (event.result) { + if (event.result._sendskill) { + lib.skill[event.result._sendskill[0]] = event.result._sendskill[1]; + } + if (event.result.skill) { + var info = get.info(event.result.skill); + if (info && info.chooseButton) { + if (event.dialog && typeof event.dialog == "object") event.dialog.close(); + var dialog = info.chooseButton.dialog(event, player); + if (info.chooseButton.chooseControl) { + var next = player.chooseControl(info.chooseButton.chooseControl(event, player)); + if (dialog.direct) next.direct = true; + if (dialog.forceDirect) next.forceDirect = true; + next.dialog = dialog; + next.set("ai", info.chooseButton.check || function () { return 0; }); + } + else { + var next = player.chooseButton(dialog); + if (dialog.direct) next.direct = true; + if (dialog.forceDirect) next.forceDirect = true; + next.set("ai", info.chooseButton.check || function () { return 1; }); + next.set("filterButton", info.chooseButton.filter || function () { return true; }); + next.set("selectButton", info.chooseButton.select || 1); + next.set("filterOk", info.chooseButton.filterOk || (() => true)); + } + event.buttoned = event.result.skill; + } + else if (info && info.precontent && !game.online) { + var next = game.createEvent("pre_" + event.result.skill); + next.setContent(info.precontent); + next.set("result", event.result); + next.set("player", player); + } + } + } + "step 3" + if (event.buttoned) { + if (result.bool || result.control && result.control != "cancel2") { + var info = get.info(event.buttoned).chooseButton; + lib.skill[event.buttoned + "_backup"] = info.backup(info.chooseControl ? result : result.links, player); + lib.skill[event.buttoned + "_backup"].sourceSkill = event.buttoned; + if (game.online) { + event._sendskill = [event.buttoned + "_backup", lib.skill[event.buttoned + "_backup"]]; + } + else { + game.broadcast((skill, audio) => { + if (!lib.skill[skill]) lib.skill[skill] = {}; + lib.skill[skill].audio = audio; + }, event.buttoned + "_backup", lib.skill[event.buttoned + "_backup"].audio); + } + event.backup(event.buttoned + "_backup"); + if (info.prompt) { + event.openskilldialog = info.prompt(info.chooseControl ? result : result.links, player); + } + } + else { + ui.control.animate("nozoom", 100); + event._aiexclude.add(event.buttoned); + } + event.goto(0); + delete event.buttoned; + } + "step 4" + delete _status.noclearcountdown; + if (event.skillDialog && get.objtype(event.skillDialog) == "div") { + event.skillDialog.close(); + } + if (event.result.bool && !game.online) { + if (event.result._sendskill) { + lib.skill[event.result._sendskill[0]] = event.result._sendskill[1]; + } + var info = get.info(event.result.skill); + if (event.onresult) { + event.onresult(event.result); + } + if ((!event.result || !event.result.bool || event.result._noHidingTimer) && (event.result.skill || event.logSkill)) { + if (info.direct && !info.clearTime) { + _status.noclearcountdown = "direct"; + } + } + if (event.logSkill) { + if (typeof event.logSkill == "string") { + player.logSkill(event.logSkill); + } + else if (Array.isArray(event.logSkill)) { + player.logSkill.apply(player, event.logSkill); + } + } + if (!event.result.card && event.result.skill) { + event.result.used = event.result.skill; + player.useSkill(event.result.skill, event.result.cards, event.result.targets); + } + else { + if (info && info.prerespond) { + info.prerespond(event.result, player); + } + var next = player.respond(event.result.cards, event.result.card, event.animate, event.result.skill, event.source); + if (event.result.noanimate) next.animate = false; + if (event.parent.card && event.parent.type == "card") { + next.set("respondTo", [event.parent.player, event.parent.card]); + } + if (event.noOrdering) next.noOrdering = true; + } + } + else if (event._sendskill) { + event.result._sendskill = event._sendskill; + } + if (event.dialog && event.dialog.close) event.dialog.close(); + if (!_status.noclearcountdown) { + game.stopCountChoose(); + } + }, + chooseToDiscard: function () { + "step 0" + if (event.autochoose()) { + event.result = { + bool: true, + autochoose: true, + cards: player.getCards(event.position), + rawcards: player.getCards(event.position), + } + for (var i = 0; i < event.result.cards.length; i++) { + if (!lib.filter.cardDiscardable(event.result.cards[i], player, event)) { + event.result.cards.splice(i--, 1); + } + } + } + else { + // &&!lib.filter.wuxieSwap(trigger) + if (game.modeSwapPlayer && !_status.auto && player.isUnderControl()) { + game.modeSwapPlayer(player); + } + event.rangecards = player.getCards(event.position); + for (var i = 0; i < event.rangecards.length; i++) { + if (lib.filter.cardDiscardable(event.rangecards[i], player, event)) { + event.rangecards.splice(i--, 1); + } + else { + event.rangecards[i].uncheck("chooseToDiscard"); + } + } + var range = get.select(event.selectCard); + if (event.isMine()) { + game.check(); + if (event.hsskill && !event.forced && _status.prehidden_skills.contains(event.hsskill)) { + ui.click.cancel(); + return; + } + game.pause(); + if (range[1] > 1 && typeof event.selectCard != "function") { + event.promptdiscard = ui.create.control("AI代选", function () { + ai.basic.chooseCard(event.ai); + if (_status.event.custom && _status.event.custom.add.card) { + _status.event.custom.add.card(); + } + for (var i = 0; i < ui.selected.cards.length; i++) { + ui.selected.cards[i].updateTransform(true); + } + }); + } + if (Array.isArray(event.dialog)) { + event.dialog = ui.create.dialog.apply(this, event.dialog); + event.dialog.open(); + event.dialog.classList.add("noselect"); + } + else if (event.prompt != false) { + var str; + if (typeof (event.prompt) == "string") str = event.prompt; + else { + str = "请弃置"; + if (range[0] == range[1]) str += get.cnNumber(range[0]); + else if (range[1] == Infinity) str += "至少" + get.cnNumber(range[0]); + else str += get.cnNumber(range[0]) + "至" + get.cnNumber(range[1]); + str += "张"; + if (event.position == "h" || event.position == undefined) str += "手"; + if (event.position == "e") str += "装备"; + str += "牌"; + } + event.dialog = ui.create.dialog(str); + if (event.prompt2) { + event.dialog.addText(event.prompt2, event.prompt2.length <= 20); + } + if (Array.isArray(event.selectCard)) { + event.promptbar = event.dialog.add("0/" + get.numStr(event.selectCard[1], "card")); + event.custom.add.card = function () { + _status.event.promptbar.innerHTML = + ui.selected.cards.length + "/" + get.numStr(_status.event.selectCard[1], "card"); + } + } + } + else if (get.itemtype(event.dialog) == "dialog") { + event.dialog.style.display = ""; + event.dialog.open(); + } + } + else if (event.isOnline()) { + event.send(); + } + else { + event.result = "ai"; + } + } + "step 1" + if (event.result == "ai") { + game.check(); + if ((ai.basic.chooseCard(event.ai) || forced) && (!event.filterOk || event.filterOk())) { + ui.click.ok(); + } + else if (event.skill) { + var skill = event.skill; + ui.click.cancel(); + event._aiexclude.add(skill); + event.redo(); + game.resume(); + } + else { + ui.click.cancel(); + } + } + if (event.rangecards) { + for (var i = 0; i < event.rangecards.length; i++) { + event.rangecards[i].recheck("chooseToDiscard"); + } + } + "step 2" + event.resume(); + if (event.promptdiscard) { + event.promptdiscard.close(); + } + "step 3" + if (event.result.bool && event.result.cards && event.result.cards.length && + !game.online && event.autodelay && !event.isMine()) { + if (typeof event.autodelay == "number") { + game.delayx(event.autodelay); + } + else { + game.delayx(); + } + } + "step 4" + if (event.logSkill && event.result.bool && !game.online) { + if (typeof event.logSkill == "string") { + player.logSkill(event.logSkill); + } + else if (Array.isArray(event.logSkill)) { + player.logSkill.apply(player, event.logSkill); + } + } + if (!game.online) { + if (typeof event.delay == "boolean") { + event.done = player.discard(event.result.cards).set("delay", event.delay); + } + else { + event.done = player.discard(event.result.cards); + } + event.done.discarder = player; + } + if (event.dialog && event.dialog.close) event.dialog.close(); + }, + gaincardMultiple: function () { + "step 0" + event.type = "gain"; + if (event.animate == "give" || event.animate == "gain2") event.visible = true; + if (player && cards) { + event._lose = true; + player.lose(cards, ui.special).set("type", "gain").set("forceDie", true).set("getlx", false); + } + "step 1" + switch (event.animate) { + case "draw": + game.delay(0, get.delayx(500, 500)); + for (var i of event.gain_list) { + if (get.itemtype(i[1]) == "card") i[1] = [i[1]]; + if (event._lose) { + i[1] = i[1].filter(card => { + return !cards.contains(card) || !player.getCards("hejsx").contains(card); + }) + } + if (i[1].length > 0) i[0].$draw(i[1].length); + } + break; + case "gain": + game.delay(0, get.delayx(700, 700)); + for (var i of event.gain_list) { + if (get.itemtype(i[1]) == "card") i[1] = [i[1]]; + if (event._lose) { + i[1] = i[1].filter(card => { + return !cards.contains(card) || !player.getCards("hejsx").contains(card); + }) + } + if (i[1].length > 0) i[0].$gain(i[1].length); + } + break; + case "gain2": case "draw2": + game.delay(0, get.delayx(500, 500)); + for (var i of event.gain_list) { + if (get.itemtype(i[1]) == "card") i[1] = [i[1]]; + if (event._lose) { + i[1] = i[1].filter(card => { + return !cards.contains(card) || !player.getCards("hejsx").contains(card); + }) + } + if (i[1].length > 0) i[0].$gain2(i[1]); + } + break; + case "give": case "giveAuto": + if (!player) break; + var evt = event.getl(player); + game.delay(0, get.delayx(500, 500)); + for (var i of event.gain_list) { + if (get.itemtype(i[1]) == "card") i[1] = [i[1]]; + if (event._lose) { + i[1] = i[1].filter(card => { + return !cards.contains(card) || !player.getCards("hejsx").contains(card); + }) + } + var shown = i[1].slice(0), hidden = []; + if (event.animate == "giveAuto") { + for (var card of i[1]) { + if (evt.hs.contains(card)) { + shown.remove(card); + hidden.push(card); + } + } + } + if (shown.length > 0) player.$give(shown, i[0]); + if (hidden.length > 0) player.$giveAuto(hidden, i[0]); + } + break; + default: + event.finish(); + } + for (var i of event.gain_list) { + if (i[1].length > 0) { + var next = i[0].gain(i[1]); + next.getlx = false; + if (event.visible) next.visible = true; + if (event.giver) next.giver = event.giver; + if (event.gaintag) next.gaintag.addArray(event.gaintag); + } + } + "step 2" + game.delayx(); + }, + discardMultiple: function () { + "step 0" + event.type = "discard"; + event.visible = true; + if (!event.position) event.position = ui.discardPile; + var cards = []; + event.cards = cards; + for (var i = 0; i < event.lose_list.length; i++) { + var next = event.lose_list[i][0].lose(event.lose_list[i][1], event.position); + game.log(event.lose_list[i][0], "弃置了", event.lose_list[i][1]); + next.type = "discard"; + next.animate = false; + next.delay = false; + cards.addArray(event.lose_list[i][1]); + next.getlx = false; + } + var evt = event; + if (evt.animate != false) { + evt.discardid = lib.status.videoId++; + game.broadcastAll(function (list, id, cards) { + for (var i of list) { + for (var j of i[1]) { + j.classList.remove("glow"); + j.classList.remove("glows"); + } + i[0].$throw(i[1], null, "nobroadcast"); + } + var cardnodes = []; + cardnodes._discardtime = get.time(); + for (var ix of list) { + var card = ix[1]; + for (var i = 0; i < cards.length; i++) { + if (cards[i].clone) { + cardnodes.push(cards[i].clone); + } + } + } + ui.todiscard[id] = cardnodes; + }, event.lose_list, evt.discardid, cards); + if (lib.config.sync_speed && cards[0] && cards[0].clone) { + if (evt.delay != false) { + var waitingForTransition = get.time(); + evt.waitingForTransition = waitingForTransition; + cards[0].clone.listenTransition(function () { + if (_status.waitingForTransition == waitingForTransition && _status.paused) { + game.resume(); + } + delete evt.waitingForTransition; + }); + } + else if (evt.getParent().discardTransition) { + delete evt.getParent().discardTransition; + var waitingForTransition = get.time(); + evt.getParent().waitingForTransition = waitingForTransition; + cards[0].clone.listenTransition(function () { + if (_status.waitingForTransition == waitingForTransition && _status.paused) { + game.resume(); + } + delete evt.getParent().waitingForTransition; + }); + } + } + } + "step 1" + if (event.delay != false) { + if (event.waitingForTransition) { + _status.waitingForTransition = event.waitingForTransition; + game.pause(); + } + else { + game.delayx(); + } + } + }, + chooseToCompareLose: function () { + for (var i = 0; i < event.lose_list.length; i++) { + var next = event.lose_list[i][0].lose(event.lose_list[i][1], ui.ordering); + next.relatedEvent = event.getParent(); + next.getlx = false; + } + }, + chooseToCompareMeanwhile: function () { + "step 0" + if (player.countCards("h") == 0) { + event.result = { cancelled: true, bool: false } + event.finish(); + return; + } + for (var i = 0; i < targets.length; i++) { + if (targets[i].countCards("h") == 0) { + event.result = { cancelled: true, bool: false } + event.finish(); + return; + } + } + if (!event.multitarget) { + targets.sort(lib.sort.seat); + } + game.log(player, "对", targets, "发起了共同拼点"); + event.compareMeanwhile = true; + "step 1" + event._result = []; + event.list = targets.filter(function (current) { + return !event.fixedResult || !event.fixedResult[current.playerid]; + }); + if (event.list.length || !event.fixedResult || !event.fixedResult[player.playerid]) { + if (!event.fixedResult || !event.fixedResult[player.playerid]) event.list.unshift(player); + player.chooseCardOL(event.list, "请选择拼点牌", true).set("type", "compare").set("ai", event.ai).set("source", player).aiCard = function (target) { + var hs = target.getCards("h"); + var event = _status.event; + event.player = target; + hs.sort(function (a, b) { + return event.ai(b) - event.ai(a); + }); + delete event.player; + return { bool: true, cards: [hs[0]] }; + }; + } + "step 2" + var cards = []; + var lose_list = []; + if (event.fixedResult && event.fixedResult[player.playerid]) { + event.list.unshift(player); + result.unshift({ bool: true, cards: [event.fixedResult[player.playerid]] }); + lose_list.push([player, [event.fixedResult[player.playerid]]]); + } + else { + if (result[0].skill && lib.skill[result[0].skill] && lib.skill[result[0].skill].onCompare) { + player.logSkill(result[0].skill); + result[0].cards = lib.skill[result[0].skill].onCompare(player) + } + else lose_list.push([player, result[0].cards]); + } + for (var j = 0; j < targets.length; j++) { + if (event.list.contains(targets[j])) { + var i = event.list.indexOf(targets[j]); + if (result[i].skill && lib.skill[result[i].skill] && lib.skill[result[i].skill].onCompare) { + event.list[i].logSkill(result[i].skill); + result[i].cards = lib.skill[result[i].skill].onCompare(event.list[i]); + } + else lose_list.push([targets[j], result[i].cards]); + cards.push(result[i].cards[0]); + } + else if (event.fixedResult && event.fixedResult[targets[j].playerid]) { + cards.push(event.fixedResult[targets[j].playerid]); + lose_list.push([targets[j], [event.fixedResult[targets[j].playerid]]]); + } + } + if (lose_list.length) { + game.loseAsync({ + lose_list: lose_list, + }).setContent("chooseToCompareLose"); + } + event.lose_list = lose_list; + event.getNum = function (card) { + for (var i of event.lose_list) { + if (i[1].contains && i[1].contains(card)) return get.number(card, i[0]); + } + return get.number(card, false); + } + event.cardlist = cards; + event.cards = cards; + event.card1 = result[0].cards[0]; + event.num1 = event.getNum(event.card1); + event.iwhile = 0; + event.winner = null; + event.maxNum = -1; + event.tempplayer = event.player; + event.result = { + winner: null, + player: event.card1, + targets: event.cardlist.slice(0), + num1: [], + num2: [], + }; + "step 3" + event.trigger("compareCardShowBefore"); + "step 4" + player.$compareMultiple(event.card1, targets, cards); + game.log(player, "的拼点牌为", event.card1); + event.cardlist.forEach((card, index) => { + game.log(targets[index], "的拼点牌为", card); + }); + player.animate("target"); + game.delay(0, 1000); + "step 5" + event.target = null; + event.trigger("compare"); + "step 6" + if (event.iwhile < targets.length) { + event.target = targets[event.iwhile]; + event.target.animate("target"); + event.card2 = event.cardlist[event.iwhile]; + event.num2 = event.getNum(event.card2); + //event.tempplayer.line(event.target); + delete event.player; + event.trigger("compare"); + } + else { + game.delay(0, 1000); + event.goto(9); + } + "step 7" + event.result.num1[event.iwhile] = event.num1; + event.result.num2[event.iwhile] = event.num2; + var list = [[event.tempplayer, event.num1], [event.target, event.num2]]; + for (var i of list) { + if (i[1] > event.maxNum) { + event.maxNum = i[1]; + event.winner = i[0]; + } + else if (event.winner && i[1] == event.maxNum && i[0] != event.winner) { + event.winner = null; + } + } + "step 8" + event.iwhile++; + event.goto(6); + "step 9" + var player = event.tempplayer; + event.player = player; + delete event.tempplayer; + var str = "无人拼点成功"; + if (event.winner) { + event.result.winner = event.winner; + str = get.translation(event.winner) + "拼点成功"; + game.log(event.winner, "拼点成功"); + event.winner.popup("胜"); + } else game.log("#b无人", "拼点成功"); + var list = [player].addArray(targets); + list.remove(event.winner); + for (var i of list) { + i.popup("负"); + } + if (str) { + game.broadcastAll(function (str) { + var dialog = ui.create.dialog(str); + dialog.classList.add("center"); + setTimeout(function () { + dialog.close(); + }, 1000); + }, str); + } + game.delay(3); + "step 10" + game.broadcastAll(ui.clear); + "step 11" + event.cards.add(event.card1); + }, + chooseToCompareMultiple: function () { + "step 0" + if (player.countCards("h") == 0) { + event.result = { cancelled: true, bool: false } + event.finish(); + return; + } + for (var i = 0; i < targets.length; i++) { + if (targets[i].countCards("h") == 0) { + event.result = { cancelled: true, bool: false } + event.finish(); + return; + } + } + if (!event.multitarget) { + targets.sort(lib.sort.seat); + } + game.log(player, "对", targets, "发起拼点"); + "step 1" + event._result = []; + event.list = targets.filter(function (current) { + return !event.fixedResult || !event.fixedResult[current.playerid]; + }); + if (event.list.length || !event.fixedResult || !event.fixedResult[player.playerid]) { + if (!event.fixedResult || !event.fixedResult[player.playerid]) event.list.unshift(player); + player.chooseCardOL(event.list, "请选择拼点牌", true).set("type", "compare").set("ai", event.ai).set("source", player).aiCard = function (target) { + var hs = target.getCards("h"); + var event = _status.event; + event.player = target; + hs.sort(function (a, b) { + return event.ai(b) - event.ai(a); + }); + delete event.player; + return { bool: true, cards: [hs[0]] }; + }; + } + "step 2" + var cards = []; + var lose_list = []; + if (event.fixedResult && event.fixedResult[player.playerid]) { + event.list.unshift(player); + result.unshift({ bool: true, cards: [event.fixedResult[player.playerid]] }); + lose_list.push([player, [event.fixedResult[player.playerid]]]); + } + else { + if (result[0].skill && lib.skill[result[0].skill] && lib.skill[result[0].skill].onCompare) { + player.logSkill(result[0].skill); + result[0].cards = lib.skill[result[0].skill].onCompare(player) + } + else lose_list.push([player, result[0].cards]); + } + for (var j = 0; j < targets.length; j++) { + if (event.list.contains(targets[j])) { + var i = event.list.indexOf(targets[j]); + if (result[i].skill && lib.skill[result[i].skill] && lib.skill[result[i].skill].onCompare) { + event.list[i].logSkill(result[i].skill); + result[i].cards = lib.skill[result[i].skill].onCompare(event.list[i]); + } + else lose_list.push([targets[j], result[i].cards]); + cards.push(result[i].cards[0]); + } + else if (event.fixedResult && event.fixedResult[targets[j].playerid]) { + cards.push(event.fixedResult[targets[j].playerid]); + lose_list.push([targets[j], [event.fixedResult[targets[j].playerid]]]); + } + } + if (lose_list.length) { + game.loseAsync({ + lose_list: lose_list, + }).setContent("chooseToCompareLose"); + } + event.lose_list = lose_list; + event.getNum = function (card) { + for (var i of event.lose_list) { + if (i[1].contains && i[1].contains(card)) return get.number(card, i[0]); + } + return get.number(card, false); + } + event.cardlist = cards; + event.cards = cards; + event.card1 = result[0].cards[0]; + event.num1 = event.getNum(event.card1); + event.iwhile = 0; + event.result = { + player: event.card1, + targets: event.cardlist.slice(0), + num1: [], + num2: [], + }; + "step 3" + event.trigger("compareCardShowBefore"); + "step 4" + game.log(player, "的拼点牌为", event.card1); + "step 5" + if (event.iwhile < targets.length) { + event.target = targets[event.iwhile]; + event.target.animate("target"); + player.animate("target"); + event.card2 = event.cardlist[event.iwhile]; + event.num2 = event.getNum(event.card2); + game.log(event.target, "的拼点牌为", event.card2); + player.line(event.target); + player.$compare(event.card1, event.target, event.card2); + event.trigger("compare"); + game.delay(0, 1500); + } + else { + event.goto(9); + } + "step 6" + event.result.num1[event.iwhile] = event.num1; + event.result.num2[event.iwhile] = event.num2; + var str; + if (event.num1 > event.num2) { + str = get.translation(player) + "拼点成功"; + player.popup("胜"); + target.popup("负"); + } + else { + str = get.translation(player) + "拼点失败"; + if (event.num1 == event.num2) { + player.popup("平"); + target.popup("平"); + } + else { + player.popup("负"); + target.popup("胜"); + } + } + game.broadcastAll(function (str) { + var dialog = ui.create.dialog(str); + dialog.classList.add("center"); + setTimeout(function () { + dialog.close(); + }, 1000); + }, str); + game.delay(2); + "step 7" + if (event.callback) { + game.broadcastAll(function (card1, card2) { + if (card1.clone) card1.clone.style.opacity = 0.5; + if (card2.clone) card2.clone.style.opacity = 0.5; + }, event.card1, event.card2); + var next = game.createEvent("compareMultiple"); + next.player = player; + next.target = event.target; + next.card1 = event.card1; + next.card2 = event.card2; + next.num1 = event.num1; + next.num2 = event.num2; + next.setContent(event.callback); + event.compareMultiple = true; + } + "step 8" + game.broadcastAll(ui.clear); + event.iwhile++; + event.goto(5); + "step 9" + event.cards.add(event.card1); + }, + chooseToCompare: function () { + "step 0" + if (((!event.fixedResult || !event.fixedResult[player.playerid]) && player.countCards("h") == 0) || ((!event.fixedResult || !event.fixedResult[target.playerid]) && target.countCards("h") == 0)) { + event.result = { cancelled: true, bool: false } + event.finish(); + return; + } + game.log(player, "对", target, "发起拼点"); + event.lose_list = []; + "step 1" + var sendback = function () { + if (_status.event != event) { + return function () { + event.resultOL = _status.event.resultOL; + }; + } + }; + if (event.fixedResult && event.fixedResult[player.playerid]) { + event.card1 = event.fixedResult[player.playerid]; + event.lose_list.push([player, event.card1]); + } + else if (player.isOnline()) { + player.wait(sendback); + event.ol = true; + player.send(function (ai) { + game.me.chooseCard("请选择拼点牌", true).set("type", "compare").set("glow_result", true).ai = ai; + game.resume(); + }, event.ai); + } + else { + event.localPlayer = true; + player.chooseCard("请选择拼点牌", true).set("type", "compare").set("glow_result", true).ai = event.ai; + } + if (event.fixedResult && event.fixedResult[target.playerid]) { + event.card2 = event.fixedResult[target.playerid]; + event.lose_list.push([target, event.card2]); + } + else if (target.isOnline()) { + target.wait(sendback); + event.ol = true; + target.send(function (ai) { + game.me.chooseCard("请选择拼点牌", true).set("type", "compare").set("glow_result", true).ai = ai; + game.resume(); + }, event.ai); + } + else { + event.localTarget = true; + } + "step 2" + if (event.localPlayer) { + if (result.skill && lib.skill[result.skill] && lib.skill[result.skill].onCompare) { + result.cards = lib.skill[result.skill].onCompare(player); + player.logSkill(result.skill); + } + else event.lose_list.push([player, result.cards[0]]); + event.card1 = result.cards[0]; + } + if (event.localTarget) { + target.chooseCard("请选择拼点牌", true).set("type", "compare").set("glow_result", true).ai = event.ai; + } + "step 3" + if (event.localTarget) { + if (result.skill && lib.skill[result.skill] && lib.skill[result.skill].onCompare) { + target.logSkill(result.skill); + result.cards = lib.skill[result.skill].onCompare(target); + } + else event.lose_list.push([target, result.cards[0]]); + event.card2 = result.cards[0]; + } + if (!event.resultOL && event.ol) { + game.pause(); + } + "step 4" + try { + if (!event.card1) { + if (event.resultOL[player.playerid].skill && lib.skill[event.resultOL[player.playerid].skill] && lib.skill[event.resultOL[player.playerid].skill].onCompare) { + player.logSkill(event.resultOL[player.playerid].skill); + event.resultOL[player.playerid].cards = lib.skill[event.resultOL[player.playerid].skill].onCompare(player); + } + else event.lose_list.push([player, event.resultOL[player.playerid].cards[0]]); + event.card1 = event.resultOL[player.playerid].cards[0]; + } + if (!event.card2) { + if (event.resultOL[target.playerid].skill && lib.skill[event.resultOL[target.playerid].skill] && lib.skill[event.resultOL[target.playerid].skill].onCompare) { + target.logSkill(event.resultOL[target.playerid].skill); + event.resultOL[target.playerid].cards = lib.skill[event.resultOL[target.playerid].skill].onCompare(player); + } + else event.lose_list.push([target, event.resultOL[target.playerid].cards[0]]); + event.card2 = event.resultOL[target.playerid].cards[0]; + } + if (!event.card1 || !event.card2) { + throw ("err"); + } + } + catch (e) { + console.log(e); + game.print(e); + event.finish(); + return; + } + if (event.card2.number >= 10 || event.card2.number <= 4) { + if (target.countCards("h") > 2) { + event.addToAI = true; + } + } + if (event.lose_list.length) { + game.loseAsync({ + lose_list: event.lose_list, + }).setContent("chooseToCompareLose"); + } + "step 5" + event.trigger("compareCardShowBefore"); + "step 6" + game.broadcast(function () { + ui.arena.classList.add("thrownhighlight"); + }); + ui.arena.classList.add("thrownhighlight"); + game.addVideo("thrownhighlight1"); + player.$compare(event.card1, target, event.card2); + game.log(player, "的拼点牌为", event.card1); + game.log(target, "的拼点牌为", event.card2); + var getNum = function (card) { + for (var i of event.lose_list) { + if (i[1] == card) return get.number(card, i[0]); + } + return get.number(card, false); + } + event.num1 = getNum(event.card1); + event.num2 = getNum(event.card2); + event.trigger("compare"); + game.delay(0, 1500); + "step 7" + event.result = { + player: event.card1, + target: event.card2, + num1: event.num1, + num2: event.num2 + } + var str; + if (event.num1 > event.num2) { + event.result.bool = true; + event.result.winner = player; + str = get.translation(player) + "拼点成功"; + player.popup("胜"); + target.popup("负"); + } + else { + event.result.bool = false; + str = get.translation(player) + "拼点失败"; + if (event.num1 == event.num2) { + event.result.tie = true; + player.popup("平"); + target.popup("平"); + } + else { + event.result.winner = target; + player.popup("负"); + target.popup("胜"); + } + } + game.broadcastAll(function (str) { + var dialog = ui.create.dialog(str); + dialog.classList.add("center"); + setTimeout(function () { + dialog.close(); + }, 1000); + }, str); + game.delay(2); + "step 8" + if (typeof event.target.ai.shown == "number" && event.target.ai.shown <= 0.85 && event.addToAI) { + event.target.ai.shown += 0.1; + } + game.broadcastAll(function () { + ui.arena.classList.remove("thrownhighlight"); + }); + game.addVideo("thrownhighlight2"); + if (event.clear !== false) { + game.broadcastAll(ui.clear); + } + if (typeof event.preserve == "function") { + event.preserve = event.preserve(event.result); + } + else if (event.preserve == "win") { + event.preserve = event.result.bool; + } + else if (event.preserve == "lose") { + event.preserve = !event.result.bool; + } + }, + chooseSkill: function () { + "step 0" + var list; + if (typeof event.target == "string") { + list = get.gainableSkillsName(event.target, event.func); + } + else { + list = event.target.getGainableSkills(event.func); + } + if (!list.length) { + event.finish(); + event.result = { bool: false }; + return; + } + event.skillai = function (list) { + return get.max(list, get.skillRank, "item"); + }; + if (event.isMine()) { + var dialog = ui.create.dialog("forcebutton"); + dialog.add(event.prompt || "选择获得一项技能"); + _status.event.list = list; + var clickItem = function () { + _status.event._result = this.link; + game.resume(); + }; + for (i = 0; i < list.length; i++) { + if (lib.translate[list[i] + "_info"]) { + var translation = get.translation(list[i]); + if (translation[0] == "新" && translation.length == 3) { + translation = translation.slice(1, 3); + } + else { + translation = translation.slice(0, 2); + } + var item = dialog.add(``); + item.firstChild.addEventListener("click", clickItem); + item.firstChild.link = list[i]; + } + } + dialog.add(ui.create.div(".placeholder")); + event.dialog = dialog; + event.switchToAuto = function () { + event._result = event.skillai(event.list); + game.resume(); + }; + _status.imchoosing = true; + game.pause(); + } + else { + event._result = event.skillai(list); + } + "step 1" + _status.imchoosing = false; + if (event.dialog) { + event.dialog.close(); + } + event.result = { bool: true, skill: result }; + }, + discoverCard: function () { + "step 0" + var num = event.num || 3; + var choice; + if (typeof event.list == "string" || typeof event.list == "function") { + choice = get.inpile(event.list).randomGets(num); + } + else if (Array.isArray(event.list)) { + choice = event.list.randomGets(num); + } + else { + choice = Array.from(event.list).randomGets(num); + } + if (choice.length) { + var prompt = event.prompt; + if (!prompt) { + prompt = "选择一张牌"; + if (event.use) { + prompt += "使用之"; + } + else if (!event.nogain) { + prompt += "获得之"; + } + } + if (typeof choice[0] === "string") { + var next = player.chooseVCardButton(choice, prompt, event.forced); + if (event.ai) { + next.set("ai", event.ai); + } + } + else if (get.itemtype(choice[0]) == "card") { + var next = player.chooseCardButton(choice, prompt, event.forced); + if (event.ai) { + next.set("ai", event.ai); + } + } + else { + event.finish(); + } + } + else { + event.finish(); + } + "step 1" + event.result = { + bool: result.bool, + card: null, + choice: null + }; + if (result.bool && result.links.length) { + var link = result.links[0]; + var togain = null; + if (get.itemtype(link) == "card") { + event.result.card = link; + togain = link; + } + else if (Array.isArray(link)) { + event.result.choice = link[2]; + togain = game.createCard(link[2]); + } + if (togain) { + if (event.use) { + player.chooseUseTarget(togain); + } + else if (!event.nogain) { + player.gain(togain, "draw"); + game.log(player, "获得了一张牌"); + } + } + } + }, + chooseButton: function () { + "step 0" + if (typeof event.dialog == "number") { + event.dialog = get.idDialog(event.dialog); + } + if (event.createDialog && !event.dialog) { + if (Array.isArray(event.createDialog)) { + event.createDialog.add("hidden"); + event.dialog = ui.create.dialog.apply(this, event.createDialog); + } + event.closeDialog = true; + } + if (event.dialog == undefined) event.dialog = ui.dialog; + if (event.isMine() || event.dialogdisplay) { + event.dialog.style.display = ""; + event.dialog.open(); + } + var filterButton = event.filterButton || function () { return true }; + var selectButton = get.select(event.selectButton); + var buttons = event.dialog.buttons; + var buttonsx = []; + var num = 0; + for (var i = 0; i < buttons.length; i++) { + var button = buttons[i]; + if (filterButton(button, player)) { + num++; + buttonsx.add(button); + } + } + if (event.isMine()) { + if (event.hsskill && !event.forced && _status.prehidden_skills.contains(event.hsskill)) { + ui.click.cancel(); + return; + } + else if (event.direct && num == selectButton[0] || event.forceDirect) { + var buttons = buttonsx.slice(0, num); + event.result = { + bool: true, + button: [buttons], + links: get.links(buttons), + }; + event.dialog.close(); + } + else { + game.check(); + game.pause(); + } + } + else if (event.isOnline()) { + if (event.direct && num == 1 || event.forceDirect) { + var buttons = buttonsx.slice(0, num); + event.result = { + bool: true, + button: [buttons], + links: get.links(buttons), + }; + event.dialog.close(); + } + else { + event.send(); + } + delete event.callback; + } + else { + event.result = "ai"; + } + if (event.onfree) { + lib.init.onfree(); + } + "step 1" + if (event.result == "ai") { + if (event.processAI) { + event.result = event.processAI(); + } + else { + game.check(); + if ((ai.basic.chooseButton(event.ai) || forced) && (!event.filterOk || event.filterOk())) ui.click.ok(); + else ui.click.cancel(); + } + } + if (event.closeDialog) { + event.dialog.close(); + } + if (event.callback) { + event.callback(event.player, event.result); + } + event.resume(); + }, + chooseCardOL: function () { + "step 0" + event.targets = event.list.slice(0); + if (!_status.connectMode) { + event.result = []; + event.goto(7); + } + else { + for (var i = 0; i < event.list.length; i++) { + var target = event.list[i]; + target.wait(); + if (target.isOnline()) { + target.send(function (args, set) { + game.me.chooseCard.apply(game.me, args).set(set); + game.resume(); + }, event._args, event._set); + event.list.splice(i--, 1); + } + else if (target == game.me) { + event.withme = true; + event.list.splice(i--, 1); + } + } + } + "step 1" + if (event.list.length) { + event.target = event.list.shift(); + event.target.chooseCard.apply(event.target, event._args).set(event._set); + } + else { + event.goto(3); + } + "step 2" + event.target.unwait(result); + event.goto(1); + "step 3" + if (event.withme) { + game.me.chooseCard.apply(game.me, event._args).set(event._set); + } + else { + event.goto(5); + } + "step 4" + game.me.unwait(result); + "step 5" + if (!event.resultOL) { + game.pause(); + } + "step 6" + event.result = []; + for (var i = 0; i < event.targets.length; i++) { + event.result[i] = event.resultOL[event.targets[i].playerid] || {}; + if (event.result[i] == "ai" && event.aiCard) { + event.result[i] = event.aiCard(event.targets[i]); + } + } + event.finish(); + "step 7" + if (event.list.length) { + event.target = event.list.shift(); + event.target.chooseCard.apply(event.target, event._args).set(event._set); + } + else { + for (var i = 0; i < event.targets.length; i++) { + if (!event.result[i]) { + event.result[i] = {}; + } + } + event.finish(); + } + "step 8" + event.result[event.targets.indexOf(event.target)] = result; + event.goto(7); + }, + chooseButtonOL: function () { + "step 0" + //ui.arena.classList.add("markhidden"); + for (var i = 0; i < event.list.length; i++) { + var current = event.list[i]; + current[0].wait(); + if (current[0].isOnline()) { + var target = current.shift(); + target.send(function (args, callback, switchToAuto, processAI) { + //ui.arena.classList.add("markhidden"); + var next = game.me.chooseButton.apply(game.me, args); + next.callback = callback; + next.switchToAuto = switchToAuto; + next.processAI = processAI; + next.complexSelect = true; + game.resume(); + }, current, event.callback, event.switchToAuto, event.processAI); + target._choose_button_ol = current; + event.list.splice(i--, 1); + } + else if (current[0] == game.me) { + event.last = current; + event.last.shift(); + event.list.splice(i--, 1); + } + } + "step 1" + if (event.list.length) { + var current = event.list.shift(); + event.target = current.shift(); + var next = event.target.chooseButton.apply(event.target, current); + next.callback = event.callback; + next.switchToAuto = event.switchToAuto; + next.processAI = event.processAI; + } + else { + event.goto(3); + } + "step 2" + event.target.unwait(result); + event.goto(1); + "step 3" + if (event.last) { + var next = game.me.chooseButton.apply(game.me, event.last); + next.callback = event.callback; + next.switchToAuto = event.switchToAuto; + next.processAI = event.processAI; + } + else { + event.goto(5); + } + "step 4" + game.me.unwait(result); + "step 5" + if (!event.resultOL) { + game.pause(); + } + "step 6" + /*game.broadcastAll(function(){ + ui.arena.classList.remove("markhidden"); + });*/ + event.result = event.resultOL; + }, + chooseCard: function () { + "step 0" + if (event.directresult) { + event.result = { + buttons: [], + cards: event.directresult.slice(0), + targets: [], + confirm: "ok", + bool: true, + links: [] + }; + } + else { + if (event.isMine()) { + game.check(); + game.pause(); + if (event.hsskill && !event.forced && _status.prehidden_skills.contains(event.hsskill)) { + ui.click.cancel(); + return; + } + if (event.prompt != false) { + var str; + if (typeof event.prompt == "string") str = event.prompt; + else { + str = "请选择" + var range = get.select(event.selectCard); + if (range[0] == range[1]) str += get.cnNumber(range[0]); + else if (range[1] == Infinity) str += "至少" + get.cnNumber(range[0]); + else str += get.cnNumber(range[0]) + "至" + get.cnNumber(range[1]); + str += "张"; + if (event.position == "h" || event.position == undefined) str += "手"; + if (event.position == "e") str += "装备"; + str += "牌"; + } + event.dialog = ui.create.dialog(str); + if (event.prompt2) { + event.dialog.addText(event.prompt2, event.prompt2.length <= 20); + } + if (Array.isArray(event.promptx)) { + for (var i = 0; i < event.promptx.length; i++) { + event.dialog.add(event.promptx[i]); + } + } + if (Array.isArray(event.selectCard)) { + event.promptbar = event.dialog.add("0/" + get.numStr(event.selectCard[1], "card")); + event.custom.add.card = function () { + _status.event.promptbar.innerHTML = + ui.selected.cards.length + "/" + get.numStr(_status.event.selectCard[1], "card"); + } + } + } + } + else if (event.isOnline()) { + event.send(); + } + else { + event.result = "ai"; + } + } + "step 1" + if (event.result == "ai") { + game.check(); + if ((ai.basic.chooseCard(event.ai) || forced) && (!event.filterOk || event.filterOk())) { + ui.click.ok(); + } + else if (event.skill) { + var skill = event.skill; + ui.click.cancel(); + event._aiexclude.add(skill); + event.redo(); + game.resume(); + } + else { + ui.click.cancel(); + } + } + "step 2" + event.resume(); + if (event.glow_result && event.result.cards && !event.directresult) { + for (var i = 0; i < event.result.cards.length; i++) { + event.result.cards[i].classList.add("glow"); + } + } + if (event.dialog) event.dialog.close(); + }, + chooseTarget: function () { + "step 0" + if (event.isMine()) { + if (event.hsskill && !event.forced && _status.prehidden_skills.contains(event.hsskill)) { + ui.click.cancel(); + return; + } + game.check(); + game.pause(); + if (event.createDialog && !event.dialog && Array.isArray(event.createDialog)) { + event.dialog = ui.create.dialog.apply(this, event.createDialog); + } + else if (event.prompt != false) { + var str; + if (typeof event.prompt == "string") str = event.prompt; + else { + str = "请选择" + var range = get.select(event.selectTarget); + if (range[0] == range[1]) str += get.cnNumber(range[0]); + else if (range[1] == Infinity) str += "至少" + get.cnNumber(range[0]); + else str += get.cnNumber(range[0]) + "至" + get.cnNumber(range[1]); + str += "个目标"; + } + event.dialog = ui.create.dialog(str); + if (event.prompt2) { + event.dialog.addText(event.prompt2, event.prompt2.length <= 20); + } + if (event.promptbar != "none") { + event.promptbar = event.dialog.add("0/" + get.numStr(get.select(event.selectTarget)[1], "target")); + event.custom.add.target = function () { + _status.event.promptbar.innerHTML = + ui.selected.targets.length + "/" + get.numStr(get.select(event.selectTarget)[1], "target"); + } + } + } + else if (get.itemtype(event.dialog) == "dialog") { + event.dialog.open(); + } + } + else if (event.isOnline()) { + event.send(); + } + else { + event.result = "ai"; + } + "step 1" + if (event.result == "ai") { + game.check(); + if ((ai.basic.chooseTarget(event.ai) || forced) && (!event.filterOk || event.filterOk())) { + ui.click.ok(); + } + else { + ui.click.cancel(); + } + } + if (event.result.bool && event.animate !== false) { + for (var i = 0; i < event.result.targets.length; i++) { + event.result.targets[i].animate("target"); + } + } + if (event.dialog) event.dialog.close(); + event.resume(); + "step 2" + if (event.onresult) { + event.onresult(event.result); + } + if (event.result.bool && event.autodelay && !event.isMine()) { + if (typeof event.autodelay == "number") { + game.delayx(event.autodelay); + } + else { + game.delayx(); + } + } + }, + chooseCardTarget: function () { + "step 0" + if (event.isMine()) { + if (event.hsskill && !event.forced && _status.prehidden_skills.contains(event.hsskill)) { + ui.click.cancel(); + return; + } + game.check(); + game.pause(); + if (event.prompt != false) { + event.dialog = ui.create.dialog(event.prompt || "请选择卡牌和目标"); + if (event.prompt2) { + event.dialog.addText(event.prompt2, event.prompt2.length <= 20); + } + } + } + else if (event.isOnline()) { + event.send(); + } + else { + event.result = "ai"; + } + "step 1" + if (event.result == "ai") { + game.check(); + if (ai.basic.chooseCard(event.ai1) || forced) { + if ((ai.basic.chooseTarget(event.ai2) || forced) && (!event.filterOk || event.filterOk())) { + ui.click.ok(); + _status.event._aiexclude.length = 0; + } + else { + ui.click.cancel(); + } + } + else { + ui.click.cancel(); + } + } + "step 2" + event.resume(); + if (event.result.bool && event.animate !== false) { + for (var i = 0; i < event.result.targets.length; i++) { + event.result.targets[i].animate("target"); + } + } + if (event.dialog) event.dialog.close(); + }, + chooseControl: function () { + "step 0" + if (event.controls.length == 0) { + if (event.sortcard) { + var sortnum = 2; + if (event.sorttop) { + sortnum = 1; + } + for (var i = 0; i < event.sortcard.length + sortnum; i++) { + event.controls.push(get.cnNumber(i, true)); + } + } + else if (event.choiceList) { + for (var i = 0; i < event.choiceList.length; i++) { + event.controls.push("选项" + get.cnNumber(i + 1, true)); + } + } + else { + event.finish(); + return; + } + } + else if (event.choiceList && event.controls.length == 1 && event.controls[0] == "cancel2") { + event.controls.shift(); + for (var i = 0; i < event.choiceList.length; i++) { + event.controls.push("选项" + get.cnNumber(i + 1, true)); + } + event.controls.push("cancel2"); + } + if (event.isMine()) { + if (event.arrangeSkill) { + var hidden = player.hiddenSkills.slice(0); + game.expandSkills(hidden); + if (hidden.length) { + for (var i of event.controls) { + if (_status.prehidden_skills.contains(i) && hidden.contains(i)) { + event.result = { + bool: true, + control: i, + } + return; + } + } + } + } + else if (event.hsskill && _status.prehidden_skills.contains(event.hsskill) && event.controls.contains("cancel2")) { + event.result = { + bool: true, + control: "cancel2", + } + return; + } + if (event.sortcard) { + var prompt = event.prompt || "选择一个位置"; + if (event.tosort) { + prompt += "放置" + get.translation(event.tosort); + } + event.dialog = ui.create.dialog(prompt, "hidden"); + if (event.sortcard && event.sortcard.length) { + event.dialog.addSmall(event.sortcard); + } + else { + event.dialog.buttons = []; + event.dialog.add(ui.create.div(".buttons")); + } + var buttons = event.dialog.content.lastChild; + var sortnum = 2; + if (event.sorttop) { + sortnum = 1; + } + for (var i = 0; i < event.dialog.buttons.length + sortnum; i++) { + var item = ui.create.div(".button.card.pointerdiv.mebg"); + item.style.width = "50px"; + buttons.insertBefore(item, event.dialog.buttons[i]); + item.innerHTML = `
第${get.cnNumber(i + 1, true)}张
`; + if (i == event.dialog.buttons.length + 1) { + item.firstChild.innerHTML = "牌堆底"; + } + item.link = get.cnNumber(i, true); + item.listen(ui.click.dialogcontrol); + } + + event.dialog.forcebutton = true; + event.dialog.classList.add("forcebutton"); + event.dialog.open(); + } + else if (event.dialogcontrol) { + event.dialog = ui.create.dialog(event.prompt || "选择一项", "hidden"); + for (var i = 0; i < event.controls.length; i++) { + var item = event.dialog.add(``); + item.firstChild.listen(ui.click.dialogcontrol); + item.firstChild.link = event.controls[i]; + } + event.dialog.forcebutton = true; + event.dialog.classList.add("forcebutton"); + if (event.addDialog) { + for (var i = 0; i < event.addDialog.length; i++) { + if (get.itemtype(event.addDialog[i]) == "cards") { + event.dialog.addSmall(event.addDialog[i]); + } + else { + event.dialog.add(event.addDialog[i]); + } + } + event.dialog.add(ui.create.div(".placeholder.slim")); + } + event.dialog.open(); + } + else { + if (event.seperate || lib.config.seperate_control) { + var controls = event.controls.slice(0); + var num = 0; + controls.remove("cancel2"); + if (event.direct && controls.length == 1 || event.forceDirect) { + event.result = { + control: event.controls[0].link, + links: get.links([event.controls[0]]), + }; + return; + } + else { + event.controlbars = []; + for (var i = 0; i < event.controls.length; i++) { + event.controlbars.push(ui.create.control([event.controls[i]])); + } + } + } + else { + var controls = event.controls.slice(0); + var num = 0; + controls.remove("cancel2"); + if (event.direct && controls.length == 1 || event.forceDirect) { + event.result = { + control: event.controls[0].link, + links: get.links([event.controls[0]]), + }; + return; + } + event.controlbar = ui.create.control(event.controls); + } + if (event.dialog) { + if (Array.isArray(event.dialog)) { + event.dialog = ui.create.dialog.apply(this, event.dialog); + } + event.dialog.open(); + } + else if (event.choiceList) { + event.dialog = ui.create.dialog(event.prompt || "选择一项", "hidden"); + event.dialog.forcebutton = true; + event.dialog.open(); + for (var i = 0; i < event.choiceList.length; i++) { + event.dialog.add(``); + } + } + else if (event.prompt) { + event.dialog = ui.create.dialog(event.prompt); + if (event.prompt2) { + event.dialog.addText(event.prompt2, Boolean(event.prompt2.length <= 20 || event.centerprompt2)); + } + } + } + game.pause(); + game.countChoose(); + event.choosing = true; + } + else if (event.isOnline()) { + event.send(); + } + else { + event.result = "ai"; + } + "step 1" + if (event.result == "ai") { + event.result = {}; + if (event.ai) { + var result = event.ai(event.getParent(), player); + if (typeof result == "number") event.result.control = event.controls[result]; + else event.result.control = result; + } + else event.result.control = event.controls[event.choice]; + } + event.result.index = event.controls.indexOf(event.result.control); + event.choosing = false; + _status.imchoosing = false; + if (event.dialog && event.dialog.close) event.dialog.close(); + if (event.controlbar) event.controlbar.close(); + if (event.controlbars) { + for (var i = 0; i < event.controlbars.length; i++) { + event.controlbars[i].close(); + } + } + event.resume(); + }, + chooseBool: function () { + "step 0" + if (event.isMine()) { + if (event.frequentSkill && !lib.config.autoskilllist.contains(event.frequentSkill)) { + ui.click.ok(); + return; + } + else if (event.hsskill && _status.prehidden_skills.contains(event.hsskill)) { + ui.click.cancel(); + return; + } + ui.create.confirm("oc"); + if (event.createDialog && !event.dialog) { + if (Array.isArray(event.createDialog)) { + event.dialog = ui.create.dialog.apply(this, event.createDialog); + if (event.dialogselectx) { + for (var i = 0; i < event.dialog.buttons.length; i++) { + event.dialog.buttons[i].classList.add("selectedx"); + } + } + } + } + if (event.dialog) { + event.dialog.open(); + } + else if (event.prompt) { + event.dialog = ui.create.dialog(event.prompt); + if (event.prompt2) { + event.dialog.addText(event.prompt2, event.prompt2.length <= 20); + } + } + game.pause(); + game.countChoose(); + event.choosing = true; + } + else if (event.isOnline()) { + event.send(); + } + else { + event.result = "ai"; + } + "step 1" + if (event.result == "ai") { + if (event.ai) { + event.choice = event.ai(event.getParent(), player); + } + event.result = { bool: event.choice }; + } + _status.imchoosing = false; + event.choosing = false; + if (event.dialog) event.dialog.close(); + event.resume(); + }, + chooseDrawRecover: function () { + "step 0" + if (player.isHealthy() && event.forced) { + player.draw(event.num1); + event.finish(); + return; + } + var controls = ["draw_card"]; + if (player.isDamaged()) { + event.num2 = Math.min(event.num2, player.maxHp - player.hp); + controls.push("recover_hp"); + } + if (!event.forced) { + controls.push("cancel2"); + } + var prompt = event.prompt; + if (!prompt) { + if (player.isHealthy()) { + prompt = "是否摸" + get.cnNumber(event.num1) + "张牌?"; + } + else { + prompt = "摸" + get.cnNumber(event.num1) + "张牌或回复" + get.cnNumber(event.num2) + "点体力"; + } + } + var next = player.chooseControl(controls); + next.set("prompt", prompt); + if (event.hsskill) next.setHiddenSkill(event.hsskill); + if (event.ai) { + next.set("ai", event.ai); + } + else { + var choice; + if (player.isDamaged() && get.recoverEffect(player) > 0 && ( + player.hp == 1 || player.needsToDiscard() || + player.hasSkillTag("maixie_hp") || event.num2 > event.num1 || + (event.num2 == event.num1 && player.needsToDiscard(1)) + )) { + choice = "recover_hp"; + } + else { + choice = "draw_card"; + } + next.set("ai", function () { + return _status.event.choice; + }); + next.set("choice", choice); + } + "step 1" + if (result.control != "cancel2") { + if (event.logSkill) { + if (typeof event.logSkill == "string") { + player.logSkill(event.logSkill); + } + else if (Array.isArray(event.logSkill)) { + player.logSkill.apply(player, event.logSkill); + } + } + if (result.control == "draw_card") { + player.draw(event.num1); + } + else { + player.recover(event.num2); + } + } + event.result = result; + }, + choosePlayerCard: function () { + "step 0" + if (!event.dialog) event.dialog = ui.create.dialog("hidden"); + else if (!event.isMine()) { + event.dialog.style.display = "none"; + } + if (event.prompt) { + event.dialog.add(event.prompt); + } + else { + event.dialog.add("选择" + get.translation(target) + "的一张牌"); + } + if (event.prompt2) { + event.dialog.addText(event.prompt2); + } + var expand_length = 0; + var directh = (!lib.config.unauto_choose && !event.complexSelect); + for (var i = 0; i < event.position.length; i++) { + if (event.position[i] == "h") { + var hs = target.getCards("h"); + if (hs.length) { + expand_length += Math.ceil(hs.length / 6); + var title = event.dialog.add(`
手牌区
`); + title.style.margin = "0px"; + title.style.padding = "0px"; + hs.randomSort(); + if (event.visible || target.isUnderControl(true) || player.hasSkillTag("viewHandcard", null, target, true)) { + event.dialog.add(hs); + directh = false; + } + else { + var shown = hs.filter(card => get.is.shownCard(card)); + if (shown.length) { + var hidden = hs.filter(card => !shown.includes(card)); + var buttons = ui.create.div(".buttons", event.dialog.content); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(shown, "card", buttons)); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(hidden, "blank", buttons)); + if (event.dialog.forcebutton !== false) event.dialog.forcebutton = true; + if (event.dialog.buttons.length > 3) { + event.dialog.classList.remove("forcebutton-auto"); + } + else if (!event.dialog.noforcebutton) { + event.dialog.classList.add("forcebutton-auto"); + } + } + else { + event.dialog.add([hs, "blank"]); + } + } + } + } + else if (event.position[i] == "e") { + var es = target.getCards("e"); + if (es.length) { + expand_length += Math.ceil(es.length / 6); + var title = event.dialog.add(`
装备区
`); + title.style.margin = "0px"; + title.style.padding = "0px"; + event.dialog.add(es); + directh = false; + } + } + else if (event.position[i] == "j") { + var js = target.getCards("j"); + if (js.length) { + expand_length += Math.ceil(js.length / 6); + var title = event.dialog.add(`
判定区
`); + title.style.margin = "0px"; + title.style.padding = "0px"; + event.dialog.add(js); + directh = false; + } + } + } + if (event.dialog.buttons.length == 0) { + event.finish(); + return; + } var directFilter = (event.forced && typeof event.filterOk != "function" && typeof event.selectButton != "function" && event.filterButton == lib.filter.all); + var cs = target.getCards(event.position); + var select = get.select(event.selectButton); + if (directFilter && select[0] >= cs.length) { + event.result = { + bool: true, + buttons: event.dialog.buttons, + links: cs + } + } + else if (directFilter && directh && !event.isOnline() && select[0] == select[1]) { + event.result = { + bool: true, + buttons: event.dialog.buttons.randomGets(select[0]), + links: [] + } + for (var i = 0; i < event.result.buttons.length; i++) { + event.result.links[i] = event.result.buttons[i].link; + } + } + else { + if (event.isMine()) { + if (event.hsskill && !event.forced && _status.prehidden_skills.contains(event.hsskill)) { + ui.click.cancel(); + return; + } + event.dialog.open(); + game.check(); + game.pause(); + if (expand_length > 2) { + ui.arena.classList.add("choose-player-card"); + event.dialog.classList.add("fullheight"); + } + } + else if (event.isOnline()) { + event.send(); + } + else { + event.result = "ai"; + } + } + "step 1" + if (event.result == "ai") { + game.check(); + if ((ai.basic.chooseButton(event.ai) || forced) && (!event.filterOk || event.filterOk())) ui.click.ok(); + else ui.click.cancel(); + } + event.dialog.close(); + if (event.result.links) { + event.result.cards = event.result.links.slice(0); + } + event.resume(); + setTimeout(function () { + ui.arena.classList.remove("choose-player-card"); + }, 500); + }, + discardPlayerCard: function () { + "step 0" + if (event.directresult) { + event.result = { + buttons: [], + cards: event.directresult.slice(0), + links: event.directresult.slice(0), + targets: [], + confirm: "ok", + bool: true + }; + event.cards = event.directresult.slice(0); + event.goto(2); + return; + } + if (!event.dialog) event.dialog = ui.create.dialog("hidden"); + else if (!event.isMine()) { + event.dialog.style.display = "none"; + } + if (event.prompt == undefined) { + var str = "弃置" + get.translation(target); + var range = get.select(event.selectButton); + if (range[0] == range[1]) str += get.cnNumber(range[0]); + else if (range[1] == Infinity) str += "至少" + get.cnNumber(range[0]); + else str += get.cnNumber(range[0]) + "至" + get.cnNumber(range[1]); + str += "张"; + if (event.position == "h" || event.position == undefined) str += "手"; + if (event.position == "e") str += "装备"; + str += "牌"; + event.prompt = str; + } + if (event.prompt) { + event.dialog.add(event.prompt); + } + if (event.prompt2) { + event.dialog.addText(event.prompt2); + } + var directh = (!lib.config.unauto_choose && !event.complexSelect); + var expand_length = 0; + for (var i = 0; i < event.position.length; i++) { + if (event.position[i] == "h") { + var hs = target.getDiscardableCards(player, "h"); + expand_length += Math.ceil(hs.length / 6); + if (hs.length) { + var title = event.dialog.add(`
手牌区
`); + title.style.margin = "0px"; + title.style.padding = "0px"; + hs.randomSort(); + if (event.visible || target.isUnderControl(true) || player.hasSkillTag("viewHandcard", null, target, true)) { + event.dialog.add(hs); + directh = false; + } + else { + var shown = hs.filter(card => get.is.shownCard(card)); + if (shown.length) { + var hidden = hs.filter(card => !shown.includes(card)); + var buttons = ui.create.div(".buttons", event.dialog.content); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(shown, "card", buttons)); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(hidden, "blank", buttons)); + if (event.dialog.forcebutton !== false) event.dialog.forcebutton = true; + if (event.dialog.buttons.length > 3) { + event.dialog.classList.remove("forcebutton-auto"); + } + else if (!event.dialog.noforcebutton) { + event.dialog.classList.add("forcebutton-auto"); + } + } + else { + event.dialog.add([hs, "blank"]); + } + } + } + } + else if (event.position[i] == "e") { + var es = target.getDiscardableCards(player, "e"); + if (es.length) { + expand_length += Math.ceil(es.length / 6); + var title = event.dialog.add(`
装备区
`); + title.style.margin = "0px"; + title.style.padding = "0px"; + event.dialog.add(es); + directh = false; + } + } + else if (event.position[i] == "j") { + var js = target.getDiscardableCards(player, "j"); + if (js.length) { + expand_length += Math.ceil(js.length / 6); + var title = event.dialog.add(`
判定区
`); + title.style.margin = "0px"; + title.style.padding = "0px"; + event.dialog.add(js); + directh = false; + } + } + } + if (event.dialog.buttons.length == 0) { + event.finish(); + return; + } + var directFilter = (event.forced && typeof event.filterOk != "function" && typeof event.selectButton != "function" && event.filterButton == lib.filter.all); + var cs = target.getCards(event.position); + var select = get.select(event.selectButton); + if (directFilter && select[0] >= cs.length) { + event.result = { + bool: true, + buttons: event.dialog.buttons, + links: cs + } + } + else if (directFilter && directh && !event.isOnline() && select[0] == select[1]) { + event.result = { + bool: true, + buttons: event.dialog.buttons.randomGets(select[0]), + links: [] + } + for (var i = 0; i < event.result.buttons.length; i++) { + event.result.links[i] = event.result.buttons[i].link; + } + } + else { + if (event.isMine()) { + event.dialog.open(); + game.check(); + game.pause(); + if (expand_length > 2) { + ui.arena.classList.add("discard-player-card"); + event.dialog.classList.add("fullheight"); + } + } + else if (event.isOnline()) { + event.send(); + } + else { + event.result = "ai"; + } + } + "step 1" + if (event.result == "ai") { + game.check(); + if ((ai.basic.chooseButton(event.ai) || forced) && (!event.filterOk || event.filterOk())) ui.click.ok(); + else ui.click.cancel(); + } + event.dialog.close(); + "step 2" + event.resume(); + setTimeout(function () { + ui.arena.classList.remove("discard-player-card"); + }, 500); + if (event.result.bool && event.result.links && !game.online) { + if (event.logSkill) { + if (typeof event.logSkill == "string") { + player.logSkill(event.logSkill); + } + else if (Array.isArray(event.logSkill)) { + player.logSkill.apply(player, event.logSkill); + } + } + var cards = []; + for (var i = 0; i < event.result.links.length; i++) { + cards.push(event.result.links[i]); + } + event.result.cards = event.result.links.slice(0); + event.cards = cards; + event.trigger("rewriteDiscardResult"); + } + "step 3" + if (event.boolline) { + player.line(target, "green"); + } + if (!event.chooseonly) { + var next = target.discard(event.cards); + if (player != target) next.notBySelf = true; + next.discarder = player; + event.done = next; + if (event.delay === false) { + next.set("delay", false); + } + } + }, + gainPlayerCard: function () { + "step 0" + if (event.directresult) { + event.result = { + buttons: [], + cards: event.directresult.slice(0), + links: event.directresult.slice(0), + targets: [], + confirm: "ok", + bool: true + }; + event.cards = event.directresult.slice(0); + event.goto(2); + return; + } + if (!event.dialog) event.dialog = ui.create.dialog("hidden"); + else if (!event.isMine()) { + event.dialog.style.display = "none"; + } + if (event.prompt == undefined) { + var str = "获得" + get.translation(target); + var range = get.select(event.selectButton); + if (range[0] == range[1]) str += get.cnNumber(range[0]); + else if (range[1] == Infinity) str += "至少" + get.cnNumber(range[0]); + else str += get.cnNumber(range[0]) + "至" + get.cnNumber(range[1]); + str += "张"; + if (event.position == "h" || event.position == undefined) str += "手"; + if (event.position == "e") str += "装备"; + str += "牌"; + event.prompt = str; + } + if (event.prompt) { + event.dialog.add(event.prompt); + } + if (event.prompt2) { + event.dialog.addText(event.prompt2); + } + var expand_length = 0; + var directh = (!lib.config.unauto_choose && !event.complexSelect); + for (var i = 0; i < event.position.length; i++) { + if (event.position[i] == "h") { + var hs = target.getGainableCards(player, "h"); + if (hs.length) { + expand_length += Math.ceil(hs.length / 6); + var title = event.dialog.add(`
手牌区
`); + title.style.margin = "0px"; + title.style.padding = "0px"; + hs.randomSort(); + if (event.visible || target.isUnderControl(true) || player.hasSkillTag("viewHandcard", null, target, true)) { + event.dialog.add(hs); + directh = false; + } + else { + var shown = hs.filter(card => get.is.shownCard(card)); + if (shown.length) { + var hidden = hs.filter(card => !shown.includes(card)); + var buttons = ui.create.div(".buttons", event.dialog.content); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(shown, "card", buttons)); + event.dialog.buttons = event.dialog.buttons.concat(ui.create.buttons(hidden, "blank", buttons)); + if (event.dialog.forcebutton !== false) event.dialog.forcebutton = true; + if (event.dialog.buttons.length > 3) { + event.dialog.classList.remove("forcebutton-auto"); + } + else if (!event.dialog.noforcebutton) { + event.dialog.classList.add("forcebutton-auto"); + } + } + else { + event.dialog.add([hs, "blank"]); + } + } + } + } + else if (event.position[i] == "e") { + var es = target.getGainableCards(player, "e"); + if (es.length) { + expand_length += Math.ceil(es.length / 6); + var title = event.dialog.add(`
装备区
`); + title.style.margin = "0px"; + title.style.padding = "0px"; + event.dialog.add(es); + directh = false; + } + } + else if (event.position[i] == "j") { + var js = target.getGainableCards(player, "j"); + if (js.length) { + expand_length += Math.ceil(js.length / 6); + var title = event.dialog.add(`
判定区
`); + title.style.margin = "0px"; + title.style.padding = "0px"; + event.dialog.add(js); + directh = false; + } + } + } + if (event.dialog.buttons.length == 0) { + event.dialog.close(); + event.finish(); + return; + } + var cs = target.getCards(event.position); + var select = get.select(event.selectButton); + var directFilter = (event.forced && typeof event.filterOk != "function" && typeof event.selectButton != "function" && event.filterButton == lib.filter.all); + if (directFilter && select[0] >= cs.length) { + event.result = { + bool: true, + buttons: event.dialog.buttons, + links: cs + } + } + else if (directFilter && directh && !event.isOnline() && select[0] == select[1]) { + event.result = { + bool: true, + buttons: event.dialog.buttons.randomGets(select[0]), + links: [] + } + for (var i = 0; i < event.result.buttons.length; i++) { + event.result.links[i] = event.result.buttons[i].link; + } + } + else { + if (event.isMine()) { + event.dialog.open(); + game.check(); + game.pause(); + if (expand_length > 2) { + ui.arena.classList.add("gain-player-card"); + event.dialog.classList.add("fullheight"); + } + } + else if (event.isOnline()) { + event.send(); + } + else { + event.result = "ai"; + } + } + "step 1" + if (event.result == "ai") { + game.check(); + if ((ai.basic.chooseButton(event.ai) || forced) && (!event.filterOk || event.filterOk())) ui.click.ok(); + else ui.click.cancel(); + } + event.dialog.close(); + "step 2" + event.resume(); + setTimeout(function () { + ui.arena.classList.remove("gain-player-card"); + }, 500); + if (game.online || !event.result.bool) { + event.finish(); + } + "step 3" + if (event.logSkill && event.result.bool && !game.online) { + if (typeof event.logSkill == "string") { + player.logSkill(event.logSkill); + } + else if (Array.isArray(event.logSkill)) { + player.logSkill.apply(player, event.logSkill); + } + } + var cards = []; + for (var i = 0; i < event.result.links.length; i++) { + cards.push(event.result.links[i]); + } + event.result.cards = event.result.links.slice(0); + event.cards = cards; + event.trigger("rewriteGainResult"); + "step 4" + if (event.boolline) { + player.line(target, "green"); + } + if (!event.chooseonly) { + if (event.delay !== false) { + var next = player.gain(event.cards, target, event.visibleMove ? "give" : "giveAuto", "bySelf"); + event.done = next; + } + else { + var next = player.gain(event.cards, target, "bySelf"); + event.done = next; + target[event.visibleMove ? "$give" : "$giveAuto"](cards, player); + if (event.visibleMove) next.visible = true; + } + } + else target[event.visibleMove ? "$give" : "$giveAuto"](cards, player); + }, + showHandcards: function () { + "step 0" + if (player.countCards("h") == 0) { + event.finish(); + return; + } + var cards = player.getCards("h"); + player.showCards(cards).setContent(function () { }); + var str = get.translation(player.name) + "的手牌"; + if (typeof event.prompt == "string") { + str = event.prompt; + } + event.dialog = ui.create.dialog(str, cards); + event.dialogid = lib.status.videoId++; + event.dialog.videoId = event.dialogid; + game.broadcast(function (str, cards, id) { + ui.create.dialog(str, cards).videoId = id; + }, str, cards, event.dialogid); + game.log(player, "展示了", cards); + game.addVideo("showCards", player, [str, get.cardsInfo(cards)]); + game.delayx(2); + "step 1" + game.broadcast("closeDialog", event.dialogid); + event.dialog.close(); + }, + showCards: function () { + "step 0" + if (get.itemtype(cards) != "cards") { + event.finish(); + return; + } + if (!event.str) { + event.str = get.translation(player.name) + "展示的牌"; + } + event.dialog = ui.create.dialog(event.str, cards); + event.dialogid = lib.status.videoId++; + event.dialog.videoId = event.dialogid; + + if (event.hiddencards) { + for (var i = 0; i < event.dialog.buttons.length; i++) { + if (event.hiddencards.contains(event.dialog.buttons[i].link)) { + event.dialog.buttons[i].className = "button card"; + event.dialog.buttons[i].innerHTML = ""; + } + } + } + game.broadcast(function (str, cards, cards2, id) { + var dialog = ui.create.dialog(str, cards); + dialog.forcebutton = true; + dialog.videoId = id; + if (cards2) { + for (var i = 0; i < dialog.buttons.length; i++) { + if (cards2.contains(dialog.buttons[i].link)) { + dialog.buttons[i].className = "button card"; + dialog.buttons[i].innerHTML = ""; + } + } + } + }, event.str, cards, event.hiddencards, event.dialogid); + if (event.hiddencards) { + var cards2 = cards.slice(0); + for (var i = 0; i < event.hiddencards.length; i++) { + cards2.remove(event.hiddencards[i]); + } + game.log(player, "展示了", cards2); + } + else { + game.log(player, "展示了", cards); + } + game.addCardKnower(cards, "everyone"); + game.delayx(event.delay_time || 2.5); + game.addVideo("showCards", player, [event.str, get.cardsInfo(cards)]); + "step 1" + game.broadcast("closeDialog", event.dialogid); + event.dialog.close(); + }, + viewCards: function () { + "step 0" + game.addCardKnower(event.cards, player); + if (player == game.me) { + event.dialog = ui.create.dialog(event.str, event.cards); + if (event.isMine()) { + game.pause(); + ui.create.confirm("o"); + game.countChoose(); + event.choosing = true; + } + else { + event.finish(); + event.result = "viewed"; + setTimeout(function () { + event.dialog.close(); + }, 2 * lib.config.duration); + game.delayx(2); + } + } + else if (event.isOnline()) { + event.send(); + } + else { + event.finish(); + } + "step 1" + event.result = "viewed"; + _status.imchoosing = false; + event.choosing = false; + if (event.dialog) event.dialog.close(); + }, + moveCard: function () { + "step 0" + if (!player.canMoveCard(null, event.nojudge, event.sourceTargets, event.aimTargets, event.filter, event.canReplace ? "canReplace" : "noReplace")) { + event.finish(); + return; + } + var next = player.chooseTarget(2, function (card, player, target) { + var filterCard = get.event("filter"); + if (ui.selected.targets.length) { + if (!get.event("aimTargets").includes(target)) return false; + var from = ui.selected.targets[0]; + var js = from.getCards("j", filterCard); + for (var i = 0; i < js.length; i++) { + if (_status.event.nojudge) break; + if (target.canAddJudge(js[i])) return true; + } + if (target.isMin()) return false; + var es = from.getCards("e", filterCard); + for (var i = 0; i < es.length; i++) { + if (target.canEquip(es[i], _status.event.canReplace)) return true; + } + return false; + } + else { + if (!get.event("sourceTargets").includes(target)) return false; + var range = "ej"; + if (_status.event.nojudge) range = "e"; + return target.countCards(range, filterCard) > 0; + } + }); + next.set("nojudge", event.nojudge || false); + next.set("ai", function (target) { + var player = _status.event.player; + var att = get.attitude(player, target); + var sgnatt = get.sgn(att); + var aimTargets = get.event("aimTargets"), filterCard = get.event("filter"); + if (ui.selected.targets.length == 0) { + if (att > 0) { + if (!_status.event.nojudge && target.countCards("j", function (card) { + if (!filterCard(card)) return false; + return game.hasPlayer(function (current) { + if (!aimTargets.includes(current)) return false; + return current != target && current.canAddJudge(card) && get.attitude(player, current) < 0; + }) + })) return 14; + if (target.countCards("e", function (card) { + if (!filterCard(card)) return false; + return get.value(card, target) < 0 && game.hasPlayer(function (current) { + if (!aimTargets.includes(current)) return false; + return current != target && get.attitude(player, current) < 0 && current.canEquip(card, _status.event.canReplace) && get.effect(target, card, player, player) < 0; + }); + }) > 0) return 9; + } + else if (att < 0) { + if (game.hasPlayer(function (current) { + if (current != target && get.attitude(player, current) > 0) { + var es = target.getCards("e", filterCard); + for (var i = 0; i < es.length; i++) { + if (get.value(es[i], target) > 0 && current.canEquip(es[i], _status.event.canReplace) && get.effect(current, es[i], player, player) > (_status.event.canReplace ? get.effect(target, es[i], player, player) : 0)) return true; + } + } + })) { + return -att; + } + } + return 0; + } + var es = ui.selected.targets[0].getCards("e", filterCard); + var i; + var att2 = get.sgn(get.attitude(player, ui.selected.targets[0])); + for (i = 0; i < es.length; i++) { + if (sgnatt != 0 && att2 != 0 && sgnatt != att2 && + get.sgn(get.value(es[i], ui.selected.targets[0])) == -att2 && + get.sgn(get.effect(target, es[i], player, target)) == sgnatt && + target.canEquip(es[i], _status.event.canReplace)) { + return Math.abs(att); + } + } + if (i == es.length && (_status.event.nojudge || !ui.selected.targets[0].countCards("j", function (card) { + if (!filterCard(card)) return false; + return target.canAddJudge(card); + }) || att2 <= 0)) { + return 0; + } + return -att * att2; + }); + next.set("multitarget", true); + next.set("targetprompt", _status.event.targetprompt || ["被移走", "移动目标"]); + next.set("prompt", event.prompt || "移动场上的一张牌"); + next.set("filter", event.filter); + next.set("sourceTargets", event.sourceTargets || game.filterPlayer()); + next.set("aimTargets", event.aimTargets || game.filterPlayer()); + next.set("canReplace", event.canReplace); + next.set("custom", get.copy(event.custom)); + if (event.prompt2) next.set("prompt2", event.prompt2); + if (event.forced) next.set("forced", true); + "step 1" + event.result = result; + if (result.bool) { + if (event.logSkill) player.logSkill(event.logSkill, result.targets, false); + player.line2(result.targets, "green"); + event.targets = result.targets; + } + else { + event.finish(); + } + "step 2" + game.delay(); + "step 3" + if (targets.length == 2) { + player.choosePlayerCard("ej", true, function (button) { + var player = _status.event.player; + var targets0 = _status.event.targets0; + var targets1 = _status.event.targets1; + if (get.attitude(player, targets0) > 0 && get.attitude(player, targets1) < 0) { + if (get.position(button.link) == "j") return 12; + if (get.value(button.link, targets0) < 0 && get.effect(targets1, button.link, player, targets1) > 0) return 10; + return 0; + } + else { + if (get.position(button.link) == "j") return -10; + return get.value(button.link) * get.effect(targets1, button.link, player, targets1); + } + }, targets[0]).set("nojudge", event.nojudge || false).set("targets0", targets[0]).set("targets1", targets[1]).set("filterButton", function (button) { + var targets1 = _status.event.targets1; + if (!get.event("filter")(button.link)) return false; + if (get.position(button.link) == "j") { + if (_status.event.nojudge) return false; + return targets1.canAddJudge(button.link); + } + else { + return targets1.canEquip(button.link, _status.event.canReplace); + } + }).set("filter", event.filter).set("canReplace", event.canReplace).set("custom", get.copy(event.custom)); + } + else { + event.finish(); + } + "step 4" + if (result.bool && result.links.length) { + var link = result.links[0]; + if (get.position(link) == "e") { + event.targets[1].equip(link); + } + else if (link.viewAs) { + event.targets[1].addJudge({ name: link.viewAs }, [link]); + } + else { + event.targets[1].addJudge(link); + } + event.targets[0].$give(link, event.targets[1], false); + game.log(event.targets[0], "的", link, "被移动给了", event.targets[1]) + event.result.card = link; + event.result.position = get.position(link); + game.delay(); + } + }, + useCard: function () { + "step 0" + if (!card) { + console.log("err: no card", get.translation(event.player)); + event.finish(); + return; + } + if (!get.info(card, false).noForceDie) event.forceDie = true; + if (cards.length) { + var owner = (get.owner(cards[0]) || player); + var next = owner.lose(cards, "visible", ui.ordering).set("type", "use"); + var directDiscard = []; + for (var i = 0; i < cards.length; i++) { + if (!next.cards.contains(cards[i])) { + directDiscard.push(cards[i]); + } + } + if (directDiscard.length) game.cardsGotoOrdering(directDiscard); + } + //player.using=cards; + var cardaudio = true; + if (event.skill) { + if (lib.skill[event.skill].audio) { + cardaudio = false; + } + if (lib.skill[event.skill].log != false) { + player.logSkill(event.skill); + } + if (get.info(event.skill).popname) { + player.tryCardAnimate(card, event.card.name, "metal", true); + } + } + else if (!event.nopopup) { + if (lib.translate[event.card.name + "_pop"]) { + player.tryCardAnimate(card, lib.translate[event.card.name + "_pop"], "metal"); + } + else { + player.tryCardAnimate(card, event.card.name, "metal"); + } + } + if (event.audio === false) { + cardaudio = false; + } + if (cardaudio) game.broadcastAll((player, card) => { + game.playCardAudio(card, player); + /* + if(!lib.config.background_audio||get.type(card)=="equip"&&!lib.config.equip_audio) return; + const sex=player.sex=="female"?"female":"male"; + var nature=get.natureList(card)[0]; + if(card.name=="sha"&&["fire","thunder","ice","stab"].includes(nature)){ + game.playAudio("card",sex,`${card.name}_${nature}`); + return; + } + const audio=lib.card[card.name].audio; + if(typeof audio=="string"){ + const audioInfo=audio.split(":"); + if(audio.startsWith("db:")) game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,audioInfo[2],`${card.name}_${sex}.${audioInfo[3]||"mp3"}`); + else if(audio.startsWith("ext:")) game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,`${card.name}_${sex}.${audioInfo[2]||"mp3"}`); + else game.playAudio("card",sex,`${audioInfo[0]}.${audioInfo[1]||"mp3"}`); + } + else game.playAudio("card",sex,card.name);*/ + }, player, card); + if (event.animate != false && event.line != false) { + if (card.name == "wuxie" && event.getParent()._info_map) { + var evtmap = event.getParent()._info_map; + if (evtmap._source) evtmap = evtmap._source; + var lining = (evtmap.multitarget ? evtmap.targets : evtmap.target) || event.player; + if (Array.isArray(lining) && event.getTrigger().name == "jiedao") { + player.line(lining[0], "green"); + } + else { + player.line(lining, "green"); + } + } + else if (card.name == "youdishenru" && event.getParent().source) { + var lining = event.getParent().sourcex || event.getParent().source2 || event.getParent().source; + if (lining == player && event.getParent().sourcex2) { + lining = event.getParent().sourcex2; + } + if (Array.isArray(lining) && event.getTrigger().name == "jiedao") { + player.line(lining[0], "green"); + } + else { + player.line(lining, "green"); + } + } + else { + var config = {}; + var nature = get.natureList(card)[0]; + if (nature || card.classList && card.classList.contains(nature)) config.color = nature; + if (event.addedTarget) { + player.line2(targets.concat(event.addedTargets), config); + } + else if (get.info(card, false).multitarget && targets.length > 1 && !get.info(card, false).multiline) { + player.line2(targets, config); + } + else { + player.line(targets, config); + } + } + if (event.throw !== false) player.$throw(cards); + if (lib.config.sync_speed && cards[0] && cards[0].clone) { + var waitingForTransition = get.time(); + event.waitingForTransition = waitingForTransition; + cards[0].clone.listenTransition(function () { + if (_status.waitingForTransition == waitingForTransition && _status.paused) { + game.resume(); + } + delete event.waitingForTransition; + }); + } + } + event.id = get.id(); + if (!Array.isArray(event.excluded)) event.excluded = []; + if (!Array.isArray(event.directHit)) event.directHit = []; + if (typeof event.customArgs != "object" || typeof event.customArgs.default != "object") event.customArgs = { default: {} }; + if (typeof event.baseDamage != "number") event.baseDamage = get.info(card, false).baseDamage || 1; + if (typeof event.effectCount != "number") event.effectCount = get.info(card, false).effectCount || 1; + event.effectedCount = 0; + if (event.oncard) { + event.oncard(event.card, event.player); + } + player.actionHistory[player.actionHistory.length - 1].useCard.push(event); + game.getGlobalHistory().useCard.push(event); + if (event.addCount !== false) { + if (player.stat[player.stat.length - 1].card[card.name] == undefined) { + player.stat[player.stat.length - 1].card[card.name] = 1; + } + else { + player.stat[player.stat.length - 1].card[card.name]++; + } + } + if (event.skill) { + if (player.stat[player.stat.length - 1].skill[event.skill] == undefined) { + player.stat[player.stat.length - 1].skill[event.skill] = 1; + } + else { + player.stat[player.stat.length - 1].skill[event.skill]++; + } + var sourceSkill = get.info(event.skill).sourceSkill; + if (sourceSkill) { + if (player.stat[player.stat.length - 1].skill[sourceSkill] == undefined) { + player.stat[player.stat.length - 1].skill[sourceSkill] = 1; + } + else { + player.stat[player.stat.length - 1].skill[sourceSkill]++; + } + } + } + if (targets.length) { + var str = (targets.length == 1 && targets[0] == player) ? "#b自己" : targets; + if (cards.length && !card.isCard) { + if (event.addedTarget) { + game.log(player, "对", str, "使用了", card, "(", cards, ",指向", event.addedTargets, ")"); + } + else { + game.log(player, "对", str, "使用了", card, "(", cards, ")"); + } + } + else { + if (event.addedTarget) { + game.log(player, "对", str, "使用了", card, "(指向", event.addedTargets, ")"); + } + else { + game.log(player, "对", str, "使用了", card); + } + } + } + else { + if (cards.length && !card.isCard) { + if (event.addedTarget) { + game.log(player, "使用了", card, "(", cards, ",指向", event.addedTargets, ")"); + } + else { + game.log(player, "使用了", card, "(", cards, ")"); + } + } + else { + if (event.addedTarget) { + game.log(player, "使用了", card, "(指向", event.addedTargets, ")"); + } + else { + game.log(player, "使用了", card); + } + } + } + if (card.name == "wuxie") { + game.logv(player, [card, cards], [event.getTrigger().card]); + } + else { + game.logv(player, [card, cards], targets); + } + event.trigger("useCard1"); + "step 1" + event.trigger("yingbian"); + "step 2" + event.trigger("useCard2"); + "step 3" + event.trigger("useCard"); + event._oncancel = function () { + game.broadcastAll(function (id) { + if (ui.tempnowuxie && ui.tempnowuxie._origin == id) { + ui.tempnowuxie.close(); + delete ui.tempnowuxie; + } + }, event.id); + }; + "step 4" + event.sortTarget = function (animate, sort) { + var info = get.info(card, false); + if (num == 0 && targets.length > 1) { + if (!info.multitarget) { + if (!event.fixedSeat && !sort) { + targets.sortBySeat((_status.currentPhase || player)); + } + if (animate) for (var i = 0; i < targets.length; i++) { + targets[i].animate("target"); + } + } + else if (animate) { + for (var i = 0; i < targets.length; i++) { + targets[i].animate("target"); + } + } + } + } + event.sortTarget(); + event.getTriggerTarget = function (list1, list2) { + var listx = list1.slice(0).sortBySeat((_status.currentPhase || player)); + for (var i = 0; i < listx.length; i++) { + if (get.numOf(list2, listx[i]) < get.numOf(listx, listx[i])) return listx[i]; + } + return null; + } + "step 5" + if (event.all_excluded) return; + if (!event.triggeredTargets1) event.triggeredTargets1 = []; + var target = event.getTriggerTarget(targets, event.triggeredTargets1); + if (target) { + event.triggeredTargets1.push(target); + var next = game.createEvent("useCardToPlayer", false); + if (!event.isFirstTarget1) { + event.isFirstTarget1 = true; + next.isFirstTarget = true; + } + next.setContent("emptyEvent"); + next.targets = targets; + next.target = target; + next.card = card; + next.cards = cards; + next.player = player; + next.skill = event.skill; + next.excluded = event.excluded; + next.directHit = event.directHit; + next.customArgs = event.customArgs; + if (event.forceDie) next.forceDie = true; + event.redo(); + } + "step 6" + if (event.all_excluded) return; + if (!event.triggeredTargets2) event.triggeredTargets2 = []; + var target = event.getTriggerTarget(targets, event.triggeredTargets2); + if (target) { + event.triggeredTargets2.push(target); + var next = game.createEvent("useCardToTarget", false); + if (!event.isFirstTarget2) { + event.isFirstTarget2 = true; + next.isFirstTarget = true; + } + next.setContent("emptyEvent"); + next.targets = targets; + next.target = target; + next.card = card; + next.cards = cards; + next.player = player; + next.skill = event.skill; + next.excluded = event.excluded; + next.directHit = event.directHit; + next.customArgs = event.customArgs; + if (event.forceDie) next.forceDie = true; + event.redo(); + } + "step 7" + var info = get.info(card, false); + if (!info.nodelay && event.animate != false) { + if (event.delayx !== false) { + if (event.waitingForTransition) { + _status.waitingForTransition = event.waitingForTransition; + game.pause(); + } + else { + game.delayx(); + } + } + } + "step 8" + if (event.all_excluded) return; + if (!event.triggeredTargets3) event.triggeredTargets3 = []; + var target = event.getTriggerTarget(targets, event.triggeredTargets3); + if (target) { + event.triggeredTargets3.push(target); + var next = game.createEvent("useCardToPlayered", false); + if (!event.isFirstTarget3) { + event.isFirstTarget3 = true; + next.isFirstTarget = true; + } + next.setContent("emptyEvent"); + next.targets = targets; + next.target = target; + next.card = card; + next.cards = cards; + next.player = player; + next.skill = event.skill; + next.excluded = event.excluded; + next.directHit = event.directHit; + next.customArgs = event.customArgs; + if (event.forceDie) next.forceDie = true; + event.redo(); + } + "step 9" + if (event.all_excluded) return; + if (!event.triggeredTargets4) event.triggeredTargets4 = []; + var target = event.getTriggerTarget(targets, event.triggeredTargets4); + if (target) { + event.triggeredTargets4.push(target); + var next = game.createEvent("useCardToTargeted", false); + if (!event.isFirstTarget4) { + event.isFirstTarget4 = true; + next.isFirstTarget = true; + } + next.setContent("emptyEvent"); + next.targets = targets; + next.target = target; + next.card = card; + next.cards = cards; + next.player = player; + next.skill = event.skill; + next.excluded = event.excluded; + next.directHit = event.directHit; + next.customArgs = event.customArgs; + if (event.forceDie) next.forceDie = true; + if (targets.length == event.triggeredTargets4.length) { + event.sortTarget(); + } + event.redo(); + } + "step 10" + if (event.all_excluded) return; + event.effectedCount++; + event.num = 0; + var info = get.info(card, false); + if (info.contentBefore) { + var next = game.createEvent(card.name + "ContentBefore"); + next.setContent(info.contentBefore); + next.targets = targets; + next.card = card; + next.cards = cards; + next.player = player; + next.skill = event.skill; + next.type = "precard"; + if (event.forceDie) next.forceDie = true; + } + else if (info.reverseOrder && get.is.versus() && targets.length > 1) { + var next = game.createEvent(card.name + "ContentBefore"); + next.setContent("reverseOrder"); + next.targets = targets; + next.card = card; + next.cards = cards; + next.player = player; + next.skill = event.skill; + next.type = "precard"; + if (event.forceDie) next.forceDie = true; + } + else if (info.singleCard && info.filterAddedTarget && event.addedTargets && event.addedTargets.length < targets.length) { + var next = game.createEvent(card.name + "ContentBefore"); + next.setContent("addExtraTarget"); + next.target = target; + next.targets = targets; + next.card = card; + next.cards = cards; + next.player = player; + next.skill = event.skill; + next.type = "precard"; + next.addedTarget = event.addedTarget; + next.addedTargets = event.addedTargets; + if (event.forceDie) next.forceDie = true; + } + "step 11" + if (event.all_excluded) return; + var info = get.info(card, false); + if (num == 0 && targets.length > 1) { + event.sortTarget(true, true); + } + if (targets[num] && targets[num].isDead()) return; + if (targets[num] && targets[num].isOut()) return; + if (targets[num] && targets[num].removed) return; + if (targets[num] && info.ignoreTarget && info.ignoreTarget(card, player, targets[num])) return; + if (targets.length == 0 && !info.notarget) return; + if (targets[num] && event.excluded.contains(targets[num])) { + var next = game.createEvent("useCardToExcluded", false); + next.setContent("emptyEvent"); + next.targets = targets; + next.target = targets[num]; + next.num = num; + next.card = card; + next.cards = cards; + next.player = player; + return; + } + var next = game.createEvent(card.name); + next.setContent(info.content); + next.targets = targets; + next.card = card; + next.cards = cards; + next.player = player; + next.num = num; + next.type = "card"; + next.skill = event.skill; + next.multitarget = info.multitarget; + next.preResult = event.preResult; + next.baseDamage = event.baseDamage; + if (event.forceDie) next.forceDie = true; + if (event.addedTargets) { + next.addedTargets = event.addedTargets; + next.addedTarget = event.addedTargets[num]; + next._targets = event._targets; + } + if (info.targetDelay === false) { + event.targetDelay = false; + } + next.target = targets[num]; + for (var i in event.customArgs.default) next[i] = event.customArgs.default[i]; + if (next.target && event.customArgs[next.target.playerid]) { + var customArgs = event.customArgs[next.target.playerid]; + for (var i in customArgs) next[i] = customArgs[i]; + } + if (next.target && event.directHit.contains(next.target)) next.directHit = true; + if (next.target && !info.multitarget) { + if (num == 0 && targets.length > 1) { + // var ttt=next.target; + // setTimeout(function(){ttt.animate("target");},0.5*lib.config.duration); + } + else { + next.target.animate("target"); + } + } + if (!info.nodelay && num > 0) { + if (event.targetDelay !== false) { + game.delayx(0.5); + } + } + "step 12" + if (event.all_excluded) return; + if (!get.info(event.card, false).multitarget && num < targets.length - 1 && !event.cancelled) { + event.num++; + event.goto(11); + } + "step 13" + if (event.all_excluded) return; + if (get.info(card, false).contentAfter) { + var next = game.createEvent(card.name + "ContentAfter"); + next.setContent(get.info(card, false).contentAfter); + next.targets = targets; + next.card = card; + next.cards = cards; + next.player = player; + next.skill = event.skill; + next.preResult = event.preResult; + next.type = "postcard"; + if (event.forceDie) next.forceDie = true; + } + "step 14" + if (event.all_excluded) return; + if (event.effectedCount < event.effectCount) { + if (document.getElementsByClassName("thrown").length) { + if (event.delayx !== false && get.info(event.card, false).finalDelay !== false) game.delayx(); + } + event.goto(10); + } + "step 15" + if (event.postAi) { + event.player.logAi(event.targets, event.card); + } + if (event._result) { + event.result = event._result; + } + //delete player.using; + if (document.getElementsByClassName("thrown").length) { + if (event.delayx !== false && get.info(event.card, false).finalDelay !== false) game.delayx(); + } + else { + event.finish(); + } + "step 16" + event._oncancel(); + }, + useSkill: function () { + "step 0" + var info = get.info(event.skill); + if (!info.noForceDie) event.forceDie = true; + if (!info.noForceOut) event.includeOut = true; + event._skill = event.skill; + game.trySkillAudio(event.skill, player); + var checkShow = player.checkShow(event.skill); + if (info.discard != false && info.lose != false && !info.viewAs) { + player.discard(cards).delay = false; + if (lib.config.low_performance) { + event.discardTransition = true; + } + } + else { + if (info.lose != false) { + if (info.losetrigger == false) { + var losecard = player.lose(cards, ui.special)._triggered = null; + } + else { + var losecard = player.lose(cards, ui.special); + if (info.visible) losecard.visible = true; + if (info.loseTo) losecard.position = ui[info.loseTo]; + if (info.insert) losecard.insert_card = true; + if (losecard.position == ui.special && info.toStorage) losecard.toStorage = true; + } + } + if (!info.prepare && info.viewAs) { + player.$throw(cards); + if (losecard) losecard.visible = true; + if (lib.config.sync_speed && cards[0] && cards[0].clone) { + var waitingForTransition = get.time(); + event.waitingForTransition = waitingForTransition; + cards[0].clone.listenTransition(function () { + if (_status.waitingForTransition == waitingForTransition && _status.paused) { + game.resume(); + } + delete event.waitingForTransition; + }); + } + } + } + if (info.line != false && targets.length) { + var config = {}; + if (get.is.object(info.line)) config = info.line; + else if (info.line == "fire") { + config.color = "fire"; + } + else if (info.line == "thunder") { + config.color = "thunder"; + } + else if (info.line === undefined || info.line == "green") { + config.color = "green"; + } + if (info.multitarget && !info.multiline && targets.length > 1) { + player.line2(targets, config); + } + else { + player.line(targets, config); + } + } + var str = ""; + if (targets && targets.length && info.log != "notarget") { + str += `对${targets[0] == player ? "自己" : get.translation(targets[0])}`; + for (var i = 1; i < targets.length; i++) { + str += "、" + (targets[i] == player ? "自己" : get.translation(targets[i])); + } + str += "" + } + str += "发动了"; + if (!info.direct && info.log !== false) { + game.log(player, str, "【" + get.skillTranslation(skill, player) + "】"); + if (info.logv !== false) game.logv(player, skill, targets); + player.trySkillAnimate(skill, skill, checkShow); + } + if (event.addCount != false) { + if (player.stat[player.stat.length - 1].skill[skill] == undefined) { + player.stat[player.stat.length - 1].skill[skill] = 1; + } + else { + player.stat[player.stat.length - 1].skill[skill]++; + } + var sourceSkill = get.info(skill).sourceSkill; + if (sourceSkill) { + if (player.stat[player.stat.length - 1].skill[sourceSkill] == undefined) { + player.stat[player.stat.length - 1].skill[sourceSkill] = 1; + } + else { + player.stat[player.stat.length - 1].skill[sourceSkill]++; + } + } + } + if (player.stat[player.stat.length - 1].allSkills == undefined) { + player.stat[player.stat.length - 1].allSkills = 1; + } + else { + player.stat[player.stat.length - 1].allSkills++; + } + if (info.prepare) { + switch (info.prepare) { + case "give": if (losecard) losecard.visible = true; player.$give(cards, targets[0]); break; + case "give2": player.$give(cards.length, targets[0]); break; + case "throw": if (losecard) losecard.visible = true; player.$throw(cards); break; + case "throw2": player.$throw(cards.length); break; + default: info.prepare(cards, player, targets); + } + } + if (info.round) { + var roundname = skill + "_roundcount"; + player.storage[roundname] = game.roundNumber; + player.syncStorage(roundname); + player.markSkill(roundname); + } + var name = event.skill; + var players = player.getSkills(false, false, false); + var equips = player.getSkills("e"); + var global = lib.skill.global.slice(0); + var logInfo = { + skill: name, + targets: targets, + event: _status.event, + }; + if (info.sourceSkill) { + logInfo.sourceSkill = info.sourceSkill; + if (global.contains(info.sourceSkill)) { + logInfo.type = "global"; + } + else if (players.contains(info.sourceSkill)) { + logInfo.type = "player"; + } + else if (equips.contains(info.sourceSkill)) { + logInfo.type = "equip"; + } + } + else { + if (global.contains(name)) { + logInfo.sourceSkill = name; + logInfo.type = "global"; + } + else if (players.contains(name)) { + logInfo.sourceSkill = name; + logInfo.type = "player"; + } + else if (equips.contains(name)) { + logInfo.sourceSkill = name; + logInfo.type = "equip"; + } + else { + var bool = false; + for (var i of players) { + var expand = [i]; + game.expandSkills(expand); + if (expand.contains(name)) { + bool = true; + logInfo.sourceSkill = i; + logInfo.type = "player"; + break; + } + } + if (!bool) { + for (var i of players) { + var expand = [i]; + game.expandSkills(expand); + if (expand.contains(name)) { + logInfo.sourceSkill = i; + logInfo.type = "equip"; + break; + } + } + } + } + } + event.sourceSkill = logInfo.sourceSkill; + event.type = logInfo.type; + player.getHistory("useSkill").push(logInfo); + event.trigger("useSkill"); + "step 1" + var info = get.info(event.skill); + if (info && info.contentBefore) { + var next = game.createEvent(event.skill + "ContentBefore"); + next.setContent(info.contentBefore); + next.targets = targets; + next.cards = cards; + next.player = player; + if (event.forceDie) next.forceDie = true; + if (event.includeOut) next.includeOut = true; + } + "step 2" + if (!event.skill) { + console.log("error: no skill", get.translation(event.player), event.player.getSkills()); + if (event._skill) { + event.skill = event._skill; + console.log(event._skill); + } + else { + event.finish(); + return; + } + } + var info = get.info(event.skill); + if (targets[num] && targets[num].isDead() || + targets[num] && targets[num].isOut() || + targets[num] && targets[num].removed) { + if (!info.multitarget && num < targets.length - 1) { + event.num++; + event.redo(); + } + return; + } + var next = game.createEvent(event.skill); + next.setContent(info.content); + next.targets = targets; + next.cards = cards; + next.player = player; + next.num = num; + next.multitarget = info.multitarget; + if (num == 0 && next.targets.length > 1) { + if (!info.multitarget) { + lib.tempSortSeat = player; + targets.sort(lib.sort.seat); + delete lib.tempSortSeat; + } + for (var i = 0; i < targets.length; i++) { + targets[i].animate("target"); + } + } + next.target = targets[num]; + if (event.forceDie) next.forceDie = true; + if (event.includeOut) next.includeOut = true; + if (next.target && !info.multitarget) { + if (num == 0 && targets.length > 1) { + // var ttt=next.target; + // setTimeout(function(){ttt.animate("target");},0.5*lib.config.duration); + } + else { + next.target.animate("target"); + } + } + if (num == 0) { + if (typeof info.delay == "number") game.delay(info.delay); + else if (info.delay !== false && info.delay !== 0) { + if (event.waitingForTransition) { + _status.waitingForTransition = event.waitingForTransition; + game.pause(); + } + else { + game.delayx() + } + } + } + else game.delayx(0.5); + if (!info.multitarget && num < targets.length - 1) { + event.num++; + event.redo(); + } + "step 3" + var info = get.info(event.skill); + if (info && info.contentAfter) { + var next = game.createEvent(event.skill + "ContentAfter"); + next.setContent(info.contentAfter); + next.targets = targets; + next.cards = cards; + next.player = player; + if (event.forceDie) next.forceDie = true; + if (event.includeOut) next.includeOut = true; + } + "step 4" + if (player.getStat().allSkills > 200) { + player._noSkill = true; + console.log(player.name, event.skill); + } + if (document.getElementsByClassName("thrown").length) { + if (event.skill && get.info(event.skill).delay !== false && get.info(event.skill).delay !== 0) game.delayx(); + } + else { + event.finish(); + } + "step 5" + ui.clear(); + }, + draw: function () { + // if(lib.config.background_audio){ + // game.playAudio("effect","draw"); + // } + // game.broadcast(function(){ + // if(lib.config.background_audio){ + // game.playAudio("effect","draw"); + // } + // }); + if (typeof event.minnum == "number" && num < event.minnum) { + num = event.minnum; + } + if (event.drawDeck) { + if (event.drawDeck > num) { + event.drawDeck = num; + } + num -= event.drawDeck; + } + if (event.log != false) { + if (num > 0) { + if (event.bottom) game.log(player, "从牌堆底摸了" + get.cnNumber(num) + "张牌"); + else game.log(player, "摸了" + get.cnNumber(num) + "张牌"); + } + if (event.drawDeck) { + game.log(player, "从牌库中获得了" + get.cnNumber(event.drawDeck) + "张牌"); + } + } + var cards; + if (num > 0) { + if (event.bottom) cards = get.bottomCards(num); + else if (player.getTopCards) cards = player.getTopCards(num); + else cards = get.cards(num); + } + else { + cards = []; + } + if (event.drawDeck) { + cards = cards.concat(player.getDeckCards(event.drawDeck)); + } + if (event.animate != false) { + if (event.visible) { + var next = player.gain(cards, "gain2"); + if (event.bottom) game.log(player, "从牌堆底摸了" + get.cnNumber(num) + "张牌(", cards, ")"); + else game.log(player, "摸了" + get.cnNumber(num) + "张牌(", cards, ")"); + } + else { + var next = player.gain(cards, "draw"); + } + } + else { + var next = player.gain(cards); + if (event.$draw) { + player.$draw(cards.length); + } + } + if (event.gaintag) next.gaintag.addArray(event.gaintag); + event.result = cards; + }, + discard: function () { + "step 0" + game.log(player, "弃置了", cards); + event.done = player.lose(cards, event.position, "visible"); + event.done.type = "discard"; + if (event.discarder) event.done.discarder = event.discarder; + "step 1" + event.trigger("discard"); + }, + loseToDiscardpile: function () { + "step 0" + if (event.log != false) game.log(player, "将", cards, "置入了弃牌堆"); + var next = player.lose(cards, event.position); + if (event.insert_index) next.insert_index = event.insert_index; + if (event.insert_card) next.insert_card = true; + if (!event.blank) next.visible = true; + next.type = "loseToDiscardpile"; + event.done = next; + "step 1" + event.trigger("loseToDiscardpile"); + }, + respond: function () { + "step 0" + var cardaudio = true; + if (event.skill) { + if (lib.skill[event.skill].audio) { + cardaudio = false; + } + player.logSkill(event.skill); + player.checkShow(event.skill, true); + if (lib.skill[event.skill].onrespond && !game.online) { + lib.skill[event.skill].onrespond(event, player); + } + } + else if (!event.nopopup) player.tryCardAnimate(card, card.name, "wood"); + if (cardaudio && event.getParent(3).name == "useCard") game.broadcastAll((player, card) => { + game.playCardAudio(card, player); + /* + if(!lib.config.background_audio) return; + const sex=player.sex=="female"?"female":"male",audio=lib.card[card.name].audio; + if(typeof audio=="string"){ + const audioInfo=audio.split(":"); + if(audio.startsWith("db:")) game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,audioInfo[2],`${card.name}_${sex}.${audioInfo[3]||"mp3"}`); + else if(audio.startsWith("ext:")) game.playAudio(`${audioInfo[0]}:${audioInfo[1]}`,`${card.name}_${sex}.${audioInfo[2]||"mp3"}`); + else game.playAudio("card",sex,`${audioInfo[0]}.${audioInfo[1]||"mp3"}`); + } + else game.playAudio("card",sex,card.name);*/ + }, player, card); + if (event.skill) { + if (player.stat[player.stat.length - 1].skill[event.skill] == undefined) { + player.stat[player.stat.length - 1].skill[event.skill] = 1; + } + else { + player.stat[player.stat.length - 1].skill[event.skill]++; + } + var sourceSkill = get.info(event.skill).sourceSkill; + if (sourceSkill) { + if (player.stat[player.stat.length - 1].skill[sourceSkill] == undefined) { + player.stat[player.stat.length - 1].skill[sourceSkill] = 1; + } + else { + player.stat[player.stat.length - 1].skill[sourceSkill]++; + } + } + } + if (cards.length && (cards.length > 1 || cards[0].name != card.name)) { + game.log(player, "打出了", card, "(", cards, ")"); + } + else { + game.log(player, "打出了", card); + } + player.actionHistory[player.actionHistory.length - 1].respond.push(event); + if (cards.length) { + var owner = (get.owner(cards[0]) || player); + var next = owner.lose(cards, "visible", ui.ordering).set("type", "use"); + var directDiscard = []; + for (var i = 0; i < cards.length; i++) { + if (!next.cards.contains(cards[i])) { + directDiscard.push(cards[i]); + } + } + if (directDiscard.length) game.cardsGotoOrdering(directDiscard); + } + if (event.animate != false && event.throw !== false) { + for (var i = 0; i < cards.length; i++) { + player.$throw(cards[i]); + if (event.highlight) { + cards[i].clone.classList.add("thrownhighlight"); + game.addVideo("highlightnode", player, get.cardInfo(cards[i])); + } + } + if (event.highlight) { + game.broadcast(function (cards) { + for (var i = 0; i < cards.length; i++) { + if (cards[i].clone) { + cards[i].clone.classList.add("thrownhighlight"); + } + } + }, cards); + } + } + event.trigger("respond"); + "step 1" + game.delayx(0.5); + }, + swapHandcards: function () { + "step 0" + event.cards1 = event.cards1 || player.getCards("h"); + event.cards2 = event.cards2 || target.getCards("h"); + game.loseAsync({ + player: player, + target: target, + cards1: event.cards1, + cards2: event.cards2, + }).setContent("swapHandcardsx"); + "step 1" + game.loseAsync({ + gain_list: [ + [player, event.cards2.filterInD()], + [target, event.cards1.filterInD()] + ], + }).setContent("gaincardMultiple"); + "step 2" + game.delayx(); + }, + swapHandcardsx: function () { + "step 0" + player.$giveAuto(event.cards1, target); + target.$giveAuto(event.cards2, player); + "step 1" + event.cards = event.cards1; + var next = player.lose(event.cards, ui.ordering); + next.getlx = false; + next.relatedEvent = event.getParent(); + if (player == game.me) { + event.delayed = true; + } + else { + next.delay = false; + } + "step 2" + event.cards = event.cards2; + var next = target.lose(event.cards, ui.ordering); + next.getlx = false; + next.relatedEvent = event.getParent(); + if (target == game.me) { + event.delayed = true; + } + else { + next.delay = false; + } + "step 3" + if (!event.delayed) game.delay(); + }, + gainMultiple: function () { + "step 0" + event.delayed = false; + event.num = 0; + event.cards = []; + "step 1" + player.gainPlayerCard(targets[num], event.position, true).set("boolline", false).set("delay", num == targets.length - 1); + "step 2" + if (result.bool) { + event.cards.addArray(result.cards); + if (num == targets.length - 1) event.delayed = true; + } + event.num++; + if (event.num < targets.length) { + event.goto(1); + } + "step 3" + if (!event.delayed) game.delay(); + }, + gain: function () { + "step 0" + if (event.animate == "give") event.visible = true; + if (cards) { + var map = {}; + for (var i of cards) { + var owner = get.owner(i, "judge"); + if (owner && (owner != player || get.position(i) != "h")) { + var id = owner.playerid; + if (!map[id]) map[id] = [[], [], []]; + map[id][0].push(i); + var position = get.position(i); + if (position == "h") map[id][1].push(i); + else map[id][2].push(i); + } + else if (!event.updatePile && get.position(i) == "c") event.updatePile = true; + } + event.losing_map = map; + for (var i in map) { + var owner = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + var next = owner.lose(map[i][0], ui.special).set("type", "gain").set("forceDie", true).set("getlx", false); + if (event.visible == true) { + next.visible = true; + } + event.relatedLose = next; + } + } + else { + event.finish(); + } + "step 1" + for (var i = 0; i < cards.length; i++) { + if (cards[i].willBeDestroyed("handcard", player, event)) { + cards[i].selfDestroy(event); + cards.splice(i--, 1); + } + else if (event.losing_map) { + for (var id in event.losing_map) { + if (event.losing_map[id][0].contains(cards[i])) { + var source = (_status.connectMode ? lib.playerOL : game.playerMap)[id]; + var hs = source.getCards("hejsx"); + if (hs.contains(cards[i])) { + cards.splice(i--, 1); + } else { + cards[i].addKnower(event.visible ? "everyone" : source); + } + } + } + } + } + if (cards.length == 0) { + event.finish(); + return; + } + player.getHistory("gain").push(event); + //if(event.source&&event.delay!==false) game.delayx(); + "step 2" + if (player.getStat().gain == undefined) { + player.getStat().gain = cards.length; + } + else { + player.getStat().gain += cards.length; + } + "step 3" + var sort; + var frag1 = document.createDocumentFragment(); + var frag2 = document.createDocumentFragment(); + var hs = player.getCards("hs"); + for (var i = 0; i < cards.length; i++) { + if (hs.contains(cards[i])) { + cards.splice(i--, 1); + } + } + for (var num = 0; num < cards.length; num++) { + sort = lib.config.sort_card(cards[num]); + if (lib.config.reverse_sort) sort = -sort; + if (["o", "d"].contains(get.position(cards[num], true))) { + cards[num].addKnower("everyone"); + } + cards[num].fix(); + cards[num].style.transform = ""; + cards[num].addGaintag(event.gaintag); + if (event.knowers) { + cards[num].addKnower(event.knowers);//添加事件设定的知情者。 + } + if (_status.discarded) { + _status.discarded.remove(cards[num]); + } + // cards[num].vanishtag.length=0; + for (var num2 = 0; num2 < cards[num].vanishtag.length; num2++) { + if (cards[num].vanishtag[num2][0] != "_") { + cards[num].vanishtag.splice(num2--, 1); + } + } + if (player == game.me) { + cards[num].classList.add("drawinghidden"); + } + if (get.is.singleHandcard() || sort > 1) frag1.appendChild(cards[num]); + else frag2.appendChild(cards[num]); + } + var addv = function () { + if (player == game.me) { + game.addVideo("gain12", player, [get.cardsInfo(frag1.childNodes), get.cardsInfo(frag2.childNodes), event.gaintag]); + } + }; + var broadcast = function () { + game.broadcast(function (player, cards, num, gaintag) { + player.directgain(cards, null, gaintag); + _status.cardPileNum = num; + }, player, cards, ui.cardPile.childNodes.length, event.gaintag); + }; + if (event.animate == "draw") { + player.$draw(cards.length); + game.pause(); + setTimeout(function () { + addv(); + player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); + player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); + player.update(); + if (player == game.me) ui.updatehl(); + broadcast(); + game.resume(); + }, get.delayx(500, 500)); + } + else if (event.animate == "gain") { + player.$gain(cards, event.log); + game.pause(); + setTimeout(function () { + addv(); + player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); + player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); + player.update(); + if (player == game.me) ui.updatehl(); + broadcast(); + game.resume(); + }, get.delayx(700, 700)); + } + else if (event.animate == "gain2" || event.animate == "draw2") { + var gain2t = 300; + if (player.$gain2(cards, event.log) && player == game.me) { + gain2t = 500; + } + game.pause(); + setTimeout(function () { + addv(); + player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); + player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); + player.update(); + if (player == game.me) ui.updatehl(); + broadcast(); + game.resume(); + }, get.delayx(gain2t, gain2t)); + } + else if (event.animate == "give" || event.animate == "giveAuto") { + var evtmap = event.losing_map; + if (event.animate == "give") { + for (var i in evtmap) { + var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + source.$give(evtmap[i][0], player, event.log) + } + } + else { + for (var i in evtmap) { + var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + if (evtmap[i][1].length) source.$giveAuto(evtmap[i][1], player, event.log); + if (evtmap[i][2].length) source.$give(evtmap[i][2], player, event.log); + } + } + game.pause(); + setTimeout(function () { + addv(); + player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); + player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); + player.update(); + if (player == game.me) ui.updatehl(); + broadcast(); + game.resume(); + }, get.delayx(500, 500)); + } + else if (typeof event.animate == "function") { + var time = event.animate(event); + game.pause(); + setTimeout(function () { + addv(); + player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); + player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); + player.update(); + if (player == game.me) ui.updatehl(); + broadcast(); + game.resume(); + }, get.delayx(time, time)); + } + else { + addv(); + player.node.handcards1.insertBefore(frag1, player.node.handcards1.firstChild); + player.node.handcards2.insertBefore(frag2, player.node.handcards2.firstChild); + player.update(); + if (player == game.me) ui.updatehl(); + broadcast(); + event.finish(); + } + "step 4" + game.delayx(); + if (event.updatePile) game.updateRoundNumber(); + }, + addToExpansion: function () { + "step 0" + if (event.animate == "give") event.visible = true; + if (cards) { + var map = {}; + for (var i of cards) { + var owner = get.owner(i, "judge"); + if (owner && (owner != player || get.position(i) != "x")) { + var id = owner.playerid; + if (!map[id]) map[id] = [[], [], []]; + map[id][0].push(i); + var position = get.position(i); + if (position == "h") map[id][1].push(i); + else map[id][2].push(i); + } + else if (!event.updatePile && get.position(i) == "c") event.updatePile = true; + } + event.losing_map = map; + for (var i in map) { + var owner = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + var next = owner.lose(map[i][0], ui.special).set("type", "loseToExpansion").set("forceDie", true).set("getlx", false); + if (event.visible == true) next.visible = true; + event.relatedLose = next; + } + } + else { + event.finish(); + } + "step 1" + for (var i = 0; i < cards.length; i++) { + if (cards[i].willBeDestroyed("expansion", player, event)) { + cards[i].selfDestroy(event); + cards.splice(i--, 1); + } + else if (event.losing_map) { + for (var id in event.losing_map) { + if (event.losing_map[id][0].contains(cards[i])) { + var source = (_status.connectMode ? lib.playerOL : game.playerMap)[id]; + var hs = source.getCards("hejsx"); + if (hs.contains(cards[i])) { + cards.splice(i--, 1); + } + } + } + } + } + if (cards.length == 0) { + event.finish(); + return; + } + "step 2" + var hs = player.getCards("x"); + for (var i = 0; i < cards.length; i++) { + if (hs.contains(cards[i])) { + cards.splice(i--, 1); + } + } + for (var num = 0; num < cards.length; num++) { + if (_status.discarded) { + _status.discarded.remove(cards[num]); + } + for (var num2 = 0; num2 < cards[num].vanishtag.length; num2++) { + if (cards[num].vanishtag[num2][0] != "_") { + cards[num].vanishtag.splice(num2--, 1); + } + } + } + if (event.animate == "draw") { + player.$draw(cards.length); + if (event.log) game.log(player, "将", get.cnNumber(cards.length), "张牌置于了武将牌上"); + game.pause(); + setTimeout(function () { + player.$addToExpansion(cards, null, event.gaintag); + for (var i of event.gaintag) player.markSkill(i); + game.resume(); + }, get.delayx(500, 500)); + } + else if (event.animate == "gain") { + player.$gain(cards, false); + game.pause(); + setTimeout(function () { + player.$addToExpansion(cards, null, event.gaintag); + for (var i of event.gaintag) player.markSkill(i); + game.resume(); + }, get.delayx(700, 700)); + } + else if (event.animate == "gain2" || event.animate == "draw2") { + var gain2t = 300; + if (player.$gain2(cards) && player == game.me) { + gain2t = 500; + } + game.pause(); + setTimeout(function () { + player.$addToExpansion(cards, null, event.gaintag); + for (var i of event.gaintag) player.markSkill(i); + game.resume(); + }, get.delayx(gain2t, gain2t)); + } + else if (event.animate == "give" || event.animate == "giveAuto") { + var evtmap = event.losing_map; + if (event.animate == "give") { + for (var i in evtmap) { + var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + source.$give(evtmap[i][0], player, false); + if (event.log) game.log(player, "将", evtmap[i][0], "置于了武将牌上"); + } + } + else { + for (var i in evtmap) { + var source = (_status.connectMode ? lib.playerOL : game.playerMap)[i]; + if (evtmap[i][1].length) { + source.$giveAuto(evtmap[i][1], player, false); + if (event.log) game.log(player, "将", get.cnNumber(evtmap[i][1].length), "张牌置于了武将牌上"); + } + if (evtmap[i][2].length) { + source.$give(evtmap[i][2], player, false); + if (event.log) game.log(player, "将", evtmap[i][2], "置于了武将牌上"); + } + } + } + game.pause(); + setTimeout(function () { + player.$addToExpansion(cards, null, event.gaintag); + for (var i of event.gaintag) player.markSkill(i); + game.resume(); + }, get.delayx(500, 500)); + } + else if (typeof event.animate == "function") { + var time = event.animate(event); + game.pause(); + setTimeout(function () { + player.$addToExpansion(cards, null, event.gaintag); + for (var i of event.gaintag) player.markSkill(i); + game.resume(); + }, get.delayx(time, time)); + } + else { + player.$addToExpansion(cards, null, event.gaintag); + for (var i of event.gaintag) player.markSkill(i); + event.finish(); + } + "step 4" + game.delayx(); + if (event.updatePile) game.updateRoundNumber(); + }, + lose: function () { + "step 0" + var evt = event.getParent(); + if ((evt.name != "discard" || event.type != "discard") && (evt.name != "loseToDiscardpile" || event.type != "loseToDiscardpile")) { + event.delay = false; + return; + } + if (evt.delay === false) event.delay = false; + if (evt.animate != false) { + evt.discardid = lib.status.videoId++; + game.broadcastAll(function (player, cards, id, visible) { + player.$throw(cards, null, "nobroadcast"); + var cardnodes = []; + cardnodes._discardtime = get.time(); + for (var i = 0; i < cards.length; i++) { + if (cards[i].clone) { + cardnodes.push(cards[i].clone); + if (!visible) { + cards[i].clone.classList.add("infohidden"); + cards[i].clone.classList.add("infoflip"); + } + } + } + ui.todiscard[id] = cardnodes; + }, player, cards, evt.discardid, event.visible); + if (lib.config.sync_speed && cards[0] && cards[0].clone) { + if (evt.delay != false) { + var waitingForTransition = get.time(); + evt.waitingForTransition = waitingForTransition; + cards[0].clone.listenTransition(function () { + if (_status.waitingForTransition == waitingForTransition && _status.paused) { + game.resume(); + } + delete evt.waitingForTransition; + }); + } + else if (evt.getParent().discardTransition) { + delete evt.getParent().discardTransition; + var waitingForTransition = get.time(); + evt.getParent().waitingForTransition = waitingForTransition; + cards[0].clone.listenTransition(function () { + if (_status.waitingForTransition == waitingForTransition && _status.paused) { + game.resume(); + } + delete evt.getParent().waitingForTransition; + }); + } + } + } + "step 1" + event.gaintag_map = {}; + var hs = [], es = [], js = [], ss = [], xs = []; + var unmarks = []; + if (event.insert_card && event.position == ui.cardPile) event.cards.reverse(); + var hej = player.getCards("hejsx"); + event.stockcards = cards.slice(0); + for (var i = 0; i < cards.length; i++) { + if (!hej.contains(cards[i])) { + cards.splice(i--, 1); + continue; + } + else if (cards[i].parentNode) { + if (cards[i].parentNode.classList.contains("equips")) { + cards[i].original = "e"; + es.push(cards[i]); + } + else if (cards[i].parentNode.classList.contains("judges")) { + cards[i].original = "j"; + js.push(cards[i]); + } + else if (cards[i].parentNode.classList.contains("expansions")) { + cards[i].original = "x"; + xs.push(cards[i]); + if (cards[i].gaintag && cards[i].gaintag.length) unmarks.addArray(cards[i].gaintag); + } + else if (cards[i].parentNode.classList.contains("handcards")) { + if (cards[i].classList.contains("glows")) { + cards[i].original = "s"; + ss.push(cards[i]); + } + else { + cards[i].original = "h"; + hs.push(cards[i]); + } + } + else { + cards[i].original = null; + } + } + if (cards[i].gaintag && cards[i].gaintag.length) { + event.gaintag_map[cards[i].cardid] = cards[i].gaintag.slice(0); + cards[i].removeGaintag(true); + } + + cards[i].style.transform += " scale(0.2)"; + cards[i].classList.remove("glow"); + cards[i].classList.remove("glows"); + cards[i].recheck(); + + var info = lib.card[cards[i].name]; + if (Object.prototype.hasOwnProperty.call(cards[i], "_destroy")) { + if (cards[i]._destroy) { + cards[i].delete(); + cards[i].destroyed = cards[i]._destroy; + continue; + } + } + else if (Object.prototype.hasOwnProperty.call(cards[i], "destroyed")) { + if (event.getlx !== false && event.position && cards[i].willBeDestroyed(event.position.id, null, event)) { + cards[i].selfDestroy(event); + continue; + } + } + else if (info.destroy) { + cards[i].delete(); + cards[i].destroyed = info.destroy; + continue; + } + if (event.position) { + if (_status.discarded) { + if (event.position == ui.discardPile) { + _status.discarded.add(cards[i]); + } + else { + _status.discarded.remove(cards[i]); + } + } + if (event.insert_index) { + cards[i].fix(); + event.position.insertBefore(cards[i], event.insert_index(event, cards[i])); + } + else if (event.insert_card) { + cards[i].fix(); + event.position.insertBefore(cards[i], event.position.firstChild); + } + else if (event.position == ui.cardPile) { + cards[i].fix(); + event.position.appendChild(cards[i]); + } + else cards[i].goto(event.position); + } + else { + cards[i].remove(); + } + //if(ss.contains(cards[i])) cards.splice(i--,1); + } + if (player == game.me) ui.updatehl(); + ui.updatej(player); + game.broadcast(function (player, cards, num) { + for (var i = 0; i < cards.length; i++) { + cards[i].classList.remove("glow"); + cards[i].classList.remove("glows"); + cards[i].fix(); + cards[i].remove(); + } + if (player == game.me) { + ui.updatehl(); + } + ui.updatej(player); + _status.cardPileNum = num; + }, player, cards, ui.cardPile.childNodes.length); + game.addVideo("lose", player, [get.cardsInfo(hs), get.cardsInfo(es), get.cardsInfo(js), get.cardsInfo(ss)]); + event.cards2 = hs.concat(es); + player.getHistory("lose").push(event); + game.getGlobalHistory().cardMove.push(event); + player.update(); + game.addVideo("loseAfter", player); + event.num = 0; + if (event.position == ui.ordering) { + var evt = event.relatedEvent || event.getParent(); + if (!evt.orderingCards) evt.orderingCards = []; + if (!evt.noOrdering && !evt.cardsOrdered) { + evt.cardsOrdered = true; + var next = game.createEvent("orderingDiscard", false, evt.getParent()); + next.relatedEvent = evt; + next.setContent("orderingDiscard"); + } + if (!evt.noOrdering) { + evt.orderingCards.addArray(cards); + } + } + else if (event.position == ui.cardPile) { + game.updateRoundNumber(); + } + if (unmarks.length) { + for (var i of unmarks) { + player[(lib.skill[i] && lib.skill[i].mark || player.hasCard((card) => card.hasGaintag(i), "x")) ? "markSkill" : "unmarkSkill"](i); + } + } + event.hs = hs; + event.es = es; + event.js = js; + event.ss = ss; + event.xs = xs; + game.clearCardKnowers(hs); + if (hs.length && !event.visible) { + player.getCards("h").forEach(hcard => { hcard.clearKnowers(); }); + } + "step 2" + if (num < cards.length) { + if (event.es.contains(cards[num])) { + event.loseEquip = true; + player.removeEquipTrigger(cards[num]); + var info = get.info(cards[num]); + if (info.onLose && (!info.filterLose || info.filterLose(cards[num], player))) { + event.goto(3); + return; + } + } + event.num++; + event.redo(); + } + else { + if (event.loseEquip) { + player.addEquipTrigger(); + } + event.goto(4); + } + "step 3" + var info = get.info(cards[num]); + if (info.loseDelay != false && (player.isAlive() || info.forceDie)) { + player.popup(cards[num].name); + game.delayx(); + } + if (Array.isArray(info.onLose)) { + for (var i = 0; i < info.onLose.length; i++) { + var next = game.createEvent("lose_" + cards[num].name); + next.setContent(info.onLose[i]); + if (info.forceDie) next.forceDie = true; + next.player = player; + next.card = cards[num]; + } + } + else { + var next = game.createEvent("lose_" + cards[num].name); + next.setContent(info.onLose); + next.player = player; + if (info.forceDie) next.forceDie = true; + next.card = cards[num]; + } + event.num++; + event.goto(2); + "step 4" + if (event.toRenku) { + _status.renku.addArray(cards.filter(function (card) { + return !card.willBeDestroyed("renku", null, event); + })); + if (_status.renku.length > 6) { + var cards = _status.renku.splice(0, _status.renku.length - 6); + game.log(cards, "从仁库进入了弃牌堆"); + game.cardsDiscard(cards).set("outRange", true).fromRenku = true; + } + game.updateRenku(); + } + "step 5" + var evt = event.getParent(); + if ((evt.name != "discard" && event.type != "discard") && (evt.name != "loseToDiscardpile" && event.type != "loseToDiscardpile")) return; + if (event.animate === false || event.delay === false) return; + if (evt.delay != false) { + if (evt.waitingForTransition) { + _status.waitingForTransition = evt.waitingForTransition; + game.pause(); + } + else { + game.delayx(); + } + } + }, + damage: function () { + "step 0" + event.forceDie = true; + if (event.unreal) { event.goto(4); return; } + event.trigger("damageBegin1"); + "step 1" + event.trigger("damageBegin2"); + "step 2" + event.trigger("damageBegin3"); + "step 3" + event.trigger("damageBegin4"); + "step 4" + //moved changeHujia to changeHp + if (player.hujia > 0 && !player.hasSkillTag("nohujia")) { + var damageAudioInfo = lib.natureAudio.hujia_damage[event.nature]; + if (!damageAudioInfo || damageAudioInfo == "normal") { + damageAudioInfo = "effect/hujia_damage" + (num > 1 ? "2" : "") + ".mp3"; + } else if (damageAudioInfo == "default") { + damageAudioInfo = "effect/hujia_damage_" + event.nature + (num > 1 ? "2" : "") + ".mp3"; + } else { + damageAudioInfo = damageAudioInfo[num > 1 ? 2 : 1]; + } + game.broadcastAll(function (damageAudioInfo) { + if (lib.config.background_audio) game.playAudio(damageAudioInfo); + }, damageAudioInfo); + } else { + var damageAudioInfo = lib.natureAudio.damage[event.nature]; + if (!damageAudioInfo || damageAudioInfo == "normal") { + damageAudioInfo = "effect/damage" + (num > 1 ? "2" : "") + ".mp3"; + } else if (damageAudioInfo == "default") { + damageAudioInfo = "effect/damage_" + event.nature + (num > 1 ? "2" : "") + ".mp3"; + } else { + damageAudioInfo = damageAudioInfo[num > 1 ? 2 : 1]; + } + game.broadcastAll(function (damageAudioInfo) { + if (lib.config.background_audio) game.playAudio(damageAudioInfo); + }, damageAudioInfo); + } + var str = event.unreal ? "视为受到了" : "受到了"; + if (source) str += `来自${source == player ? "自己" : get.translation(source)}的`; + str += get.cnNumber(num) + "点"; + if (event.nature) str += get.translation(event.nature) + "属性"; + str += "伤害"; + game.log(player, str); + if (player.stat[player.stat.length - 1].damaged == undefined) { + player.stat[player.stat.length - 1].damaged = num; + } + else { + player.stat[player.stat.length - 1].damaged += num; + } + if (source) { + source.getHistory("sourceDamage").push(event); + if (source.stat[source.stat.length - 1].damage == undefined) { + source.stat[source.stat.length - 1].damage = num; + } + else { + source.stat[source.stat.length - 1].damage += num; + } + } + player.getHistory("damage").push(event); + if (!event.unreal) { + if (event.notrigger) { + player.changeHp(-num, false)._triggered = null; + } + else { + player.changeHp(-num, false); + } + } + if (event.animate !== false) { + player.$damage(source); + var natures = (event.nature || "").split(lib.natureSeparator); + game.broadcastAll(function (natures, player) { + if (lib.config.animation && !lib.config.low_performance) { + if (natures.includes("fire")) { + player.$fire(); + } + if (natures.includes("thunder")) { + player.$thunder(); + } + } + }, natures, player); + var numx = player.hasSkillTag("nohujia") ? num : Math.max(0, num - player.hujia); + player.$damagepop(-numx, natures[0]); + } + if (event.unreal) event.goto(6) + if (!event.notrigger) { + if (num == 0) { + event.trigger("damageZero"); + event._triggered = null; + } + else { + event.trigger("damage"); + } + } + "step 5" + if (player.hp <= 0 && player.isAlive() && !event.nodying) { + game.delayx(); + event._dyinged = true; + player.dying(event); + } + if (source && lib.config.border_style == "auto") { + var dnum = 0; + for (var j = 0; j < source.stat.length; j++) { + if (source.stat[j].damage != undefined) dnum += source.stat[j].damage; + } + if (dnum >= 2) { + if (lib.config.autoborder_start == "silver") { + dnum += 4; + } + else if (lib.config.autoborder_start == "gold") { + dnum += 8; + } + } + if (lib.config.autoborder_count == "damage") { + source.node.framebg.dataset.decoration = ""; + if (dnum >= 10) { + source.node.framebg.dataset.auto = "gold"; + if (dnum >= 12) source.node.framebg.dataset.decoration = "gold"; + } + else if (dnum >= 6) { + source.node.framebg.dataset.auto = "silver"; + if (dnum >= 8) source.node.framebg.dataset.decoration = "silver"; + } + else if (dnum >= 2) { + source.node.framebg.dataset.auto = "bronze"; + if (dnum >= 4) source.node.framebg.dataset.decoration = "bronze"; + } + if (dnum >= 2) { + source.classList.add("topcount"); + } + } + else if (lib.config.autoborder_count == "mix") { + source.node.framebg.dataset.decoration = ""; + switch (source.node.framebg.dataset.auto) { + case "bronze": if (dnum >= 4) source.node.framebg.dataset.decoration = "bronze"; break; + case "silver": if (dnum >= 8) source.node.framebg.dataset.decoration = "silver"; break; + case "gold": if (dnum >= 12) source.node.framebg.dataset.decoration = "gold"; break; + } + } + } + "step 6" + if (!event.notrigger) event.trigger("damageSource"); + }, + recover: function () { + if (lib.config.background_audio) { + game.playAudio("effect", "recover"); + } + game.broadcast(function () { + if (lib.config.background_audio) { + game.playAudio("effect", "recover"); + } + }); + if (num > player.maxHp - player.hp) { + num = player.maxHp - player.hp; + event.num = num; + } + if (num > 0) { + player.changeHp(num, false); + game.broadcastAll(function (player) { + if (lib.config.animation && !lib.config.low_performance) { + player.$recover(); + } + }, player); + player.$damagepop(num, "wood"); + game.log(player, "回复了" + get.cnNumber(num) + "点体力") + } + }, + loseHp: function () { + "step 0" + if (lib.config.background_audio) { + game.playAudio("effect", "loseHp"); + } + game.broadcast(function () { + if (lib.config.background_audio) { + game.playAudio("effect", "loseHp"); + } + }); + game.log(player, "失去了" + get.cnNumber(num) + "点体力") + player.changeHp(-num); + "step 1" + if (player.hp <= 0 && !event.nodying) { + game.delayx(); + event._dyinged = true; + player.dying(event); + } + }, + doubleDraw: function () { + "step 0" + player.chooseBool("你的主副将体力上限之和是奇数,是否摸一张牌?"); + "step 1" + if (result.bool) { + player.draw(); + } + }, + loseMaxHp: function () { + "step 0" + game.log(player, "减少了" + get.cnNumber(num) + "点体力上限"); + player.maxHp -= num; + event.loseHp = Math.max(0, player.hp - player.maxHp); + player.update(); + "step 1" + if (player.maxHp <= 0) { + player.die(event); + } + }, + gainMaxHp: function () { + "step 0" + game.log(player, "增加了" + get.cnNumber(num) + "点体力上限"); + player.maxHp += num; + player.update(); + }, + changeHp: function () { + //add to GlobalHistory + game.getGlobalHistory().changeHp.push(event); + //changeHujia moved here + if (num < 0 && player.hujia > 0 && event.getParent().name == "damage" && !player.hasSkillTag("nohujia")) { + event.hujia = Math.min(-num, player.hujia); + event.getParent().hujia = event.hujia; + event.num += event.hujia; + //log moved to changeHujia + //game.log(player,"的护甲抵挡了"+get.cnNumber(event.hujia)+"点伤害"); + player.changeHujia(-event.hujia).type = "damage"; + } + //old part + num = event.num; + player.hp += num; + if (isNaN(player.hp)) player.hp = 0; + if (player.hp > player.maxHp) player.hp = player.maxHp; + player.update(); + if (event.popup !== false) { + player.$damagepop(num, "water"); + } + if (_status.dying.contains(player) && player.hp > 0) { + _status.dying.remove(player); + game.broadcast(function (list) { + _status.dying = list; + }, _status.dying); + var evt = event.getParent("_save"); + if (evt && evt.finish) evt.finish(); + evt = event.getParent("dying"); + if (evt && evt.finish) evt.finish() + } + event.trigger("changeHp"); + }, + changeHujia: function () { + if (num > 0) { + game.log(player, "获得了" + get.cnNumber(num) + "点护甲"); + } + else if (num < 0) { + if (-num > player.hujia) { + num = -player.hujia; + event.num = num; + } + switch (event.type) { //log moved here + case "damage": + game.log(player, "的护甲抵挡了" + get.cnNumber(-num) + "点伤害"); + break; + case "lose": + game.log(player, "失去了" + get.cnNumber(-num) + "点护甲"); + break; + } + } + player.hujia += num; + //if(player.hujia<0){ + // player.hujia=0; + //} + player.update(); + }, + dying: function () { + "step 0" + event.forceDie = true; + if (player.isDying() || player.hp > 0) { + event.finish(); + return; + } + _status.dying.unshift(player); + game.broadcast(function (list) { + _status.dying = list; + }, _status.dying); + event.trigger("dying"); + game.log(player, "濒死"); + "step 1" + delete event.filterStop; + if (player.hp > 0 || event.nodying) { + _status.dying.remove(player); + game.broadcast(function (list) { + _status.dying = list; + }, _status.dying); + event.finish(); + } + else if (!event.skipTao) { + var next = game.createEvent("_save"); + var start = false; + var starts = [_status.currentPhase, event.source, event.player, game.me, game.players[0]]; + for (var i = 0; i < starts.length; i++) { + if (get.itemtype(starts[i]) == "player") { + start = starts[i]; break; + } + } + next.player = start; + next._trigger = event; + next.triggername = "_save"; + next.forceDie = true; + next.setContent(lib.skill._save.content); + } + "step 2" + _status.dying.remove(player); + game.broadcast(function (list) { + _status.dying = list; + }, _status.dying); + if (player.hp <= 0 && !event.nodying && !player.nodying) player.die(event.reason); + }, + die: function () { + "step 0" + event.forceDie = true; + if (_status.roundStart == player) { + _status.roundStart = player.next || player.getNext() || game.players[0]; + } + if (ui.land && ui.land.player == player) { + game.addVideo("destroyLand"); + ui.land.destroy(); + } + var unseen = false; + if (player.classList.contains("unseen")) { + player.classList.remove("unseen"); + unseen = true; + } + var logvid = game.logv(player, "die", source); + event.logvid = logvid; + if (unseen) { + player.classList.add("unseen"); + } + if (source) { + game.log(player, "被", source, "杀害"); + if (source.stat[source.stat.length - 1].kill == undefined) { + source.stat[source.stat.length - 1].kill = 1; + } + else { + source.stat[source.stat.length - 1].kill++; + } + } + else { + game.log(player, "阵亡") + } + + + // player.removeEquipTrigger(); + + // for(var i in lib.skill.globalmap){ + // if(lib.skill.globalmap[i].contains(player)){ + // lib.skill.globalmap[i].remove(player); + // if(lib.skill.globalmap[i].length==0&&!lib.skill[i].globalFixed){ + // game.removeGlobalSkill(i); + // } + // } + // } + game.broadcastAll(function (player) { + player.classList.add("dead"); + player.removeLink(); + player.classList.remove("turnedover"); + player.classList.remove("out"); + player.node.count.innerHTML = "0"; + player.node.hp.hide(); + player.node.equips.hide(); + player.node.count.hide(); + player.previous.next = player.next; + player.next.previous = player.previous; + game.players.remove(player); + game.dead.push(player); + _status.dying.remove(player); + + if (lib.config.background_speak) { + if (lib.character[player.name] && lib.character[player.name][4].some(tag => /^die:.+$/.test(tag))) { + var tag = lib.character[player.name][4].find(tag => /^die:.+$/.test(tag)); + var reg = new RegExp("^ext:(.+)?/"); + var match = tag.match(/^die:(.+)$/); + if (match) { + var path = match[1]; + if (reg.test(path)) path = path.replace(reg, (_o, p) => `../extension/${p}/`); + game.playAudio(path); + } + } + else if (lib.character[player.name] && lib.character[player.name][4].some(tag => tag.startsWith("die_audio"))) { + var tag = lib.character[player.name][4].find(tag => tag.startsWith("die_audio")); + var list = tag.split(":").slice(1); + game.playAudio("die", list.length ? list[0] : player.name); + } + else { + game.playAudio("die", player.name, function () { + game.playAudio("die", player.name.slice(player.name.indexOf("_") + 1)); + }); + } + } + }, player); + + game.addVideo("diex", player); + if (event.animate !== false) { + player.$die(source); + } + if (player.hp != 0) { + player.changeHp(0 - player.hp, false).forceDie = true; + } + "step 1" + if (player.dieAfter) player.dieAfter(source); + "step 2" + event.trigger("die"); + "step 3" + if (player.isDead()) { + if (!game.reserveDead) { + for (var mark in player.marks) { + player.unmarkSkill(mark); + } + while (player.node.marks.childNodes.length > 1) { + player.node.marks.lastChild.remove(); + } + game.broadcast(function (player) { + while (player.node.marks.childNodes.length > 1) { + player.node.marks.lastChild.remove(); + } + }, player); + } + for (var i in player.tempSkills) { + player.removeSkill(i); + } + var skills = player.getSkills(); + for (var i = 0; i < skills.length; i++) { + if (lib.skill[skills[i]].temp) { + player.removeSkill(skills[i]); + } + } + if (_status.characterlist) { + if (lib.character[player.name] && !player.name.startsWith("gz_shibing") && !player.name.startsWith("gz_jun_")) _status.characterlist.add(player.name); + if (lib.character[player.name1] && !player.name1.startsWith("gz_shibing") && !player.name1.startsWith("gz_jun_")) _status.characterlist.add(player.name1); + if (lib.character[player.name2] && !player.name2.startsWith("gz_shibing") && !player.name2.startsWith("gz_jun_")) _status.characterlist.add(player.name2); + } + event.cards = player.getCards("hejsx"); + if (event.cards.length) { + player.discard(event.cards).forceDie = true; + //player.$throw(event.cards,1000); + } + } + "step 4" + if (player.dieAfter2) player.dieAfter2(source); + "step 5" + game.broadcastAll(function (player) { + if (game.online && player == game.me && !_status.over && !game.controlOver && !ui.exit) { + if (lib.mode[lib.configOL.mode].config.dierestart) { + ui.create.exit(); + } + } + }, player); + if (!_status.connectMode && player == game.me && !_status.over && !game.controlOver) { + ui.control.show(); + if (get.config("revive") && lib.mode[lib.config.mode].config.revive && !ui.revive) { + ui.revive = ui.create.control("revive", ui.click.dierevive); + } + if (get.config("continue_game") && !ui.continue_game && lib.mode[lib.config.mode].config.continue_game && !_status.brawl && !game.no_continue_game) { + ui.continue_game = ui.create.control("再战", game.reloadCurrent); + } + if (get.config("dierestart") && lib.mode[lib.config.mode].config.dierestart && !ui.restart) { + ui.restart = ui.create.control("restart", game.reload); + } + } + + if (!_status.connectMode && player == game.me && !game.modeSwapPlayer) { + // _status.auto=false; + if (ui.auto) { + // ui.auto.classList.remove("glow"); + ui.auto.hide(); + } + if (ui.wuxie) ui.wuxie.hide(); + } + + if (typeof _status.coin == "number" && source && !_status.auto) { + if (source == game.me || source.isUnderControl()) { + _status.coin += 10; + } + } + if (source && lib.config.border_style == "auto" && (lib.config.autoborder_count == "kill" || lib.config.autoborder_count == "mix")) { + switch (source.node.framebg.dataset.auto) { + case "gold": case "silver": source.node.framebg.dataset.auto = "gold"; break; + case "bronze": source.node.framebg.dataset.auto = "silver"; break; + default: source.node.framebg.dataset.auto = lib.config.autoborder_start || "bronze"; + } + if (lib.config.autoborder_count == "kill") { + source.node.framebg.dataset.decoration = source.node.framebg.dataset.auto; + } + else { + var dnum = 0; + for (var j = 0; j < source.stat.length; j++) { + if (source.stat[j].damage != undefined) dnum += source.stat[j].damage; + } + source.node.framebg.dataset.decoration = ""; + switch (source.node.framebg.dataset.auto) { + case "bronze": if (dnum >= 4) source.node.framebg.dataset.decoration = "bronze"; break; + case "silver": if (dnum >= 8) source.node.framebg.dataset.decoration = "silver"; break; + case "gold": if (dnum >= 12) source.node.framebg.dataset.decoration = "gold"; break; + } + } + source.classList.add("topcount"); + } + }, + addJudge: function () { + "step 0" + if (cards) { + var owner = get.owner(cards[0]); + if (owner) { + event.relatedLose = owner.lose(cards, "visible", ui.special).set("getlx", false); + } + else if (get.position(cards[0]) == "c") event.updatePile = true; + } + "step 1" + if (cards[0].willBeDestroyed("judge", player, event)) { + cards[0].selfDestroy(event); + event.finish(); + return; + } + else if (event.relatedLose) { + var owner = event.relatedLose.player; + if (owner.getCards("hejsx").contains(card)) { + event.finish(); + return; + } + } + cards[0].fix(); + cards[0].style.transform = ""; + cards[0].classList.remove("drawinghidden"); + delete cards[0]._transform; + var viewAs = typeof card == "string" ? card : card.name; + if (!lib.card[viewAs] || !lib.card[viewAs].effect) { + game.cardsDiscard(cards[0]); + } + else { + cards[0].style.transform = ""; + cards[0].classList.add("drawinghidden"); + player.node.judges.insertBefore(cards[0], player.node.judges.firstChild); + if (_status.discarded) { + _status.discarded.remove(cards[0]); + } + ui.updatej(player); + game.broadcast(function (player, card, viewAs) { + card.fix(); + card.style.transform = ""; + card.classList.add("drawinghidden"); + card.viewAs = viewAs; + if (viewAs && viewAs != card.name && (card.classList.contains("fullskin") || card.classList.contains("fullborder"))) { + card.classList.add("fakejudge"); + card.node.background.innerHTML = lib.translate[viewAs + "_bg"] || get.translation(viewAs)[0] + } + else { + card.classList.remove("fakejudge"); + } + player.node.judges.insertBefore(card, player.node.judges.firstChild); + ui.updatej(player); + if (card.clone && (card.clone.parentNode == player.parentNode || card.clone.parentNode == ui.arena)) { + card.clone.moveDelete(player); + game.addVideo("gain2", player, get.cardsInfo([card])); + } + }, player, cards[0], viewAs); + if (cards[0].clone && (cards[0].clone.parentNode == player.parentNode || cards[0].clone.parentNode == ui.arena)) { + cards[0].clone.moveDelete(player); + game.addVideo("gain2", player, get.cardsInfo(cards)); + } + // player.$gain2(cards); + if (get.itemtype(card) != "card") { + if (typeof card == "string") cards[0].viewAs = card; + else cards[0].viewAs = card.name; + } + else { + delete cards[0].viewAs; + } + if (cards[0].viewAs && cards[0].viewAs != cards[0].name) { + if (cards[0].classList.contains("fullskin") || cards[0].classList.contains("fullborder")) { + cards[0].classList.add("fakejudge"); + cards[0].node.background.innerHTML = lib.translate[cards[0].viewAs + "_bg"] || get.translation(cards[0].viewAs)[0]; + } + game.log(player, `被贴上了${get.translation(cards[0].viewAs)}(`, cards, ")"); + } + else { + cards[0].classList.remove("fakejudge"); + game.log(player, "被贴上了", cards); + } + game.addVideo("addJudge", player, [get.cardInfo(cards[0]), cards[0].viewAs]); + } + if (event.updatePile) game.updateRoundNumber(); + }, + judge: function () { + "step 0" + var judgestr = get.translation(player) + "的" + event.judgestr + "判定"; + event.videoId = lib.status.videoId++; + var cardj = event.directresult; + if (!cardj) { + if (player.getTopCards) cardj = player.getTopCards()[0]; + else cardj = get.cards()[0]; + } + var owner = get.owner(cardj); + if (owner) { + owner.lose(cardj, "visible", ui.ordering); + } + else { + var nextj = game.cardsGotoOrdering(cardj); + if (event.position != ui.discardPile) nextj.noOrdering = true; + } + player.judging.unshift(cardj); + game.addVideo("judge1", player, [get.cardInfo(player.judging[0]), judgestr, event.videoId]); + game.broadcastAll(function (player, card, str, id, cardid) { + var event; + if (game.online) { + event = {}; + } + else { + event = _status.event; + } + if (game.chess) { + event.node = card.copy("thrown", "center", ui.arena).animate("start"); + } + else { + event.node = player.$throwordered(card.copy(), true); + } + if (lib.cardOL) lib.cardOL[cardid] = event.node; + event.node.cardid = cardid; + event.node.classList.add("thrownhighlight"); + ui.arena.classList.add("thrownhighlight"); + event.dialog = ui.create.dialog(str); + event.dialog.classList.add("center"); + event.dialog.videoId = id; + }, player, player.judging[0], judgestr, event.videoId, get.id()); + + game.log(player, "进行" + event.judgestr + "判定,亮出的判定牌为", player.judging[0]); + game.delay(2); + if (!event.noJudgeTrigger) event.trigger("judge"); + "step 1" + event.result = { + card: player.judging[0], + name: player.judging[0].name, + number: get.number(player.judging[0]), + suit: get.suit(player.judging[0]), + color: get.color(player.judging[0]), + node: event.node, + }; + if (event.fixedResult) { + for (var i in event.fixedResult) { + event.result[i] = event.fixedResult[i]; + } + } + event.result.judge = event.judge(event.result); + if (event.result.judge > 0) event.result.bool = true; + else if (event.result.judge < 0) event.result.bool = false; + else event.result.bool = null; + player.judging.shift(); + game.checkMod(player, event.result, "judge", player); + if (event.judge2) { + var judge2 = event.judge2(event.result); + if (typeof judge2 == "boolean") player.tryJudgeAnimate(judge2); + } + if (event.clearArena != false) { + game.broadcastAll(ui.clear); + } + game.broadcast(function (id) { + var dialog = get.idDialog(id); + if (dialog) { + dialog.close(); + } + ui.arena.classList.remove("thrownhighlight"); + }, event.videoId); + event.dialog.close(); + game.addVideo("judge2", null, event.videoId); + ui.arena.classList.remove("thrownhighlight"); + game.log(player, "的判定结果为", event.result.card); + event.trigger("judgeFixing"); + if (event.callback) { + var next = game.createEvent("judgeCallback", false); + next.player = player; + next.card = event.result.card; + next.judgeResult = get.copy(event.result); + next.setContent(event.callback); + } + else { + if (!get.owner(event.result.card)) { + if (event.position != ui.discardPile) event.position.appendChild(event.result.card); + } + } + }, + turnOver: function () { + game.log(player, "翻面"); + player.classList.toggle("turnedover"); + game.broadcast(function (player) { + player.classList.toggle("turnedover"); + }, player); + game.addVideo("turnOver", player, player.classList.contains("turnedover")); + }, + link: function () { + if (player.isLinked()) { + game.log(player, "解除连环"); + } + else { + game.log(player, "被连环"); + } + if (lib.config.background_audio) { + game.playAudio("effect", "link"); + } + game.broadcast(function () { + if (lib.config.background_audio) { + game.playAudio("effect", "link"); + } + }); + player.classList.remove("target"); + if (get.is.linked2(player)) { + player.classList.toggle("linked2"); + } + else { + player.classList.toggle("linked"); + } + ui.updatej(player); + ui.updatem(player); + game.broadcast(function (player, linked) { + player.classList.remove("target"); + if (get.is.linked2(player)) { + if (linked) { + player.classList.add("linked2"); + } + else { + player.classList.remove("linked2"); + } + } + else { + if (linked) { + player.classList.add("linked"); + } + else { + player.classList.remove("linked"); + } + } + ui.updatej(player); + ui.updatem(player); + }, player, player.isLinked()); + game.addVideo("link", player, player.isLinked()); + }, + chooseToGuanxing: function () { + "step 0" + var cards = get.cards(num); + game.cardsGotoOrdering(cards); + var next = player.chooseToMove(); + next.set("list", [ + ["牌堆顶", cards], + ["牌堆底"], + ]); + next.set("prompt", "点击将牌移动到牌堆顶或牌堆底"); + next.processAI = event.processAI || function (list) { + var cards = list[0][1], player = _status.event.player; + var top = []; + var bottom; + cards.sort(function (a, b) { + return get.value(b, player) - get.value(a, player); + }); + while (cards.length) { + if (get.value(cards[0], player) <= 5) break; + top.unshift(cards.shift()); + } + bottom = cards; + return [top, bottom]; + }; + "step 1" + var top = result.moved[0]; + var bottom = result.moved[1]; + top.reverse(); + for (var i = 0; i < top.length; i++) { + ui.cardPile.insertBefore(top[i], ui.cardPile.firstChild); + } + for (i = 0; i < bottom.length; i++) { + ui.cardPile.appendChild(bottom[i]); + } + game.addCardKnower(top, player); + game.addCardKnower(bottom, player); + player.popup(get.cnNumber(top.length) + "上" + get.cnNumber(bottom.length) + "下"); + game.log(player, "将" + get.cnNumber(top.length) + "张牌置于牌堆顶"); + game.updateRoundNumber(); + game.delayx(); + }, + }, Player, + Card, VCard, - GameEvent + Button, + GameEvent, + GameEventPromise, + Dialog, + Control, + Client, + NodeWS, + WS, + /** + * @legacy Use {@link lib.element.Player.prototype} instead. + */ + get player() { + return this.Player.prototype; + }, + /** + * @legacy Use {@link lib.element.Card.prototype} instead. + */ + get card() { + return this.Card.prototype; + }, + /** + * @legacy Use {@link lib.element.Button.prototype} instead. + */ + get button() { + return this.Button.prototype; + }, + /** + * @legacy Use {@link lib.element.GameEvent.prototype} instead. + */ + get event() { + return this.GameEvent.prototype; + }, + /** + * @legacy Use {@link lib.element.Dialog.prototype} instead. + */ + get dialog() { + return this.Dialog.prototype; + }, + /** + * @legacy Use {@link lib.element.Control.prototype} instead. + */ + get control() { + return this.Control.prototype; + }, + /** + * @legacy Use {@link lib.element.Client.prototype} instead. + */ + get client() { + return this.Client.prototype; + }, + /** + * @legacy Use {@link lib.element.NodeWS.prototype} instead. + */ + get nodews() { + return this.NodeWS.prototype; + } }; diff --git a/noname/library/element/button.js b/noname/library/element/button.js new file mode 100644 index 000000000..9a978cd55 --- /dev/null +++ b/noname/library/element/button.js @@ -0,0 +1,30 @@ +export class Button extends HTMLDivElement { + /** + * @param {{}} item + * @param {keyof typeof ui.create.buttonPresets | (item: {}, type: Function, position?: HTMLDivElement, noClick?: true, button?: HTMLDivElement) => HTMLDivElement} type + * @param {HTMLDivElement} [position] + * @param {true} [noClick] + * @param {HTMLDivElement} [button] + */ + constructor(item, type, position, noClick, button) { + if (ui.create.buttonPresets[type]) button = ui.create.buttonPresets[type](item, type, position, noClick, button); + else if (typeof type == "function") button = type(item, type, position, noClick, button); + Object.setPrototypeOf(button, lib.element.Button.prototype); + if (!noClick) button.addEventListener(lib.config.touchscreen ? "touchend" : "click", ui.click.button); + else { + button.classList.add("noclick"); + const intro = button.querySelector(".intro"); + if (intro) intro.remove(); + } + return button; + } + exclude() { + if (_status.event.excludeButton == undefined) { + _status.event.excludeButton = []; + } + _status.event.excludeButton.add(this); + } + get updateTransform() { + return lib.element.Card.prototype.updateTransform; + } +} diff --git a/noname/library/element/card.js b/noname/library/element/card.js new file mode 100644 index 000000000..e8b08c4bd --- /dev/null +++ b/noname/library/element/card.js @@ -0,0 +1,775 @@ +export class Card extends HTMLDivElement { + /** + * @param {HTMLDivElement} [position] + * @param {"noclick"} [info] + * @param {true} [noclick] + */ + constructor(position, info, noclick) { + const card = ui.create.div(".card", position); + Object.setPrototypeOf(card, lib.element.Card.prototype); + card.build(info, noclick); + return card; + } + build(info, noclick) { + let card = this; + card.buildNode(); + card.buildIntro(noclick); + card.buildProperty(); + card.buildEventListener(info); + } + buildEventListener(info) { + let card = this; + if (info != "noclick") { + card.addEventListener(lib.config.touchscreen ? "touchend" : "click", ui.click.card); + if (lib.config.touchscreen) { + card.addEventListener("touchstart", ui.click.cardtouchstart); + card.addEventListener("touchmove", ui.click.cardtouchmove); + } + if (lib.cardSelectObserver) lib.cardSelectObserver.observe(card, { + attributes: true + }); + } + } + buildProperty() { + let card = this; + card.storage = {}; + card.vanishtag = []; + card.gaintag = []; + card._uncheck = []; + } + buildNode() { + this.node = { + image: ui.create.div(".image", this), + info: ui.create.div(".info", this), + name: ui.create.div(".name", this), + name2: ui.create.div(".name2", this), + background: ui.create.div(".background", this), + intro: ui.create.div(".intro", this), + range: ui.create.div(".range", this), + gaintag: ui.create.div(".gaintag", this), + }; + this.node.intro.innerHTML = lib.config.intro; + } + buildIntro(noclick) { + if (!noclick) lib.setIntro(this); + } + //执行销毁一张牌的钩子函数 + selfDestroy(event) { + if (this._selfDestroyed) return; + this._selfDestroyed = true; + this.fix(); + this.delete(); + const info = get.info(this, false); + if (!info) return; + if (info.destroyLog !== false) game.log(this, "被销毁了"); + if (info.onDestroy) info.onDestroy(this, event); + } + //判断一张牌进入某个区域后是否会被销毁 + willBeDestroyed(targetPosition, player, event) { + const destroyed = this.destroyed; + if (typeof destroyed == "function") { + return destroyed(this, targetPosition, player, event); + } + else if (lib.skill[destroyed]) { + if (player) { + if (player.hasSkill(destroyed)) { + delete this.destroyed; + return false; + } + } + return true; + } + else if (typeof destroyed == "string") { + return (destroyed == targetPosition); + } + return destroyed; + } + hasNature(nature, player) { + return game.hasNature(this, nature, player); + } + //只针对【杀】起效果 + addNature(nature) { + let natures = []; + if (!this.nature) this.nature = ""; + else { + natures.addArray(get.natureList(this.nature)); + } + natures.addArray(get.natureList(nature)); + this.nature = get.nature(natures); + this.classList.add(nature); + let str = get.translation(this.nature) + "杀"; + this.node.name.innerText = str; + let name = get.name(this, false); + do { + if (name == "sha") { + let _bg; + for (const n of natures) if (lib.natureBg.has(n)) _bg = n; + if (_bg) { + this.node.image.setBackgroundImage(lib.natureBg.get(_bg)); + break; + } + } + this.node.image.setBackgroundImage("image/card/" + name + ".png"); + } + while (0); + return this.nature; + } + removeNature(nature) { + if (!this.nature) return; + let natures = get.natureList(this.nature); + natures.remove(nature); + if (!natures.length) delete this.nature; + else this.nature = get.nature(natures); + this.classList.remove(nature); + let str = get.translation(this.nature) + "杀"; + this.node.name.innerText = str; + let name = get.name(this, false); + do { + if (name == "sha") { + let _bg; + for (const n of natures) if (lib.natureBg.has(n)) _bg = n; + if (_bg) { + this.node.image.setBackgroundImage(lib.natureBg.get(_bg)); + break; + } + } + this.node.image.setBackgroundImage("image/card/" + name + ".png"); + } + while (0); + return this.nature; + } + addGaintag(gaintag) { + if (Array.isArray(gaintag)) this.gaintag = gaintag.slice(0); + else this.gaintag.add(gaintag); + var str = ""; + for (var gi = 0; gi < this.gaintag.length; gi++) { + var translate = get.translation(this.gaintag[gi]); + if (translate != "invisible") { + str += translate; + if (gi < this.gaintag.length - 1) str += " "; + } + } + this.node.gaintag.innerHTML = str; + } + removeGaintag(tag) { + if (tag === true) { + if (this.gaintag && this.gaintag.length || this.node.gaintag.innerHTML.length) this.addGaintag([]); + } + else if (this.hasGaintag(tag)) { + this.gaintag.remove(tag); + this.addGaintag(this.gaintag); + } + } + hasGaintag(tag) { + return this.gaintag && this.gaintag.contains(tag); + } + /** + * @param {[string, number, string, string] | { + * suit: string; + * number: number; + * name: string; + * nature: string; + * }} card + */ + init(card) { + if (Array.isArray(card)) { + if (card[2] == "huosha") { + card[2] = "sha"; + card[3] = "fire"; + } + else if (card[2] == "leisha") { + card[2] = "sha"; + card[3] = "thunder"; + } + else if (card[2] == "cisha") { + card[2] = "sha"; + card[3] = "stab"; + } + else if (card[2].length > 3) { + let prefix = card[2].slice(0, card[2].lastIndexOf("sha")); + if (lib.nature.has(prefix)) { + if (prefix.length + 3 == card[2].length) { + card[2] = "sha"; + card[3] = prefix; + } + } + if (card[2].startsWith("sha_")) { + let suffix = card[2].slice(4); + let natureList = suffix.split("_"); + card[2] = "sha"; + card[3] = get.nature(natureList); + } + } + } + else if (typeof card == "object") { + card = [card.suit, card.number, card.name, card.nature]; + } + var cardnum = card[1] || ""; + if (parseInt(cardnum) == cardnum) cardnum = parseInt(cardnum); + + if (!lib.card[card[2]]) { + lib.card[card[2]] = {}; + } + var info = lib.card[card[2]]; + if (info.global && !this.classList.contains("button")) { + if (Array.isArray(info.global)) { + while (info.global.length) { + game.addGlobalSkill(info.global.shift()); + } + } + else if (typeof info.global == "string") { + game.addGlobalSkill(info.global); + } + delete info.global; + } + this.suit = card[0]; + this.number = parseInt(card[1]) || 0; + this.name = card[2]; + + if (info.destroy && (typeof info.destroy != "boolean" && !lib.skill[info.destroy])) { + this.destroyed = info.destroy; + } + + if (_status.connectMode && !game.online && lib.cardOL && !this.cardid) { + this.cardid = get.id(); + lib.cardOL[this.cardid] = this; + } + if (!_status.connectMode && !_status.video) { + this.cardid = get.id(); + } + + this.$init(card); + + if (this.inits) { + for (var i = 0; i < this.inits.length; i++) { + this.inits[i](this); + } + } + if (typeof info.init == "function") info.init(); + + return this; + } + /** + * @param {[string, number, string, string]} card + */ + $init(card) { + var info = lib.card[card[2]]; + var cardnum = card[1] || ""; + if (parseInt(cardnum) == cardnum) cardnum = parseInt(cardnum); + if (cardnum > 0 && cardnum < 14) { + cardnum = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"][cardnum - 1]; + } + if (this.name) { + this.classList.remove("epic"); + this.classList.remove("legend"); + this.classList.remove("gold"); + this.classList.remove("unique"); + this.style.background = ""; + var subtype = get.subtype(this, false); + if (subtype) { + this.classList.remove(subtype); + } + } + if (info.epic) { + this.classList.add("epic"); + } + else if (info.legend) { + this.classList.add("legend"); + } + else if (info.gold) { + this.classList.add("gold"); + } + else if (info.unique) { + this.classList.add("unique"); + } + var bg = card[2]; + if (info.cardimage) { + bg = info.cardimage; + } + var img = lib.card[bg].image; + if (img) { + if (img.startsWith("db:")) { + img = img.slice(3); + } + else if (!img.startsWith("ext:")) { + img = null; + } + } + this.classList.remove("fullskin"); + this.classList.remove("fullimage"); + this.classList.remove("fullborder"); + this.dataset.cardName = card[2]; + this.dataset.cardType = info.type || ""; + this.dataset.cardSubype = info.subtype || ""; + this.dataset.cardMultitarget = info.multitarget ? "1" : "0"; + this.node.name.dataset.nature = ""; + this.node.info.classList.remove("red"); + if (!lib.config.hide_card_image && lib.card[bg].fullskin) { + this.classList.add("fullskin"); + if (img) { + if (img.startsWith("ext:")) { + this.node.image.setBackgroundImage(img.replace(/^ext:/, "extension/")); + } + else { + this.node.image.setBackgroundDB(img); + } + } + else { + if (lib.card[bg].modeimage) { + this.node.image.setBackgroundImage("image/mode/" + lib.card[bg].modeimage + "/card/" + bg + ".png"); + } + else { + do { + let nature = card[3]; + if (bg == "sha" && typeof nature == "string") { + let natures = get.natureList(nature), _bg; + for (const n of natures) if (lib.natureBg.has(n)) _bg = n; + if (_bg) { + this.node.image.setBackgroundImage(lib.natureBg.get(_bg)); + break; + } + } + this.node.image.setBackgroundImage("image/card/" + bg + ".png"); + } + while (0); + } + } + } + else if (lib.card[bg].image == "background") { + if (card[3]) this.node.background.setBackground(bg + "_" + get.natureList(card[3])[0], "card"); + else this.node.background.setBackground(bg, "card"); + } + else if (lib.card[bg].fullimage) { + this.classList.add("fullimage"); + if (img) { + if (img.startsWith("ext:")) { + this.setBackgroundImage(img.replace(/^ext:/, "extension/")); + this.style.backgroundSize = "cover"; + } + else { + this.setBackgroundDB(img); + } + } + else if (lib.card[bg].image) { + if (lib.card[bg].image.startsWith("character:")) { + this.setBackground(lib.card[bg].image.slice(10), "character"); + } + else { + this.setBackground(lib.card[bg].image); + } + } + else { + var cardPack = lib.cardPack["mode_" + get.mode()]; + if (Array.isArray(cardPack) && cardPack.contains(bg)) { + this.setBackground("mode/" + get.mode() + "/card/" + bg); + } + else { + this.setBackground("card/" + bg); + } + } + } + else if (lib.card[bg].fullborder) { + this.classList.add("fullborder"); + if (lib.card[bg].fullborder == "gold") { + this.node.name.dataset.nature = "metalmm"; + } + else if (lib.card[bg].fullborder == "silver") { + this.node.name.dataset.nature = "watermm"; + } + if (!this.node.avatar) { + this.node.avatar = ui.create.div(".cardavatar"); + this.insertBefore(this.node.avatar, this.firstChild); + } + if (!this.node.framebg) { + this.node.framebg = ui.create.div(".cardframebg"); + this.node.framebg.dataset.auto = lib.card[bg].fullborder; + this.insertBefore(this.node.framebg, this.firstChild); + } + if (img) { + if (img.startsWith("ext:")) { + this.node.avatar.setBackgroundImage(img.replace(/^ext:/, "extension/")); + this.node.avatar.style.backgroundSize = "cover"; + } + else { + this.node.avatar.setBackgroundDB(img); + } + } + else if (lib.card[bg].image) { + if (lib.card[bg].image.startsWith("character:")) { + this.node.avatar.setBackground(lib.card[bg].image.slice(10), "character"); + } + else { + this.node.avatar.setBackground(lib.card[bg].image); + } + } + else { + var cardPack = lib.cardPack["mode_" + get.mode()]; + if (Array.isArray(cardPack) && cardPack.contains(bg)) { + this.node.avatar.setBackground("mode/" + get.mode() + "/card/" + bg); + } + else { + this.node.avatar.setBackground("card/" + bg); + } + } + } + else if (lib.card[bg].image == "card") { + if (card[3]) this.setBackground(bg + "_" + get.natureList(card[3])[0], "card"); + else this.setBackground(bg, "card"); + } + else if (typeof lib.card[bg].image == "string" && !lib.card[bg].fullskin) { + if (img) { + if (img.startsWith("ext:")) { + this.setBackgroundImage(img.replace(/^ext:/, "extension/")); + this.style.backgroundSize = "cover"; + } + else { + this.setBackgroundDB(img); + } + } + else { + this.setBackground(lib.card[bg].image); + } + } + else { + this.node.background.innerHTML = lib.translate[bg + "_cbg"] || lib.translate[bg + "_bg"] || get.translation(bg)[0]; + // this.node.background.style.fontFamily=lib.config.card_font; + if (this.node.background.innerHTML.length > 1) this.node.background.classList.add("tight"); + else this.node.background.classList.remove("tight"); + } + if (!lib.card[bg].fullborder && this.node.avatar && this.node.framebg) { + this.node.avatar.remove(); + this.node.framebg.remove(); + delete this.node.avatar; + delete this.node.framebg; + } + if (info.noname && !this.classList.contains("button")) { + this.node.name.style.display = "none"; + } + if (info.color) { + this.style.color = info.color; + } + if (info.textShadow) { + this.style.textShadow = info.textShadow; + } + if (info.opacity) { + this.node.info.style.opacity = info.opacity; + this.node.name.style.opacity = info.opacity; + } + if (info.modinfo) { + this.node.info.innerHTML = info.modinfo; + } + else { + this.node.info.innerHTML = `${get.translation(card[0])} ${cardnum}`; + } + if (info.addinfo) { + if (!this.node.addinfo) { + this.node.addinfo = ui.create.div(".range", this); + } + this.node.addinfo.innerHTML = info.addinfo; + } + else if (this.node.addinfo) { + this.node.addinfo.remove(); + delete this.node.addinfo; + } + if (card[0] == "heart" || card[0] == "diamond") { + this.node.info.classList.add("red"); + } + this.node.image.className = "image"; + var name = get.translation(card[2]); + if (card[2] == "sha") { + name = ""; + let nature = card[3]; + if (nature) { + let natures = get.natureList(nature); + natures.sort(lib.sort.nature); + for (let nature of natures) { + name += lib.translate["nature_" + nature] || lib.translate[nature] || ""; + if (nature != "stab") this.node.image.classList.add(nature); + } + } + name += "杀"; + } + this.node.name.innerHTML = name; + if (name.length >= 5) { + this.node.name.classList.add("long"); + if (name.length >= 7) { + this.node.name.classList.add("longlong"); + } + } + this.node.name2.innerHTML = get.translation(card[0]) + cardnum + " " + name; + this.classList.add("card"); + if (card[3]) { + let natures = get.natureList(card[3]); + natures.forEach(n => { if (n) this.classList.add(n) }); + this.nature = natures.filter(n => lib.nature.has(n)).sort(lib.sort.nature).join(lib.natureSeparator); + } + else if (this.nature) { + this.classList.remove(this.nature); + delete this.nature; + } + if (info.subtype) this.classList.add(info.subtype); + this.node.range.innerHTML = ""; + switch (get.subtype(this, false)) { + case "equip1": + var added = false; + if (lib.card[this.name] && lib.card[this.name].distance) { + var dist = lib.card[this.name].distance; + if (dist.attackFrom) { + added = true; + this.node.range.innerHTML = "范围: " + (-dist.attackFrom + 1); + } + } + if (!added) { + this.node.range.innerHTML = "范围: 1"; + } + break; + case "equip3": + if (info.distance && info.distance.globalTo) { + this.node.range.innerHTML = "防御: " + info.distance.globalTo; + this.node.name2.innerHTML += "+"; + } + break; + case "equip4": + if (info.distance && info.distance.globalFrom) { + this.node.range.innerHTML = "进攻: " + (-info.distance.globalFrom); + this.node.name2.innerHTML += "-"; + } + break; + } + var tags = []; + if (Array.isArray(card[4])) { + tags.addArray(card[4]); + } + if (this.cardid) { + if (!_status.cardtag) { + _status.cardtag = {}; + } + for (var i in _status.cardtag) { + if (_status.cardtag[i].contains(this.cardid)) { + tags.add(i); + } + } + if (tags.length) { + var tagstr = ` `; + for (var i = 0; i < tags.length; i++) { + var tag = tags[i]; + if (!_status.cardtag[tag]) { + _status.cardtag[tag] = []; + } + _status.cardtag[tag].add(this.cardid); + tagstr += lib.translate[tag + "_tag"]; + //if(i this._knowers.add(p.playerid)); + } + } + } + removeKnower(player) { + if (!this._knowers) { + return; + } + if (typeof player == "string") { + this._knowers.remove(player); + } else { + let type = get.itemtype(player); + if (type == "player") { + this._knowers.remove(player.playerid); + } else if (type == "players") { + player.forEach(p => this._knowers.remove(p.playerid)); + } + } + } + //清除此牌的知情者。 + clearKnowers() { + if (this._knowers) delete this._knowers; + } + //判断玩家对此牌是否知情。 + isKnownBy(player) { + if (["e", "j"].includes(get.position(this))) return true;//装备区或者判定区的牌,必知情。 + let owner = get.owner(this); + if (owner) { + if (owner == player) return true;//是牌主,必知情。 + if (player.hasSkillTag("viewHandcard", null, owner, true)) return true;//有viewHandcard标签,必知情。 + if (owner.isUnderControl(true, player)) return true;//被操控,必知情。 + } + if (get.is.shownCard(this)) return true;//此牌是明置牌,必知情。 + if (this._knowers) { + return this._knowers.includes("everyone") || this._knowers.includes(player.playerid); + } + return false; + } + getSource(name) { + if (this.name == name) return true; + var info = lib.card[this.name]; + if (info && Array.isArray(info.source)) { + return info.source.contains(name); + } + return false; + } + moveDelete(player) { + this.fixed = true; + if (!this._listeningEnd || this._transitionEnded) { + this.moveTo(player); + var that = this; + setTimeout(function () { + that.delete(); + }, 200); + } + else { + this._onEndMoveDelete = player; + } + } + moveTo(player) { + this.fixed = true; + var dx, dy; + if (this.classList.contains("center")) { + var nx = [50, -52]; + var ny = [50, -52]; + nx = nx[0] * ui.arena.offsetWidth / 100 + nx[1]; + ny = ny[0] * ui.arena.offsetHeight / 100 + ny[1]; + dx = player.getLeft() + player.offsetWidth / 2 - 52 - nx; + dy = player.getTop() + player.offsetHeight / 2 - 52 - ny; + } + else { + this.style.left = this.offsetLeft + "px"; + this.style.top = this.offsetTop + "px"; + + dx = player.getLeft() + player.offsetWidth / 2 - 52 - this.offsetLeft; + dy = player.getTop() + player.offsetHeight / 2 - 52 - this.offsetTop; + } + if (get.is.mobileMe(player)) { + dx += get.cardOffset(); + if (ui.arena.classList.contains("oblongcard")) { + dy -= 16; + } + } + + + if (this.style.transform && this.style.transform != "none" && this.style.transform.indexOf("translate") == -1) { + this.style.transform += " translate(" + dx + "px," + dy + "px)"; + } + else { + this.style.transform = "translate(" + dx + "px," + dy + "px)"; + } + return this; + } + copy() { + /** + * @type {Card} + */ + var node = this.cloneNode(true); + node.style.transform = ""; + node.name = this.name; + node.suit = this.suit; + node.number = this.number; + node.nature = this.nature; + node.classList.remove("hidden"); + node.classList.remove("start"); + node.classList.remove("thrown"); + node.classList.remove("selectable"); + node.classList.remove("selected"); + node.classList.remove("removing"); + node.classList.remove("drawinghidden"); + node.classList.remove("glows"); + node.node = { + name: node.querySelector(".name"), + info: node.querySelector(".info"), + intro: node.querySelector(".intro"), + background: node.querySelector(".background"), + image: node.querySelector(".image"), + gaintag: node.querySelector(".gaintag"), + } + node.node.gaintag.innerHTML = ""; + var clone = true; + var position; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "string") node.classList.add(arguments[i]); + else if (get.objtype(arguments[i]) == "div") position = arguments[i]; + else if (typeof arguments[i] == "boolean") clone = arguments[i]; + } + node.moveTo = lib.element.Card.prototype.moveTo; + node.moveDelete = lib.element.Card.prototype.moveDelete; + if (clone) this.clone = node; + if (position) position.appendChild(node); + return node; + } + uncheck(skill) { + if (skill) this._uncheck.add(skill); + this.classList.add("uncheck"); + } + recheck(skill) { + if (skill) this._uncheck.remove(skill); + else this._uncheck.length = 0; + if (this._uncheck.length == 0) this.classList.remove("uncheck"); + } + discard(bool) { + if (!this._selfDestroyed) { + this.fix(); + ui.discardPile.appendChild(this); + } + this.classList.remove("glow"); + if (bool === false) { + ui.cardPile.insertBefore(this, ui.cardPile.childNodes[Math.floor(Math.random() * ui.cardPile.childNodes.length)]); + } + else { + if (_status.discarded) { + _status.discarded.add(this); + } + } + } + hasTag(tag) { + if (this.cardid && _status.cardtag && _status.cardtag[tag] && _status.cardtag[tag].contains(this.cardid)) { + return true; + } + return false; + } + hasPosition() { + return ["h", "e", "j", "s", "x"].contains(get.position(this)); + } + isInPile() { + return ["c", "d"].contains(get.position(this)); + } +} diff --git a/noname/library/element/client.js b/noname/library/element/client.js new file mode 100644 index 000000000..c35ce4eee --- /dev/null +++ b/noname/library/element/client.js @@ -0,0 +1,61 @@ +export class Client { + /** + * @param {NodeWS | InstanceType} ws + */ + constructor(ws) { + this.ws = ws; + this.id = ws.wsid || get.id(); + this.closed = false; + } + send() { + if (this.closed) return this; + var args = Array.from(arguments); + if (typeof args[0] == "function") { + args.unshift("exec"); + } + for (var i = 1; i < args.length; i++) { + args[i] = get.stringifiedResult(args[i]); + } + try { + this.ws.send(JSON.stringify(args)); + } + catch (e) { + this.ws.close(); + } + return this; + } + close() { + lib.node.clients.remove(this); + lib.node.observing.remove(this); + if (ui.removeObserve && !lib.node.observing.length) { + ui.removeObserve.remove(); + delete ui.removeObserve; + } + this.closed = true; + if (_status.waitingForPlayer) { + for (var i = 0; i < game.connectPlayers.length; i++) { + if (game.connectPlayers[i].playerid == this.id) { + game.connectPlayers[i].uninitOL(); + delete game.connectPlayers[i].playerid; + } + } + if (game.onlinezhu == this.id) { + game.onlinezhu = null; + } + game.updateWaiting(); + } + else if (lib.playerOL[this.id]) { + var player = lib.playerOL[this.id]; + player.setNickname(player.nickname + " - 离线"); + game.broadcast(function (player) { + player.setNickname(player.nickname + " - 离线"); + }, player); + player.unwait("ai"); + } + + if (window.isNonameServer) { + document.querySelector("#server_count").innerHTML = lib.node.clients.length; + } + return this; + } +} diff --git a/noname/library/element/control.js b/noname/library/element/control.js new file mode 100644 index 000000000..a206dcee2 --- /dev/null +++ b/noname/library/element/control.js @@ -0,0 +1,119 @@ +export class Control extends HTMLDivElement { + constructor() { + const nc = !ui.control.querySelector("div:not(.removing):not(.stayleft)"); + const controls = Array.isArray(arguments[0]) ? arguments[0] : Array.from(arguments); + const control = ui.create.div(".control"); + Object.setPrototypeOf(control, lib.element.Control.prototype); + ui.control.insertBefore(control, _status.createControl || ui.confirm); + controls.forEach(argument => { + if (argument == "nozoom") return; + if (typeof argument == "function") control.custom = argument; + else if (argument == "stayleft") { + control.stayleft = true; + control.classList.add("stayleft"); + } + else control.add(argument); + }); + ui.controls.unshift(control); + if (nc) ui.control.animate("nozoom", 100); + if (control.childNodes.length) { + control.style.transition = "opacity 0.5s"; + control.animate("controlpressdownx", 500); + ui.refresh(control); + if (!control.stayleft) control.style.transform = `translateX(-${control.offsetWidth / 2}px)`; + control.style.opacity = 1; + ui.refresh(control); + control.style.transition = ""; + } + + control.addEventListener(lib.config.touchscreen ? "touchend" : "click", ui.click.control2); + + if (lib.config.button_press) { + control.addEventListener(lib.config.touchscreen ? "touchstart" : "mousedown", function () { + if (this.classList.contains("disabled")) return; + this.classList.add("controlpressdown"); + if (typeof this._offset == "number") this.style.transform = `translateX(${this._offset}px) scale(0.97)`; + }); + control.addEventListener(lib.config.touchscreen ? "touchend" : "mouseup", function () { + this.classList.remove("controlpressdown"); + if (typeof this._offset == "number") this.style.transform = `translateX(${this._offset}px)`; + }); + } + + ui.updatec(); + return control; + } + open() { + ui.control.insertBefore(this, _status.createControl || ui.confirm); + ui.controls.unshift(this); + if (this.childNodes.length) { + this.style.transition = "opacity 0.5s"; + ui.refresh(this); + this.style.transform = "translateX(-" + (this.offsetWidth / 2) + "px)"; + this.style.opacity = 1; + ui.refresh(this); + this.style.transition = ""; + } + else { + this.animate("controlpressdownx", 500); + } + ui.updatec(); + return this; + } + add(item) { + var node = document.createElement("div"); + this.appendChild(node); + node.link = item; + node.innerHTML = get.translation(item); + node.addEventListener(lib.config.touchscreen ? "touchend" : "click", ui.click.control); + } + close() { + this.animate("controlpressdownx", 500); + + ui.controls.remove(this); + this.delete(); + + setTimeout(ui.updatec, 100); + + + if (ui.confirm == this) delete ui.confirm; + if (ui.skills == this) delete ui.skills; + if (ui.skills2 == this) delete ui.skills2; + if (ui.skills3 == this) delete ui.skills3; + } + replace() { + // this.animate("controlpressdownx",500); + if (this.replaceTransition === false) { + this.style.transitionProperty = "none"; + ui.refresh(this); + } + + while (this.childNodes.length) this.firstChild.remove(); + var i, controls; + if (Array.isArray(arguments[0])) controls = arguments[0]; + else controls = arguments; + delete this.custom; + for (i = 0; i < controls.length; i++) { + if (typeof controls[i] == "function") { + this.custom = controls[i]; + } + else { + this.add(controls[i]); + } + } + if (this.childNodes.length) { + var width = 0; + for (i = 0; i < this.childNodes.length; i++) width += this.childNodes[i].offsetWidth; + ui.refresh(this); + this.style.width = width + "px"; + } + ui.updatec(); + if (this.replaceTransition === false) { + var that = this; + setTimeout(function () { + that.style.transitionProperty = ""; + }, 200); + } + return this; + } +} diff --git a/noname/library/element/dialog.js b/noname/library/element/dialog.js new file mode 100644 index 000000000..3c880f8b8 --- /dev/null +++ b/noname/library/element/dialog.js @@ -0,0 +1,168 @@ +export class Dialog extends HTMLDivElement { + constructor() { + let hidden = false; + let noTouchScroll = false; + let forceButton = false; + let noForceButton = false; + const dialog = ui.create.div(".dialog"); + Object.setPrototypeOf(dialog, lib.element.Dialog.prototype); + dialog.contentContainer = ui.create.div(".content-container", dialog); + dialog.content = ui.create.div(".content", dialog.contentContainer); + dialog.bar1 = ui.create.div(".bar.top", dialog); + dialog.bar2 = ui.create.div(".bar.bottom", dialog); + dialog.buttons = []; + Array.from(arguments).forEach(argument => { + if (typeof argument == "boolean") dialog.static = argument; + else if (argument == "hidden") hidden = true; + else if (argument == "notouchscroll") noTouchScroll = true; + else if (argument == "forcebutton") forceButton = true; + else if (argument == "noforcebutton") noForceButton = true; + else dialog.add(argument); + }); + if (!hidden) dialog.open(); + if (!lib.config.touchscreen) dialog.contentContainer.onscroll = ui.update; + if (!noTouchScroll) { + dialog.contentContainer.ontouchstart = ui.click.dialogtouchStart; + dialog.contentContainer.ontouchmove = ui.click.touchScroll; + dialog.contentContainer.style.webkitOverflowScrolling = "touch"; + dialog.ontouchstart = ui.click.dragtouchdialog; + } + if (noForceButton) dialog.noforcebutton = true; + else if (forceButton) { + dialog.forcebutton = true; + dialog.classList.add("forcebutton"); + } + return dialog; + } + add(item, noclick, zoom) { + if (typeof item == "string") { + if (item.startsWith("###")) { + var items = item.slice(3).split("###"); + this.add(items[0], noclick, zoom); + this.addText(items[1], items[1].length <= 20, zoom); + } + else if (noclick) { + var strstr = item; + item = ui.create.div("", this.content); + item.innerHTML = strstr; + } + else { + item = ui.create.caption(item, this.content); + } + } + else if (get.objtype(item) == "div") { + this.content.appendChild(item); + } + else if (get.itemtype(item) == "cards") { + var buttons = ui.create.div(".buttons", this.content); + if (zoom) buttons.classList.add("smallzoom"); + this.buttons = this.buttons.concat(ui.create.buttons(item, "card", buttons, noclick)); + } + else if (get.itemtype(item) == "players") { + var buttons = ui.create.div(".buttons", this.content); + if (zoom) buttons.classList.add("smallzoom"); + this.buttons = this.buttons.concat(ui.create.buttons(item, "player", buttons, noclick)); + } + else if (item[1] == "textbutton") { + ui.create.textbuttons(item[0], this, noclick); + } + else { + var buttons = ui.create.div(".buttons", this.content); + if (zoom) buttons.classList.add("smallzoom"); + this.buttons = this.buttons.concat(ui.create.buttons(item[0], item[1], buttons, noclick)); + } + if (this.buttons.length) { + if (this.forcebutton !== false) this.forcebutton = true; + if (this.buttons.length > 3 || (zoom && this.buttons.length > 5)) { + this.classList.remove("forcebutton-auto"); + } + else if (!this.noforcebutton) { + this.classList.add("forcebutton-auto"); + } + } + ui.update(); + return item; + } + addText(str, center) { + if (str && str.startsWith("${str}`); + } + else { + this.add(`
${str}
`); + } + return this; + } + addSmall(item, noclick) { + return this.add(item, noclick, true); + } + addAuto(content) { + if (content && content.length > 4 && !this._hovercustomed) { + this.addSmall(content); + } + else { + this.add(content); + } + } + open() { + if (this.noopen) return; + for (var i = 0; i < ui.dialogs.length; i++) { + if (ui.dialogs[i] == this) { + this.show(); + this.refocus(); + ui.dialogs.remove(this); + ui.dialogs.unshift(this); + ui.update(); + return this; + } + if (ui.dialogs[i].static) ui.dialogs[i].unfocus(); + else ui.dialogs[i].hide(); + } + ui.dialog = this; + var translate; + if (lib.config.remember_dialog && lib.config.dialog_transform && !this.classList.contains("fixed")) { + translate = lib.config.dialog_transform; + this._dragtransform = translate; + this.style.transform = "translate(" + translate[0] + "px," + translate[1] + "px) scale(0.8)"; + } + else { + this.style.transform = "scale(0.8)"; + } + this.style.transitionProperty = "opacity,transform"; + this.style.opacity = 0; + ui.arena.appendChild(this); + ui.dialogs.unshift(this); + ui.update(); + ui.refresh(this); + if (lib.config.remember_dialog && lib.config.dialog_transform && !this.classList.contains("fixed")) { + this.style.transform = "translate(" + translate[0] + "px," + translate[1] + "px) scale(1)"; + } + else { + this.style.transform = "scale(1)"; + } + this.style.opacity = 1; + var that = this; + setTimeout(function () { + that.style.transitionProperty = ""; + }, 500); + return this; + } + close() { + ui.dialogs.remove(this); + this.delete(); + if (ui.dialogs.length > 0) { + ui.dialog = ui.dialogs[0]; + ui.dialog.show(); + ui.dialog.refocus(); + ui.update(); + } + // if(ui.arenalog){ + // ui.arenalog.classList.remove("withdialog"); + // } + return this; + } + setCaption(str) { + this.querySelector(".caption").innerHTML = str; + return this; + } +} diff --git a/noname/library/element/game-event-promise.js b/noname/library/element/game-event-promise.js new file mode 100644 index 000000000..5176015ac --- /dev/null +++ b/noname/library/element/game-event-promise.js @@ -0,0 +1,74 @@ +export class GameEventPromise extends Promise { + // 我谢谢你,这里是必须有的 + // 否则Promise的方法对其子类无效 + static get [Symbol.species]() { + return Promise; + } + /** + * @param { GameEvent } event + * @returns { Promise & GameEvent } + */ + constructor(event) { + super(resolve => { + // 设置为异步事件 + event.async = true; + // 事件结束后触发resolve + event.resolve = resolve; + // 如果父级事件也是一个异步的话,那应该立即执行这个事件的 + // 如果在AsyncFunction执行过程中在别的位置新建了一个异步事件,那也直接(等会set配置完)执行 + if (_status.event.next.includes(event) && _status.event.content instanceof AsyncFunction) { + if (_status.event != event) { + event.parent = _status.event; + _status.event = event; + game.getGlobalHistory("everything").push(event); + } + // 异步执行game.loop + // 不直接game.loop(event)是因为需要让别人可以手动set()和setContent() + // 再执行game.loop是因为原有的game.loop被await卡住了, + // 得新执行一个只执行这个异步事件的game.loop + Promise.resolve().then(() => game.loop(event)); + } + }); + return new Proxy(this, { + get(target, prop, receiver) { + const thisValue = Reflect.get(target, prop); + if (thisValue) { + if (typeof thisValue == "function") { + return thisValue.bind(target); + } + return thisValue; + } + const eventValue = Reflect.get(event, prop); + // 返回值如果是event,则修改为GameEventPromise类实例 + if (typeof eventValue == "function") return (function (...args) { + const returnValue = eventValue.call(event, ...args); + return returnValue == event ? receiver : returnValue; + }).bind(event); + return eventValue; + }, + set(target, prop, newValue) { + return Reflect.set(event, prop, newValue); + }, + deleteProperty(target, prop) { + return Reflect.deleteProperty(event, prop); + }, + defineProperty(target, prop, attributes) { + return Reflect.defineProperty(event, prop, attributes); + }, + has(target, prop) { + return Reflect.has(event, prop); + }, + ownKeys(target, prop) { + return Reflect.ownKeys(event, prop); + }, + }); + } + /** + * TODO: 实现debugger + */ + async debugger() { + return new Promise(resolve => { + resolve(null); + }); + } +} diff --git a/noname/library/element/game-event.js b/noname/library/element/game-event.js index 40733c345..d9d4694d8 100644 --- a/noname/library/element/game-event.js +++ b/noname/library/element/game-event.js @@ -7,7 +7,7 @@ export class GameEvent { * @param {false} [trigger] */ constructor(name, trigger) { - if (typeof name == 'string') { + if (typeof name == "string") { this.name = name; const gameEvent = Get.event(); @@ -43,9 +43,799 @@ export class GameEvent { static initialGameEvent() { return (new this).finish(); } + /** + * @param {keyof this} key + * @param {number} [value] + * @param {number} [baseValue] + */ + addNumber(key, value, baseValue) { + if (typeof value != "number") value = 0; + if (typeof this[key] == "number") this[key] += value; + else { + if (typeof baseValue != "number") baseValue = 0; + this[key] = baseValue + value; + } + return this; + } + /** + * @param {keyof this} key + * @param {number} [baseValue] + */ + decrease(key, baseValue) { + if (typeof this[key] == "number") this[key]--; + else this.subtractNumber(key, 1, baseValue); + return this; + } + /** + * @param {keyof this} key + * @param {number} [baseValue] + */ + increase(key, baseValue) { + if (typeof this[key] == "number") this[key]++; + else this.addNumber(key, 1, baseValue); + return this; + } + /** + * @param {keyof this} key + * @param {number} [value] + * @param {number} [baseValue] + */ + subtractNumber(key, value, baseValue) { + if (typeof value != "number") value = 0; + if (typeof this[key] == "number") this[key] -= value; + else { + if (typeof baseValue != "number") baseValue = 0; + this[key] = baseValue - value; + } + return this; + } + /** + * @param {Parameters[0]} type + * @param {GameEvent} event + * @param {{ + * state?: "begin" | "end"; + * }} option + * @returns {this} + */ + callHandler(type, event, option) { + if (this.hasHandler(type)) this.getHandler(type).forEach(handler => { + if (typeof handler == "function") handler(event, option); + }); + return this; + } + getDefaultHandlerType() { + const eventName = this.name; + if (eventName) return `on${eventName[0].toUpperCase()}${eventName.slice(1)}`; + } + /** + * @param {Parameters[0]} [type] + * @returns {((event: GameEvent, option: { + * state?: "begin" | "end"; + * }) => void)[]} + */ + getHandler(type) { + if (!type) type = this.getDefaultHandlerType(); + const currentHandler = this[type]; + if (!currentHandler) this[type] = []; + else if (!Array.isArray(currentHandler)) this[type] = [currentHandler]; + return this[type]; + } + /** + * @param {`on${Capitalize}`} [type] + */ + hasHandler(type) { + if (!type) type = this.getDefaultHandlerType(); + return Boolean(this[type] && this.getHandler(type).length); + } + /** + * @overload + * @param {...((event: GameEvent, option: { + * state?: "begin" | "end"; + * }) => void)[]} handlers + * @returns {number} + */ + /** + * @overload + * @param {Parameters[0]} type + * @param {...((event: GameEvent, option: { + * state?: "begin" | "end"; + * }) => void)[]} handlers + * @returns {number} + */ + pushHandler(type) { + return typeof type == "string" ? this.getHandler(type).push(...Array.from(arguments).slice(1)) : this.getHandler().push(...arguments); + } + changeToZero() { + this.num = 0; + this.numFixed = true; + return this; + } finish() { this.finished = true; return this; } + putStepCache(key, value) { + if (!this._stepCache) { + this._stepCache = {}; + } + this._stepCache[key] = value; + return this; + } + getStepCache(key) { + if (!this._stepCache) return undefined; + return this._stepCache[key]; + } + clearStepCache(key) { + if (key !== undefined && key !== null) { + delete this._stepCache[key]; + } + delete this._stepCache; + return this; + } + callFuncUseStepCache(prefix, func, params) { + if (typeof func != "function") return; + if (_status.closeStepCache) return func.apply(null, params); + var cacheKey = "[" + prefix + "]" + get.paramToCacheKey.apply(null, params); + var ret = this.getStepCache(cacheKey); + if (ret === undefined || ret === null) { + ret = func.apply(null, params); + this.putStepCache(cacheKey, ret); + } + return ret; + } + putTempCache(key1, key2, value) { + if (!this._tempCache) { + this._tempCache = {}; + } + if (!this._tempCache[key1]) { + this._tempCache[key1] = {}; + } + this._tempCache[key1][key2] = value; + return value; + } + getTempCache(key1, key2) { + if (!this._tempCache) { + return undefined; + } + if (!this._tempCache[key1]) { + return undefined; + } + return this._tempCache[key1][key2]; + } + cancel(arg1, arg2, notrigger) { + this.untrigger(arg1, arg2); + this.finish(); + if (notrigger != "notrigger") { + this.trigger(this.name + "Cancelled"); + if (this.player && lib.phaseName.contains(this.name)) this.player.getHistory("skipped").add(this.name); + } + return this; + } + neutralize(event) { + this.untrigger(); + this.finish(); + this._neutralized = true; + this.trigger("eventNeutralized"); + this._neutralize_event = event || _status.event; + return this; + } + unneutralize() { + this.untrigger(); + delete this._neutralized; + delete this.finished; + if (this.type == "card" && this.card && this.name == "sha") this.directHit = true; + return this; + } + goto(step) { + this.step = step - 1; + return this; + } + redo() { + this.step--; + return this; + } + setHiddenSkill(skill) { + if (!this.player) return this; + var hidden = this.player.hiddenSkills.slice(0); + game.expandSkills(hidden); + if (hidden.contains(skill)) this.set("hsskill", skill); + return this; + } + set(key, value) { + if (arguments.length == 1 && Array.isArray(arguments[0])) { + for (var i = 0; i < arguments[0].length; i++) { + if (Array.isArray(arguments[0][i])) { + this.set(arguments[0][i][0], arguments[0][i][1]); + } + } + } + else { + if (typeof key != "string") { + console.log("warning: using non-string object as event key"); + console.log(key, value); + console.log(_status.event); + } + this[key] = value; + this._set.push([key, value]); + } + return this; + } + /** + * @param {ArrayLike | Function | keyof typeof lib.element.content} item + */ + setContent(item) { + switch (typeof item) { + case "object": + case "function": + if (item instanceof AsyncFunction) { + this.content = item; + } + else this.content = lib.init.parsex(item); + break; + default: + try { + if (!lib.element.content[item]._parsed) { + lib.element.content[item] = lib.init.parsex(lib.element.content[item]); + lib.element.content[item]._parsed = true; + } + } + catch (_) { + throw new Error(`Content ${item} may not exist.\nlib.element.content[${item}] = ${lib.element.content[item]}`); + } + this.content = lib.element.content[item]; + break; + } + return this; + } + getLogv() { + for (var i = 1; i <= 3; i++) { + var event = this.getParent(i); + if (event && event.logvid) return event.logvid; + } + return null; + } + send() { + this.player.send(function (name, args, set, event, skills) { + game.me.applySkills(skills); + var next = game.me[name].apply(game.me, args); + for (var i = 0; i < set.length; i++) { + next.set(set[i][0], set[i][1]); + } + if (next._backupevent) { + next.backup(next._backupevent); + } + next._modparent = event; + game.resume(); + }, this.name, this._args || [], this._set, + get.stringifiedResult(this.parent), get.skillState(this.player)); + this.player.wait(); + game.pause(); + return this; + } + resume() { + delete this._cardChoice; + delete this._targetChoice; + delete this._skillChoice; + return this; + } + getParent(level, forced) { + var parent, historys = []; + if (this._modparent && game.online) { + parent = this._modparent; + } + else { + parent = this.parent; + } + var toreturn = {}; + if (typeof level == "string" && forced == true) { + toreturn = null; + } + if (!parent) return toreturn; + if (typeof level == "number") { + for (var i = 1; i < level; i++) { + if (!parent) return toreturn; + parent = parent.parent; + } + } + else if (typeof level == "string") { + while (true) { + if (!parent) return toreturn; + historys.push(parent); + if (parent.name == level) return parent; + parent = parent.parent; + if (historys.contains(parent)) return toreturn; + } + } + if (toreturn === null) { + return null; + } + return parent; + } + getTrigger() { + return this.getParent()._trigger; + } + getRand(name) { + if (name) { + if (!this._rand_map) this._rand_map = {}; + if (!this._rand_map[name]) this._rand_map[name] = Math.random(); + return this._rand_map[name]; + } + if (!this._rand) this._rand = Math.random(); + return this._rand; + } + insert(content, map) { + const next = new lib.element.GameEvent(`${this.name}Inserted`, false); + this.next.push(next); + next.setContent(content); + Object.entries(map).forEach(entry => next.set(entry[0], entry[1])); + return next; + } + insertAfter(content, map) { + const next = new lib.element.GameEvent(`${this.name}Inserted`, false); + this.after.push(next); + next.setContent(content); + Object.entries(map).forEach(entry => next.set(entry[0], entry[1])); + return next; + } + backup(skill) { + this._backup = { + filterButton: this.filterButton, + selectButton: this.selectButton, + filterTarget: this.filterTarget, + selectTarget: this.selectTarget, + filterCard: this.filterCard, + selectCard: this.selectCard, + position: this.position, + forced: this.forced, + fakeforce: this.fakeforce, + _aiexclude: this._aiexclude, + complexSelect: this.complexSelect, + complexCard: this.complexCard, + complexTarget: this.complexTarget, + _cardChoice: this._cardChoice, + _targetChoice: this._targetChoice, + _skillChoice: this._skillChoice, + ai1: this.ai1, + ai2: this.ai2, + filterOk: this.filterOk, + } + if (skill) { + var info = get.info(skill); + this.skill = skill; + this._aiexclude = []; + if (typeof info.viewAs == "function") { + if (info.filterButton != undefined) this.filterButton = get.filter(info.filterButton); + if (info.selectButton != undefined) this.selectButton = info.selectButton; + if (info.filterTarget != undefined) this.filterTarget = get.filter(info.filterTarget); + if (info.selectTarget != undefined) this.selectTarget = info.selectTarget; + if (info.filterCard != undefined) { + if (info.ignoreMod) this.ignoreMod = true; + this.filterCard2 = get.filter(info.filterCard); + this.filterCard = function (card, player, event) { + var evt = event || _status.event; + if (!evt.ignoreMod && player) { + var mod = game.checkMod(card, player, "unchanged", "cardEnabled2", player); + if (mod != "unchanged") return mod; + } + return get.filter(evt.filterCard2).apply(this, arguments); + }; + } + if (info.filterOk == undefined) { + this.filterOk = function () { + var evt = _status.event; + var card = get.card(), player = get.player(); + var filter = evt._backup.filterCard; + if (filter && !filter(card, player, evt)) return false; + if (evt._backup.filterOk) return evt._backup.filterOk(); + return true; + }; + } + else this.filterOk = info.filterOk; + if (info.selectCard != undefined) this.selectCard = info.selectCard; + if (info.position != undefined) this.position = info.position; + //if(info.forced!=undefined) this.forced=info.forced; + if (info.complexSelect != undefined) this.complexSelect = info.complexSelect; + if (info.complexCard != undefined) this.complexCard = info.complexCard; + if (info.complexTarget != undefined) this.complexTarget = info.complexTarget; + if (info.ai1 != undefined) this.ai1 = info.ai1; + if (info.ai2 != undefined) this.ai2 = info.ai2; + } + else if (info.viewAs) { + if (info.filterButton != undefined) this.filterButton = get.filter(info.filterButton); + if (info.selectButton != undefined) this.selectButton = info.selectButton; + if (info.filterTarget != undefined) this.filterTarget = get.filter(info.filterTarget); + if (info.selectTarget != undefined) this.selectTarget = info.selectTarget; + if (info.filterCard != undefined) { + if (info.ignoreMod) this.ignoreMod = true; + this.filterCard2 = get.filter(info.filterCard); + this.filterCard = function (card, player, event) { + var evt = event || _status.event; + if (!evt.ignoreMod && player) { + var mod = game.checkMod(card, player, "unchanged", "cardEnabled2", player); + if (mod != "unchanged") return mod; + } + return get.filter(evt.filterCard2).apply(this, arguments); + }; + } + if (info.filterOk == undefined) { + this.filterOk = function () { + var evt = _status.event; + var card = get.card(), player = get.player(); + var filter = evt._backup.filterCard; + if (filter && !filter(card, player, evt)) return false; + if (evt._backup.filterOk) return evt._backup.filterOk() + return true; + }; + } + else this.filterOk = info.filterOk; + if (info.selectCard != undefined) this.selectCard = info.selectCard; + if (info.position != undefined) this.position = info.position; + //if(info.forced!=undefined) this.forced=info.forced; + if (info.complexSelect != undefined) this.complexSelect = info.complexSelect; + if (info.complexCard != undefined) this.complexCard = info.complexCard; + if (info.complexTarget != undefined) this.complexTarget = info.complexTarget; + if (info.ai1 != undefined) this.ai1 = info.ai1; + if (info.ai2 != undefined) this.ai2 = info.ai2; + } + else { + this.filterButton = info.filterButton ? get.filter(info.filterButton) : undefined; + this.selectButton = info.selectButton; + this.filterTarget = info.filterTarget ? get.filter(info.filterTarget) : undefined; + this.selectTarget = info.selectTarget; + this.filterCard = info.filterCard ? get.filter(info.filterCard) : undefined; + this.selectCard = info.selectCard; + this.position = info.position; + //this.forced=info.forced; + this.complexSelect = info.complexSelect; + this.complexCard = info.complexCard; + this.complexTarget = info.complexTarget; + if (info.ai1 != undefined) this.ai1 = info.ai1; + if (info.ai2 != undefined) this.ai2 = info.ai2; + this.filterOk = info.filterOk; + } + delete this.fakeforce; + } + delete this._cardChoice; + delete this._targetChoice; + delete this._skillChoice; + return this; + } + restore() { + if (this._backup) { + this.filterButton = this._backup.filterButton; + this.selectButton = this._backup.selectButton; + this.filterTarget = this._backup.filterTarget; + this.selectTarget = this._backup.selectTarget; + this.filterCard = this._backup.filterCard; + this.selectCard = this._backup.selectCard; + this.position = this._backup.position; + this.forced = this._backup.forced; + this.fakeforce = this._backup.fakeforce; + this._aiexclude = this._backup._aiexclude; + this.complexSelect = this._backup.complexSelect; + this.complexCard = this._backup.complexCard; + this.complexTarget = this._backup.complexTarget; + this.ai1 = this._backup.ai1; + this.ai2 = this._backup.ai2; + this._cardChoice = this._backup._cardChoice; + this._targetChoice = this._backup._targetChoice; + this._skillChoice = this._backup._skillChoice; + this.filterOk = this._backup.filterOk; + } + delete this.skill; + delete this.ignoreMod; + delete this.filterCard2; + return this; + } + isMine() { + return (this.player && this.player == game.me && !_status.auto && !this.player.isMad() && !game.notMe); + } + isOnline() { + return (this.player && this.player.isOnline()); + } + notLink() { + return this.getParent().name != "_lianhuan" && this.getParent().name != "_lianhuan2"; + } + isPhaseUsing(player) { + var evt = this.getParent("phaseUse"); + if (!evt || evt.name != "phaseUse") return false; + return !player || player == evt.player; + } + addTrigger(skills, player) { + if (!player || !skills) return this; + let evt = this; + if (typeof skills == "string") skills = [skills]; + game.expandSkills(skills); + while (true) { + evt = evt.getParent("arrangeTrigger"); + if (!evt || evt.name != "arrangeTrigger" || !evt.doingList) return this; + const doing = (() => { + if (evt.doing && evt.doing.player == player) return evt.doing; + return evt.doingList.find(i => i.player == player); + })(); + // if(!doing) return this; + const firstDo = evt.doingList.find(i => i.player == "firstDo"); + const lastDo = evt.doingList.find(i => i.player == "lastDo"); + + for (const skill of skills) { + const info = lib.skill[skill]; + if (!info.trigger) continue; + if (!Object.keys(info.trigger).some(i => { + if (Array.isArray(info.trigger[i])) return info.trigger[i].includes(evt.triggername); + return info.trigger[i] == evt.triggername; + })) continue; + + const playerMap = game.players.concat(game.dead).sortBySeat(evt.starter); + const priority = get.priority(skill); + const toadd = { + skill: skill, + player: player, + priority: priority, + } + const map = info.firstDo ? firstDo : info.lastDo ? lastDo : doing; + if (!map) continue; + if (map.doneList && map.doneList.some(i => i.skill == toadd.skill && i.player == toadd.player)) continue; + if (map.todoList.some(i => i.skill == toadd.skill && i.player == toadd.player)) continue; + map.todoList.add(toadd); + map.todoList.sort((a, b) => (b.priority - a.priority) || (playerMap.indexOf(a) - playerMap.indexOf(b))); + } + } + } + removeTrigger(skills, player) { + if (!player || !skills) return this; + let evt = this; + if (typeof skills == "string") skills = [skills]; + game.expandSkills(skills); + while (true) { + evt = evt.getParent("arrangeTrigger"); + if (!evt || evt.name != "arrangeTrigger" || !evt.doingList) return this; + const doing = (() => { + if (evt.doing && evt.doing.player == player) return evt.doing; + return evt.doingList.find(i => i.player == player); + })(); + // if(!doing) return this; + const firstDo = evt.doingList.find(i => i.player == "firstDo"); + const lastDo = evt.doingList.find(i => i.player == "lastDo"); + + for (const skill of skills) { + [doing, firstDo, lastDo].forEach(map => { + if (!map) return; + const toremove = map.todoList.filter(i => i.skill == skill && i.player == player); + if (toremove.length > 0) map.todoList.removeArray(toremove); + }); + } + } + } + trigger(name) { + if (_status.video) return this; + if ((this.name === "gain" || this.name === "lose") && !_status.gameDrawed) return this; + if (name === "gameDrawEnd") _status.gameDrawed = true; + if (name === "gameStart") { + lib.announce.publish("gameStart", {}); + if (_status.brawl && _status.brawl.gameStart) _status.brawl.gameStart(); + if (lib.config.show_cardpile) ui.cardPileButton.style.display = ""; + _status.gameStarted = true; + game.showHistory(); + } + if (!lib.hookmap[name] && !lib.config.compatiblemode) return this; + if (!game.players || !game.players.length) return this; + const event = this; + let start = [_status.currentPhase, event.source, event.player, game.me, game.players[0]].find(i => get.itemtype(i) == "player"); + if (!start) return this; + if (!game.players.includes(start) && !game.dead.includes(start)) start = game.findNext(start); + const firstDo = { + player: "firstDo", + todoList: [], + doneList: [], + } + const lastDo = { + player: "lastDo", + todoList: [], + doneList: [], + } + const doingList = []; + let allbool = false; + const roles = ["player", "source", "target", "global"]; + const playerMap = game.players.concat(game.dead).sortBySeat(start); + function addList(skill, player) { + if (this.listAdded[skill]) return; + this.listAdded[skill] = true; + if (player.forbiddenSkills[skill]) return; + if (player.disabledSkills[skill]) return; + + const info = lib.skill[skill]; + const list = info.firstDo ? firstDo.todoList : info.lastDo ? lastDo.todoList : this.todoList; + const priority = get.priority(skill); + list.push({ + skill: skill, + player: player, + priority: priority, + }); + if (typeof list.player == "string") list.sort((a, b) => (b.priority - a.priority) || (playerMap.indexOf(a) - playerMap.indexOf(b))); + else list.sort((a, b) => b.priority - a.priority); + allbool = true; + } + let player = start; + do { + const doing = { + player: player, + todoList: [], + doneList: [], + listAdded: {}, + addList: addList, + } + const notemp = player.skills.slice(); + for (const j in player.additionalSkills) { + if (!j.startsWith("hidden:")) notemp.addArray(player.additionalSkills[j]); + } + for (const skill in player.tempSkills) { + if (notemp.includes(skill)) continue; + const expire = player.tempSkills[skill]; + if (typeof expire === "function" && expire(event, player, name)) { + delete player.tempSkills[skill]; + player.removeSkill(skill); + } + else if (get.objtype(expire) === "object") { + for (const role of roles) { + if (role !== "global" && player !== event[role]) continue; + if (expire[role] === name || (Array.isArray(expire[role]) && expire[role].includes(name))) { + delete player.tempSkills[skill]; + player.removeSkill(skill); + } + } + } + } + if (lib.config.compatiblemode) { + let skills = player.getSkills("invisible").concat(lib.skill.global); + game.expandSkills(skills); + for (const skill of skills) { + const info = get.info(skill); + if (!info || !info.trigger) continue; + if (roles.some(role => { + if (info.trigger[role] === name) return true; + if (Array.isArray(info.trigger[role]) && info.trigger[role].includes(name)) return true; + })) doing.addList(skill, player); + } + } + else { + for (const role of roles) { + const globalTriggername = role + "_" + name; + if (lib.hook.globalskill[globalTriggername]) { + lib.hook.globalskill[globalTriggername].forEach(skill => doing.addList(skill, player)); + } + const triggername = player.playerid + "_" + role + "_" + name; + if (lib.hook[triggername]) { + lib.hook[triggername].forEach(skill => doing.addList(skill, player)); + } + } + } + delete doing.listAdded; + delete doing.addList; + doingList.push(doing); + player = player.nextSeat; + } while (player && player !== start) + doingList.unshift(firstDo); + doingList.push(lastDo); + // console.log(name,event.player,doingList.map(i=>({player:i.player,todoList:i.todoList.slice(),doneList:i.doneList.slice()}))) + + if (allbool) { + var next = game.createEvent("arrangeTrigger", false, event); + next.setContent("arrangeTrigger"); + next.doingList = doingList; + next._trigger = event; + next.triggername = name; + next.starter = start; + event._triggering = next; + } + return this; + } + untrigger(all, player) { + if (typeof all == "undefined") all = true; + var evt = this._triggering; + if (all) { + if (evt && evt.doingList) { + evt.doingList.forEach(doing => doing.todoList = []); + evt.list = []; + if (evt.doing) evt.doing.todoList = []; + } + this._triggered = 5; + } + else if (player) { + this._notrigger.add(player); + if (!evt || !evt.doingList) return this; + const doing = evt.doingList.find(doing => doing.player == player); + if (doing) doing.todoList = []; + } + return this; + } + /** + * @returns {never} + */ + typeAnnotation() { + /** + * @type {Player} + */ + this.source; + /** + * @type {Player} + */ + this.player; + /** + * @type {Player} + */ + this.target; + /** + * @type {Player[]} + */ + this.targets; + /** + * @type {Card} + */ + this.card; + /** + * @type {Card[]} + */ + this.cards; + /** + * @type {string} + */ + this.skill; + /** + * @type {boolean} + */ + this.forced; + /** + * @type {number} + */ + this.num; + /** + * @type {GameEvent} + */ + this._trigger; + /** + * @type {Record} + */ + this._result; + /** + * @type {number} + */ + this.baseDamage; + /** + * @type {Player} + */ + this.customSource; + /** + * @type {number} + */ + this.extraDamage; + /** + * @type {string} + */ + this.nature; + /** + * @type {boolean} + */ + this.notrigger; + /** + * @type {number} + */ + this.original_num; + /** + * @type {boolean} + */ + this.unreal; + throw new Error("Do not call this method"); + } + /** + * 事件转为Promise化 + * + * @returns { Promise & GameEvent } + */ + toPromise() { + if (this.async && this.resolve) { + throw new TypeError("This event has been converted into a promise"); + } + return new lib.element.GameEventPromise(this); + } } diff --git a/noname/library/element/node-ws.js b/noname/library/element/node-ws.js new file mode 100644 index 000000000..9a16ee9ca --- /dev/null +++ b/noname/library/element/node-ws.js @@ -0,0 +1,17 @@ +export class NodeWS { + /** + * @param {string} id + */ + constructor(id) { + this.wsid = id; + } + send(message) { + game.send("server", "send", this.wsid, message); + } + on(type, func) { + this["on" + type] = func; + } + close() { + game.send("server", "close", this.wsid); + } +} diff --git a/noname/library/element/player.js b/noname/library/element/player.js index c5810f777..c6092efd0 100644 --- a/noname/library/element/player.js +++ b/noname/library/element/player.js @@ -1 +1,9436 @@ -export class Player { } +export class Player { + /** + * @param {HTMLDivElement} [position] + * @param {true} [noclick] + */ + constructor(position, noclick) { + /** + * @type {Player} + */ + const player = ui.create.div(".player", position); + Object.setPrototypeOf(player, lib.element.Player.prototype); + player.build(noclick); + return player; + } + build(noclick) { + let player = this; + player.buildNode(); + player.buildProperty(); + player.buildExtra(); + player.buildEventListener(noclick); + } + buildNode() { + let player = this; + const node = player.node = { + avatar: ui.create.div(".avatar", player, ui.click.avatar).hide(), + avatar2: ui.create.div(".avatar2", player, ui.click.avatar2).hide(), + turnedover: ui.create.div(".turned", "
翻面
", player), + framebg: ui.create.div(".framebg", player), + intro: ui.create.div(".intro", player), + identity: ui.create.div(".identity", player), + hp: ui.create.div(".hp", player), + name: ui.create.div(".name", player), + name2: ui.create.div(".name.name2", player), + nameol: ui.create.div(".nameol", player), + count: ui.create.div(".count", player).hide(), + equips: ui.create.div(".equips", player).hide(), + judges: ui.create.div(".judges", player), + marks: ui.create.div(".marks", player), + chain: ui.create.div(".chain", "
", player), + handcards1: ui.create.div(".handcards"), + handcards2: ui.create.div(".handcards"), + expansions: ui.create.div(".expansions") + }; + node.expansions.style.display = "none"; + const chainLength = game.layout == "default" ? 64 : 40; + for (let repetition = 0; repetition < chainLength; repetition++) { + ui.create.div(node.chain.firstChild, ".cardbg").style.transform = `translateX(${repetition * 5 - 5}px)`; + } + node.action = ui.create.div(".action", node.avatar); + } + buildExtra() { + let player = this; + let node = player.node; + node.link = player.mark(" ", { + mark: get.linkintro + }); + node.link.firstChild.setBackgroundImage("image/card/tiesuo_mark.png"); + node.link.firstChild.style.backgroundSize = "cover"; + ui.create.div(node.identity); + } + buildProperty() { + let player = this; + player.phaseNumber = 0; + player.skipList = []; + player.skills = []; + player.invisibleSkills = []; + player.initedSkills = []; + player.additionalSkills = {}; + player.disabledSkills = {}; + player.hiddenSkills = []; + player.awakenedSkills = []; + player.forbiddenSkills = {}; + player.popups = []; + player.damagepopups = []; + player.judging = []; + player.stat = [{ + card: {}, + skill: {} + }]; + player.actionHistory = [{ + useCard: [], + respond: [], + skipped: [], + lose: [], + gain: [], + sourceDamage: [], + damage: [], + custom: [], + useSkill: [] + }]; + player.tempSkills = {}; + player.storage = {}; + player.marks = {}; + player.expandedSlots = {}; + player.disabledSlots = {}; + player.ai = { + friend: [], + enemy: [], + neutral: [], + handcards: { + global: [], + source: [], + viewed: [] + } + }; + player.queueCount = 0; + player.outCount = 0; + /** + * 这部分应该用d.ts写。目前只给出大概类型 + * @type { {[key in keyof Player]: (...args) => Promise & GameEvent} } + */ + player.promises = new Proxy({}, { + get(target, prop) { + const eventKeys = Object.keys(lib.element.player).filter(key => typeof lib.element.player[key] == "function"); + if (eventKeys.includes(prop)) { + return function (...args) { + /** @type { GameEvent } */ + const event = player[prop](...args); + return event.toPromise(); + }; + } + } + }); + } + buildEventListener(noclick) { + let player = this; + let node = player.node; + if (noclick) player.noclick = true; + else { + player.addEventListener(lib.config.touchscreen ? "touchend" : "click", ui.click.target); + node.identity.addEventListener(lib.config.touchscreen ? "touchend" : "click", ui.click.identity); + if (lib.config.touchscreen) player.addEventListener("touchstart", ui.click.playertouchstart); + } + } + //新函数 + changeFury(amount, limit) { + if (typeof this.storage.stratagem_fury != "number") this.storage.stratagem_fury = 0; + if (!amount) return; + const furyBefore = this.storage.stratagem_fury; + if (limit === true && typeof _status.stratagemFuryMax == "number") this.storage.stratagem_fury = Math.min(Math.max(furyBefore + amount, 0), _status.stratagemFuryMax); + else this.storage.stratagem_fury = Math.max(furyBefore + amount, 0); + const difference = this.storage.stratagem_fury - furyBefore; + if (!difference) return; + game.log(this, difference > 0 ? "获得了" : "失去了", get.cnNumber(Math.abs(difference)), "点", "#r怒气"); + this.markSkill("stratagem_fury"); + } + /** + * version 1.7 + * + * 链式创建一次性技能的api。 + * + * 使用者只需要关注技能的效果,而不是技能的本身。 + * + * v1.7 可传递作用域 + * @example + * ```js + * (function () { + * let _var = 1; + * let me = player; + * player.when("drawAfter") + * .apply(code => eval(code)) + * .then(() => console.log(_var)) + * .then("me.gainMaxHp(5)"); + * })(); + * ``` + */ + when() { + if (!_status.postReconnect.player_when) _status.postReconnect.player_when = [ + function (map) { + "use strict"; + for (let i in map) { + lib.skill[i] = { + charlotte: true, + forced: true, + popup: false, + } + if (typeof map[i] == "string") lib.translate[i] = map[i]; + } + }, {} + ]; + let triggerNames = Array.from(arguments); + let trigger; + if (triggerNames.length == 0) throw "player.when的参数数量应大于0"; + //add other triggerNames + //arguments.length = 1 + if (triggerNames.length == 1) { + //以下两种情况: + //triggerNames = [ ["xxAfter", ...args] ] + //triggerNames = [ "xxAfter" ] + if (Array.isArray(triggerNames[0]) || typeof triggerNames[0] == "string") trigger = { player: triggerNames[0] }; + //triggerNames = [ {player:"xxx"} ] + else if (get.is.object(triggerNames[0])) trigger = triggerNames[0]; + } + //arguments.length > 1 + else { + //triggerNames = [ "xxAfter", "yyBegin" ] + if (triggerNames.every(t => typeof t == "string")) trigger = { player: triggerNames }; + //triggerNames = [ {player: "xxAfter"}, {global: "yyBegin"} ] + //此处不做特殊的合并处理,由使用者自行把握,同名属性后者覆盖前者 + else if (triggerNames.every(t => get.is.object(t))) trigger = triggerNames.reduce((pre, cur) => Object.assign(pre, cur)); + } + if (!trigger) throw "player.when传参数类型错误:" + triggerNames; + let skillName; + do { + skillName = "player_when_" + Math.random().toString(36).slice(-8); + } while (lib.skill[skillName] != null); + const after = `${skillName}After`; + if (!trigger.player) trigger.player = after; + else if (Array.isArray(trigger.player)) trigger.player.add(after); + else if (typeof trigger.player == "string") trigger.player = [trigger.player, after]; + const vars = {}; + /** + * 作用域 + * @type { (code: string) => any } + */ + let scope; + let skill = { + trigger: trigger, + forced: true, + charlotte: true, + popup: false, + //必要条件 + filterFuns: [], + //充分条件 + filter2Funs: [], + contentFuns: [], + //外部变量 + get vars() { + return vars; + }, + get filter() { + return (event, player, name) => { + if (name == `${skillName}After`) { + skill.popup = false; + return true; + } + return skill.filterFuns.every(fun => Boolean(fun(event, player, name))) && + skill.filter2(event, player, name); + } + }, + get filter2() { + return (event, player, name) => { + return skill.filter2Funs.length == 0 || + skill.filter2Funs.some(fun => Boolean(fun(event, player, name))); + }; + } + }; + const warnVars = ["event", "step", "source", "player", "target", "targets", + "card", "cards", "skill", "forced", "num", "trigger", "result"]; + const errVars = ["_status", "lib", "game", "ui", "get", "ai"]; + const createContent = () => { + let varstr = ""; + for (const key in vars) { + if (warnVars.includes(key)) console.warn(`Variable "${key}" should not be referenced by vars objects`); + if (errVars.includes(key)) throw new Error(`Variable "${key}" should not be referenced by vars objects`); + varstr += `var ${key}=lib.skill["${skillName}"].vars["${key}"];\n`; + } + let str = ` + function content(){ + ${varstr}if(event.triggername=="${skillName}After"){ + player.removeSkill("${skillName}"); + delete lib.skill["${skillName}"]; + delete lib.translate["${skillName}"]; + return event.finish(); + } + `; + for (let i = 0; i < skill.contentFuns.length; i++) { + const fun2 = skill.contentFuns[i]; + const a = fun2.toString(); + //防止传入()=>xxx的情况 + const begin = a.indexOf("{") == a.indexOf("}") && a.indexOf("{") == -1 && a.indexOf("=>") > -1 ? a.indexOf("=>") + 2 : a.indexOf("{") + 1; + const str2 = a.slice(begin, a.lastIndexOf("}") != -1 ? a.lastIndexOf("}") : undefined).trim(); + str += `"step ${i}"\n\t${str2}\n\t`; + } + skill.content = lib.init.parsex((scope || eval)(str + `\n};content;`), scope); + skill.content._parsed = true; + }; + Object.defineProperty(lib.skill, skillName, { + configurable: true, + //这类技能不需要被遍历到 + enumerable: false, + writable: true, + value: skill + }); + game.broadcast(function (skillName) { + Object.defineProperty(lib.skill, skillName, { + configurable: true, + enumerable: false, + writable: true, + value: { + forced: true, + charlotte: true, + popup: false, + vars: {}, + } + }); + }, skillName); + this.addSkill(skillName); + _status.postReconnect.player_when[1][skillName] = true; + return { + filter(fun) { + if (lib.skill[skillName] != skill) throw `This skill has been destroyed`; + skill.filterFuns.push(fun); + return this; + }, + removeFilter(fun) { + if (lib.skill[skillName] != skill) throw `This skill has been destroyed`; + skill.filterFuns.remove(fun); + return this; + }, + filter2(fun) { + if (lib.skill[skillName] != skill) throw `This skill has been destroyed`; + skill.filter2Funs.push(fun); + return this; + }, + removeFilter2(fun) { + if (lib.skill[skillName] != skill) throw `This skill has been destroyed`; + skill.filter2Funs.remove(fun); + return this; + }, + then(fun) { + if (lib.skill[skillName] != skill) throw `This skill has been destroyed`; + skill.contentFuns.push(fun); + createContent(); + return this; + }, + popup(str) { + if (lib.skill[skillName] != skill) throw `This skill has been destroyed`; + if (typeof str == "string") skill.popup = str; + return this; + }, + translation(translation) { + if (lib.skill[skillName] != skill) throw `This skill has been destroyed`; + if (typeof translation == "string") { + _status.postReconnect.player_when[1][skillName] = translation; + game.broadcastAll((skillName, translation) => lib.translate[skillName] = translation, skillName, translation) + } + return this; + }, + assign(obj) { + if (lib.skill[skillName] != skill) throw `This skill has been destroyed`; + if (typeof obj == "object" && obj !== null) Object.assign(skill, obj); + return this; + }, + vars(arg) { + if (lib.skill[skillName] != skill) throw `This skill has been destroyed`; + if (!get.is.object(arg)) throw "vars的第一个参数必须为对象"; + Object.assign(vars, arg); + createContent(); + return this; + }, + /** + * 传递外部作用域 + * + * 一般是传递一个 code=>eval(code) 函数 + * + * 传递后可在then中使用外部变量(vars的上位替代) + * + * @param {Function} _scope + */ + apply(_scope) { + if (lib.skill[skillName] != skill) throw `This skill has been destroyed`; + scope = _scope; + if (skill.contentFuns.length > 0) createContent(); + return this; + } + }; + } + //让一名角色明置一些手牌 + addShownCards() { + const cards = [], tags = []; + for (const argument of arguments) { + const type = get.itemtype(argument); + if (type == "cards") cards.addArray(argument); + else if (type == "card") cards.add(argument); + else if (typeof argument == "string" && argument.startsWith("visible_")) tags.add(argument); + } + if (!cards.length || !tags.length) return; + const next = game.createEvent("addShownCards", false); + next.player = this; + next._cards = cards; + next.gaintag = tags; + next.setContent("addShownCards"); + return next; + } + hideShownCards() { + const cards = [], tags = []; + for (const argument of arguments) { + const type = get.itemtype(argument); + if (type == "cards") cards.addArray(argument); + else if (type == "card") cards.add(argument); + else if (typeof argument == "string" && argument.startsWith("visible_")) tags.add(argument); + } + if (!cards.length) return; + const next = game.createEvent("hideShownCards", false); + next.player = this; + next._cards = cards; + next.gaintag = tags; + next.setContent("hideShownCards"); + return next; + } + //获取角色所有的明置手牌 + getShownCards() { + return this.getCards("h", function (card) { + return get.is.shownCard(card); + }); + } + //获取该角色被other所知的牌。 + getKnownCards(other, filter) { + if (!other) other = _status.event.player; + if (!other) other = this; + if (!filter) filter = (card) => { return true }; + return this.getCards("h", function (card) { + return card.isKnownBy(other) && filter(card); + }); + } + //判断此角色的手牌是否已经被看光了。 + isAllCardsKnown(other) { + if (!other) other = _status.event.player; + if (!other) other = this; + return this.countCards("h", function (card) { + return !card.isKnownBy(other); + }) == 0; + } + //判断此角色是否有被知的牌。 + hasKnownCards(other, filter) { + if (!other) other = _status.event.player; + if (!other) other = this; + if (!filter) filter = (card) => { return true }; + return this.countCards("h", function (card) { + return card.isKnownBy(other) && filter(card); + }) > 0; + } + //数此角色被知道的牌。 + countKnownCards(other, filter) { + return this.getKnownCards(other, filter).length; + } + //Execute the delay card effect + //执行延时锦囊牌效果 + executeDelayCardEffect(card, target, judge, judge2) { + const executeDelayCardEffect = game.createEvent("executeDelayCardEffect"); + executeDelayCardEffect.player = this; + executeDelayCardEffect.target = target || this; + if (typeof card == "string") { + const virtualCard = executeDelayCardEffect.card = ui.create.card(); + virtualCard._destroy = true; + virtualCard.expired = true; + const info = lib.card[card]; + virtualCard.init(["", "", card, info && info.cardnature]); + } + else if (get.itemtype(card) == "card") executeDelayCardEffect.card = card; + else _status.event.next.remove(executeDelayCardEffect); + executeDelayCardEffect.judge = judge; + executeDelayCardEffect.judge2 = judge2; + executeDelayCardEffect.setContent("executeDelayCardEffect"); + executeDelayCardEffect._args = Array.from(arguments); + return executeDelayCardEffect; + } + //Check if the card does not count toward hand limit + //检测此牌是否不计入手牌上限 + canIgnoreHandcard(card) { + return lib.filter.ignoredHandcard(card, this); + } + //Gift + //赠予 + gift(cards, target) { + const gift = game.createEvent("gift"); + gift.player = this; + gift.target = target; + const isArray = Array.isArray(cards); + if (cards && !isArray) gift.cards = [cards]; + else if (isArray && cards.length) gift.cards = cards; + else _status.event.next.remove(gift); + gift.deniedGifts = []; + gift.setContent("gift"); + gift._args = Array.from(arguments); + return gift; + } + //Check if the player can gift the card + //检测角色是否能赠予此牌 + canGift(card, target, strict) { + return lib.filter.cardGiftable(card, this, target, strict); + } + //Check if the player refuses gifts + //检测角色是否拒绝赠予 + refuseGifts(card, player) { + return this.hasSkillTag("refuseGifts", null, { + player: player, + card: card + }); + } + //Gift AI related + //赠予AI相关 + getGiftAIResultTarget(card, target) { + if (!card || target.refuseGifts(card, this)) return 0; + if (get.type(card, false) == "equip") return get.effect(target, card, target, target); + if (card.name == "du") return this.hp > target.hp ? -1 : 0; + if (target.hasSkillTag("nogain")) return 0; + return Math.max(1, get.value(card, this) - get.value(card, target)); + } + getGiftEffect(card, target) { + return this.getGiftAIResultTarget(card, target) * get.attitude(this, target); + } + //Recast + //重铸 + recast(cards, recastingLose, recastingGain) { + const recast = game.createEvent("recast"); + recast.player = this; + const isArray = Array.isArray(cards); + if (cards && !isArray) recast.cards = [cards]; + else if (isArray && cards.length) recast.cards = cards; + else _status.event.next.remove(recast); + if (typeof recastingLose != "function") recastingLose = (player, cards) => player.loseToDiscardpile(cards).log = false; + recast.recastingLose = recastingLose; + recast.recastingLosingEvents = []; + if (typeof recastingGain != "function") recastingGain = (player, cards) => player.draw(cards.length).log = false; + recast.recastingGain = recastingGain; + recast.recastingGainingEvents = []; + recast.setContent("recast"); + recast._args = Array.from(arguments); + return recast; + } + //Check if the player can recast the card + //检测角色是否能重铸此牌 + canRecast(card, source, strict) { + return lib.filter.cardRecastable(card, this, source, strict); + } + //装备栏相关 + //判断一名角色的某个区域是否被废除 + //type为要判断的区域 若为空 则判断玩家是否有任意一个被废除的区域 + hasDisabledSlot(type) { + var player = this; + if (type == "horse" || type == "equip3_4") { + return player.hasDisabledSlot(3) && (get.is.mountCombined() || player.hasDisabledSlot(4)); + } + else if (get.is.mountCombined() && type == "equip4") { + return false; + } + return player.countDisabledSlot(type) > 0; + } + //判断一名角色的某个区域被废除的数量 + //用法同上 + countDisabledSlot(type) { + var player = this; + var map = (player.disabledSlots || {}); + if (type == undefined) { + num = 0; + for (var i = 1; i <= 5; i++) { + num += player.countDisabledSlot(i); + } + return num; + } + else { + if (typeof type == "number") type = ("equip" + type); + if (get.is.mountCombined() && type == "equip4") { + return 0; + } + var num = map[type]; + if (typeof num == "number" && num > 0) return num; + return 0; + } + } + //判断一名角色是否有某个装备栏空着 + hasEmptySlot(type) { + var player = this; + if (type == "horse" || type == "equip3_4") { + return player.hasEmptySlot(3) && (get.is.mountCombined() || player.hasEmptySlot(4)); + } + else if (get.is.mountCombined() && type == "equip4") { + return false; + } + return player.countEmptySlot(type) > 0; + } + //判断一名角色的某个装备栏空位的数量 + countEmptySlot(type) { + if (!type) return 0; + var player = this; + if (typeof type == "number") type = ("equip" + type); + else if (type == "equip3_4") { + type = "equip3"; + } + return Math.max(0, player.countEnabledSlot(type) - player.getEquips(type).reduce(function (num, card) { + var types = get.subtypes(card, false); + return num + get.numOf(types, type); + }, 0)) + } + //判断一名角色是否有可以用于装备新装备牌的区域(排除金箍棒和六龙等“不可被替换装备”) + //用法同下 + hasEquipableSlot(type) { + return this.countEquipableSlot(type) > 0; + } + //统计一名角色有多少个可以用于装备新的装备牌的区域 + //用法同下 + countEquipableSlot(type) { + if (!type) return 0; + var player = this; + if (typeof type == "number") type = ("equip" + type); + else if (type == "equip3_4") { + type = "equip3"; + } + else if (get.is.mountCombined() && type == "equip4") { + return 0; + } + return Math.max(0, player.countEnabledSlot(type) - player.getEquips(type).reduce(function (num, card) { + var types = get.subtypes(card, false); + if (!lib.filter.canBeReplaced(card, player)) num += get.numOf(types, type); + return num; + }, 0)) + } + //判断一名角色是否拥有未被废除的某个区域 + //type为要判断的区域 若为空 则判断玩家是否有任意一个未被废除的区域 + hasEnabledSlot(type) { + var player = this; + if (type == "horse" || type == "equip3_4") { + return player.hasEnabledSlot(3) && (get.is.mountCombined() || player.hasEnabledSlot(4)); + } + // else if(type=="equip3_4"){ + // type="equip3"; + // } + else if (get.is.mountCombined() && type == "equip4") { + return false; + } + return player.countEnabledSlot(type) > 0; + } + //判断一名角色的某个区域未被废除的数量 + //用法同上 + countEnabledSlot(type) { + var player = this; + var map = (player.expandedSlots || {}); + if (!type) { + num = 0; + for (var i = 1; i <= 5; i++) { + num += player.countEnabledSlot(i); + } + return num; + } + else { + if (typeof type == "number") type = ("equip" + type); + if (get.is.mountCombined() && type == "equip4") { + return 0; + } + var slots = 1; + var num = map[type]; + if (typeof num == "number" && num > 0) slots += num; + slots -= player.countDisabledSlot(type); + return slots; + } + } + //获取一名角色装备区内某种类型的装备牌 + //参数可以为数字/区域字符串/实体牌/虚拟牌/牌名 + getEquips(subtype) { + var type = (typeof subtype); + switch (type) { + case "string": + if (subtype == "equip3_4") { + const cards = []; + cards.addArray(this.getEquips(3)); + cards.addArray(this.getEquips(4)); + return cards; + } + else if (subtype.startsWith("equip") && parseInt(subtype.slice(5)) > 0) { + break; + } + else if (lib.card[subtype]) { + return this.getCards("e", card => card.name == subtype); + } + else return []; + case "number": + subtype = "equip" + subtype; + break; + case "object": + subtype = get.subtype(subtype, false); + break; + default: + return []; + } + if (!subtype) return []; + return this.getCards("e", function (card) { + return get.subtypes(card, false).contains(subtype); + }) + } + //新的废除装备区/恢复装备区/扩展装备区 + //参数:废除来源角色(不写默认当前事件角色),废除区域(数字/区域字符串/数组,可以写多个,重复废除) + disableEquip() { + var next = game.createEvent("disableEquip"); + next.player = this; + next.slots = []; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + next.source = arguments[i]; + } + else if (Array.isArray(arguments[i])) { + for (var arg of arguments[i]) { + if (typeof arg == "string") { + if (arg.startsWith("equip") && parseInt(arg.slice(5)) > 0) next.slots.push(arg); + } + else if (typeof arg == "number") { + next.slots.push("equip" + arg); + } + } + } + else if (typeof arguments[i] == "string") { + if (arguments[i].startsWith("equip") && parseInt(arguments[i].slice(5)) > 0) next.slots.push(arguments[i]); + } + else if (typeof arguments[i] == "number") { + next.slots.push("equip" + arguments[i]); + } + } + if (!next.source) next.source = _status.event.player; + if (!next.slots.length) { + _status.event.next.remove(next); + } + next.setContent("disableEquip"); + return next; + } + enableEquip() { + var next = game.createEvent("enableEquip"); + next.player = this; + next.slots = []; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + next.source = arguments[i]; + } + else if (Array.isArray(arguments[i])) { + for (var arg of arguments[i]) { + if (typeof arg == "string") { + if (arg.startsWith("equip") && parseInt(arg.slice(5)) > 0) next.slots.push(arg); + } + else if (typeof arg == "number") { + next.slots.push("equip" + arg); + } + } + } + else if (typeof arguments[i] == "string") { + if (arguments[i].startsWith("equip") && parseInt(arguments[i].slice(5)) > 0) next.slots.push(arguments[i]); + } + else if (typeof arguments[i] == "number") { + next.slots.push("equip" + arguments[i]); + } + } + if (!next.source) next.source = _status.event.player; + if (!next.slots.length) { + _status.event.next.remove(next); + } + next.setContent("enableEquip"); + return next; + } + expandEquip() { + var next = game.createEvent("expandEquip"); + next.player = this; + next.slots = []; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + next.source = arguments[i]; + } + else if (Array.isArray(arguments[i])) { + for (var arg of arguments[i]) { + if (typeof arg == "string") { + if (arg.startsWith("equip") && parseInt(arg.slice(5)) > 0) next.slots.push(arg); + } + else if (typeof arg == "number") { + next.slots.push("equip" + arg); + } + } + } + else if (typeof arguments[i] == "string") { + if (arguments[i].startsWith("equip") && parseInt(arguments[i].slice(5)) > 0) next.slots.push(arguments[i]); + } + else if (typeof arguments[i] == "number") { + next.slots.push("equip" + arguments[i]); + } + } + if (!next.source) next.source = _status.event.player; + if (!next.slots.length) { + _status.event.next.remove(next); + } + next.setContent("expandEquip"); + return next; + } + //判断判定区是否被废除 + isDisabledJudge() { + return Boolean(this.storage._disableJudge); + } + //同步显示扩展装备区状态 + $syncExpand(map) { + var player = this; + if (!map) { + map = (player.expandedSlots || {}); + } + game.addVideo("$syncExpand", player, get.copy(map)) + game.broadcast(function (player, map) { + player.expandedSlots = map; + player.$syncExpand(map); + }, player, map); + player.markSkill("expandedSlots"); + } + //同步装备区废除牌显示状态 + $syncDisable(map) { + const player = this; + const suits = { equip3: "+1马栏", equip4: "-1马栏", equip6: "特殊栏" }; + if (get.is.mountCombined()) suits.equip3 = "坐骑栏"; + if (!map) { + map = (player.disabledSlots || {}); + } + game.addVideo("$syncDisable", player, get.copy(map)) + game.broadcast(function (player, map) { + player.disabledSlots = map; + player.$syncDisable(map); + }, player, map) + const map2 = get.copy(map); + const cards = Array.from(player.node.equips.childNodes); + for (const card of cards) { + if (card.name.startsWith("feichu_")) { + const index = card.name.slice(7); + if (!map2[index]) map2[index] = 0; + map2[index]--; + } + } + for (const index in map2) { + if (!index.startsWith("equip") || !(parseInt(index.slice(5)) > 0)) continue; + const num = map2[index]; + if (num > 0) { + for (let i = 0; i < num; i++) { + const card = game.createCard("feichu_" + index, (suits[index] || (get.translation(index) + "栏")), ""); + card.fix(); + card.style.transform = ""; + card.classList.remove("drawinghidden"); + card.classList.add("feichu"); + delete card._transform; + const equipNum = get.equipNum(card); + let equipped = false; + for (let j = 0; j < player.node.equips.childNodes.length; j++) { + if (get.equipNum(player.node.equips.childNodes[j]) >= equipNum) { + player.node.equips.insertBefore(card, player.node.equips.childNodes[j]); + equipped = true; + break; + } + } + if (!equipped) { + player.node.equips.appendChild(card); + if (_status.discarded) { + _status.discarded.remove(card); + } + } + } + } + else if (num < 0) { + for (let i = 0; i > num; i--) { + const card = cards.find(card => card.name == "feichu_" + index); + if (card) { + player.node.equips.removeChild(card); + cards.remove(card); + } + } + } + } + } + //以下函数涉及到本次更新内容而进行修改 + canEquip(name, replace) { + const ranges = get.subtypes(name), rangex = [], player = this, combined = get.is.mountCombined(); + if (combined) { + ranges.forEach(type => { + if (type == "equip3" || type == "equip4") rangex.add("equip3_4"); + else rangex.add(type) + }) + } + else { + rangex.push(...new Set(ranges)); + } + for (let range of rangex) { + let num = this.countEquipableSlot(range); + let num2 = get.numOf(rangex, range); + if (!replace) num -= this.getEquips(range).filter(card => lib.filter.canBeReplaced(card, player)).length; + if (num < num2) return false; + } + return true; + } + //以下函数将不再进行后续维护 + countDisabled() { + return this.countDisabledSlot.apply(this, arguments) + } + isDisabled(arg) { + return this.hasDisabledSlot(arg) && !this.hasEnabledSlot(arg); + } + isEmpty(num) { + return this.countEnabledSlot(num) > this.getEquips(num).length; + } + //以下函数将被废弃 + $disableEquip() { } + $enableEquip() { } + //装备区End + chooseToDebate() { + var next = game.createEvent("chooseToDebate"); + next.player = this; + next._args = []; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "players") { + next.list = arguments[i].slice(0); + } + else { + next._args.push(arguments[i]); + } + } + next.setContent("chooseToDebate"); + return next; + } + cooperationWith(target, type, reason) { + var player = this; + if (!player.storage.cooperation) player.storage.cooperation = []; + var info = { + target: target, + type: type, + reason: reason, + }; + player.storage.cooperation.add(info); + player.addTempSkill("cooperation", { player: "dieAfter" }); + player.addSkill("cooperation_" + type, { player: "dieAfter" }); + game.log(player, "向", target, "发起了“协力”,合作类型是", "#g" + get.translation("cooperation_" + type)); + } + chooseCooperationFor() { + var next = game.createEvent("chooseCooperationFor"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + next.target = arguments[i]; + } + else if (Array.isArray(arguments[i])) { + next.cardlist = arguments[i]; + } + else if (typeof arguments[i] == "string") { + next.reason = arguments[i]; + } + } + if (!next.cardlist) next.cardlist = ["cooperation_damage", "cooperation_draw", "cooperation_discard", "cooperation_use"]; + next.setContent("chooseCooperationFor"); + return next; + } + checkCooperationStatus(target, reason) { + var storage = this.getStorage("cooperation"); + for (var info of storage) { + if (info.target == target && info.reason == reason) { + var skill = lib.skill["cooperation_" + info.type]; + if (skill && skill.checkx && skill.checkx(info)) return true; + } + } + return false; + } + removeCooperation(info) { + var player = this; + var storage = player.getStorage("cooperation"); + if (!storage.contains(info)) return; + storage.remove(info); + var unmark = true, reason = info.type; + if (!storage.length) { + player.removeSkill("cooperation"); + } + else { + for (var i of storage) { + if (i.type == reason) { + unmark = false; + break; + } + } + } + if (unmark) player.removeSkill("cooperation_" + reason); + else player.markSkill("cooperation_" + reason); + } + hasClan(clan, unseen) { + if (unseen || !this.isUnseen(0)) { + var info = lib.character[this.name1]; + if (info && info[4]) { + for (var i of info[4]) { + if (typeof i == "string" && i.startsWith("clan:") && i.slice(5) == clan) return true; + } + } + } + if (this.name2 && (unseen || !this.isUnseen(1))) { + var info = lib.character[this.name2]; + if (info && info[4]) { + for (var i of info[4]) { + if (typeof i == "string" && i.startsWith("clan:") && i.slice(5) == clan) return true; + } + } + } + return false; + } + changeZhuanhuanji(skill) { + var player = this, info = get.info(skill), zhuanhuan = info.zhuanhuanji; + if (typeof zhuanhuan == "function") zhuanhuan(player, skill); + else if (zhuanhuan == "number") player.addMark(skill, 1, false); + else player.storage[skill] = !player.storage[skill]; + game.broadcastAll(function (player, skill) { + player.$changeZhuanhuanji(skill); + }, player, skill); + } + $changeZhuanhuanji(skill) { + var mark = this.marks[skill]; + if (mark) { + if (mark.firstChild.reversed) { + mark.firstChild.reversed = false; + mark.firstChild.style.transform = "none"; + } + else { + mark.firstChild.reversed = true; + mark.firstChild.style.transform = "rotate(180deg)"; + } + } + } + setSeatNum(num) { + _status.seatNumSettled = true; + game.broadcastAll(function (player, num) { + player.seatNum = num; + }, this, num); + } + getSeatNum() { + if (typeof this.seatNum == "number") return this.seatNum; + return 0; + } + hasSex(sex) { + if (this.sex == "unknown") return false; + if (this.sex == "double") return true; + return this.sex == sex; + } + sameSexAs(target) { + var sex1 = this.sex, sex2 = target.sex; + if (sex1 == "unknown" || sex2 == "unknown") return false; + if (sex1 == "double" || sex2 == "double") return true; + return sex1 == sex2; + } + differentSexFrom(target) { + var sex1 = this.sex, sex2 = target.sex; + if (sex1 == "unknown" || sex2 == "unknown") return false; + if (sex1 == "double" || sex2 == "double") return true; + return sex1 != sex2; + } + addSkillBlocker(skill) { + if (!this.storage.skill_blocker) this.storage.skill_blocker = []; + this.storage.skill_blocker.push(skill); + } + removeSkillBlocker(skill) { + if (this.storage.skill_blocker) { + this.storage.skill_blocker.remove(skill); + if (!this.storage.skill_blocker.length) delete this.storage.skill_blocker; + } + } + loseToSpecial(cards, tag, target) { + var next = game.loseAsync({ + player: this, + cards: cards, + tag: tag, + toStorage: true, + target: target || this, + }); + next.setContent(function () { + "step 0" + player.lose(cards, ui.special).set("getlx", false); + "step 1" + var cards = event.cards.slice(0); + cards.removeArray(player.getCards("hejsx")); + if (cards.length) target.directgains(cards, null, event.tag) + }); + return next; + } + addGaintag(cards, tag) { + if (get.itemtype(cards) == "card") cards = [cards]; + game.addVideo("addGaintag", this, [get.cardsInfo(cards), tag]); + game.broadcastAll(function (player, cards, tag) { + var hs = player.getCards("hejsx"); + for (var i of cards) { + if (hs.contains(i)) i.addGaintag(tag); + } + }, this, cards, tag); + } + removeGaintag(tag, cards) { + cards = cards || this.getCards("h"); + game.addVideo("removeGaintag", this, [tag, get.cardsInfo(cards)]); + game.broadcastAll(function (player, tag, cards) { + for (var i of cards) i.removeGaintag(tag); + }, this, tag, cards); + } + canSave(target) { + var player = this; + if (player.hasSkillTag("save", true, target, true)) return true; + var name = {}, hs = player.getCards("hs"); + for (var i of hs) name[get.name(i)] = true; + for (var i in lib.card) { + if (lib.card[i].savable && (lib.inpile.contains(i) || name[i])) { + if (lib.filter.cardSavable({ name: i }, player, target) && (_status.connectMode || player.hasUsableCard(i))) return true; + } + } + return false; + } + canSaveCard(card, target) { + var player = this; + var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); + if (mod2 != "unchanged") return mod2; + var mod = game.checkMod(card, player, target, "unchanged", "cardSavable", player); + if (mod != "unchanged") return mod; + var savable = get.info(card).savable; + if (typeof savable == "function") savable = savable(card, player, target); + return savable; + } + showCharacter(num, log) { + var toShow = []; + if ((num == 0 || num == 2) && this.isUnseen(0)) toShow.add(this.name1); + if ((num == 1 || num == 2) && this.isUnseen(1)) toShow.add(this.name2); + if (!toShow.length) return; + this.$showCharacter(num, log); + var next = game.createEvent("showCharacter", false); + next.player = this; + next.num = num; + next.toShow = toShow; + next._args = Array.from(arguments); + next.setContent("showCharacter"); + var evt = _status.event; + evt.next.remove(next); + if (evt.logSkill) evt = evt.getParent(); + evt.after.push(next); + return next; + } + $showCharacter(num, log) { + if (num == 0 && !this.isUnseen(0)) { + return; + } + if (num == 1 && (!this.name2 || !this.isUnseen(1))) { + return; + } + if (!this.isUnseen(2)) { + return; + } + game.addVideo("showCharacter", this, num); + 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]; + if (this.group == "unknown") this.group = lib.character[this.name][1]; + 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.startsWith("unknown")) this.name = this.name2; + this.classList.remove("unseen2"); + break; + case 2: + if (log !== false) { + if (this.name2) game.log(this, "展示了主将", "#b" + this.name1, "、副将", "#b" + this.name2); + else game.log(this, "展示了主将", "#b" + this.name1); + } + this.name = this.name1; + var skills = (lib.character[this.name][3] || []); + if (this.name2) skills = skills.concat(lib.character[this.name2][3] || []); + this.sex = lib.character[this.name][0]; + if (this.group == "unknown") this.group = lib.character[this.name][1]; + this.classList.remove("unseen"); + this.classList.remove("unseen2"); + break; + } + if (!this.isUnseen(2)) { + delete this.storage.nohp; + this.hp = this.storage.rawHp + this.maxHp - 1; + this.maxHp = this.storage.rawMaxHp + this.maxHp - 1; + this.node.hp.show(); + this.update(); + } + game.broadcast(function (player, name, sex, num, group) { + player.group = group; + player.name = name; + player.sex = sex; + 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; + } + if (!player.isUnseen(2)) { + delete player.storage.nohp; + player.node.hp.show(); + player.update(); + } + }, this, this.name, this.sex, num, this.group); + skills = skills.filter(skill => { + var info = get.info(skill); + if (info && info.zhuSkill && !this.isZhu2()) return false; + return true; + }); + for (var i = 0; i < skills.length; i++) { + if (this.hiddenSkills.contains(skills[i])) { + this.hiddenSkills.remove(skills[i]); + this.addSkill(skills[i]); + } + } + this.checkConflict(); + } + chooseToPlayBeatmap(beatmap) { + var next = game.createEvent("chooseToPlayBeatmap"); + next.player = this; + next.beatmap = beatmap; + next._args = Array.from(arguments); + next.setContent("chooseToPlayBeatmap"); + return next; + } + chooseToMove() { + var next = game.createEvent("chooseToMove"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "boolean") { + next.forced = arguments[i]; + } + else if (typeof arguments[i] == "string") { + next.prompt = arguments[i]; + } + } + next.setContent("chooseToMove"); + next.filterOk = function () { return true }; + next.filterMove = function () { return true }; + return next; + } + chooseToGuanxing(num) { + var next = game.createEvent("chooseToGuanxing"); + next.num = num || 1; + next.player = this; + next.setContent("chooseToGuanxing"); + return next; + } + $throwEmotion(target, name, rotate) { + game.addVideo("throwEmotion", this, [target.dataset.position, name]); + var getLeft = function (player) { + if (player == game.me && !ui.fakeme && !ui.chess) return player.getLeft() + player.node.avatar.offsetWidth / 2; + return player.getLeft() + player.offsetWidth / 2; + } + var player = this; + var emotion = ui.create.div("", `
`, game.chess ? ui.chess : ui.window); + emotion.style.width = "60px"; + emotion.style.height = "60px"; + var width = emotion.offsetWidth / 2; + var height = emotion.offsetHeight / 2; + if (game.chess) width += 60; + var left = getLeft(player) - width; + var top = player.getTop() + player.offsetHeight / 3 - height; + emotion.style.left = left + "px"; + emotion.style.top = top + "px"; + var left2 = getLeft(target) - width; + var top2 = target.getTop() + target.offsetHeight / 3 - height; + if (["egg", "flower", "shoe"].contains(name) || rotate) { + var num1 = 0.95 + Math.random() * (1.1 - 0.95); + var num2 = 1 + Math.random() * (3 - 1); + var left2 = getLeft(target) / num1 - width; + var top2 = target.getTop() + target.offsetHeight / num2 - height; + } + else { + var left2 = getLeft(target) - width; + var top2 = target.getTop() + target.offsetHeight / 3 - height; + } + emotion.style["z-index"] = 10; + emotion.style.transform = "translateY(" + (top2 - top) + "px) translateX(" + (left2 - left) + "px)"; + if (["egg", "flower", "shoe"].contains(name) || rotate) emotion.firstElementChild.style.transform = "rotate(1440deg)"; + if (lib.config.background_audio) game.playAudio("effect", "throw_" + name + get.rand(1, 2)); + setTimeout(function () { + emotion.innerHTML = `
`; + setTimeout(function () { + emotion.delete(); + }, 1200); + }, 600); + } + tryJudgeAnimate(bool) { + var player = this; + game.broadcast(function (player, bool) { + player.trySkillAnimate(bool); + }, player, bool); + if (bool) this.popup("判定生效", "wood", false); + else this.popup("判定失效", "fire", false); + } + trySkillAnimate(name, popname, checkShow) { + if (!game.online && lib.config.skill_animation_type != "off" && lib.skill[name] && lib.skill[name].skillAnimation) { + if (lib.config.skill_animation_type == "default") { + checkShow = checkShow || "main"; + } + else { + checkShow = false; + } + if (lib.skill[name].textAnimation) { + checkShow = false; + } + this.$skill(lib.skill[name].animationStr || lib.translate[name], lib.skill[name].skillAnimation, lib.skill[name].animationColor, checkShow); + return; + } + var player = this; + game.broadcast(function (player, name, popname) { + player.trySkillAnimate(name, popname); + }, player, name, popname); + if (lib.animate.skill[name]) lib.animate.skill[name].apply(this, arguments); + else { + if (popname != name) this.popup(popname, "water", false); + else this.popup(get.skillTranslation(name, this), "water", false); + } + } + tryCardAnimate(card, name, nature, popname) { + var player = this; + game.broadcast(function (player, card, name, nature, popname) { + player.tryCardAnimate(card, name, nature, popname); + }, player, card, name, nature, popname); + if (lib.animate.card[card.name]) lib.animate.card[card.name].apply(this, arguments); + else { + if (!lib.config.show_card_prompt) return; + if (get.type(card) == "equip" && lib.config.hide_card_prompt_equip) return; + if (get.type(card) == "basic" && lib.config.hide_card_prompt_basic) return; + if (popname) player.popup({ name: card.name, nature: card.nature }, nature, false); + else player.popup(name, nature, false); + } + } + hasUsableCard(name) { + var player = this; + if (player.countCards("hs", name)) return true; + var skills = player.getSkills("invisible").concat(lib.skill.global); + game.expandSkills(skills); + for (var i = 0; i < skills.length; i++) { + var ifo = get.info(skills[i]); + if (ifo.viewAs && typeof ifo.viewAs != "function" && ifo.viewAs.name == name) { + if (!ifo.viewAsFilter || ifo.viewAsFilter(player) !== false) { + return true; + } + } + else { + var hiddenCard = get.info(skills[i]).hiddenCard; + if (typeof hiddenCard == "function" && hiddenCard(player, name)) { + return true; + } + } + } + } + inRange(to) { + var from = this; + if (from == to || from.hasSkill("undist") || to.hasSkill("undist")) return false; + if (!game.players.contains(from) && !game.dead.contains(from)) return false; + if (!game.players.contains(to) && !game.dead.contains(to)) return false; + var mod1 = game.checkMod(from, to, "unchanged", "inRange", from); + if (mod1 != "unchanged") return mod1; + var mod2 = game.checkMod(from, to, "unchanged", "inRangeOf", to); + if (mod2 != "unchanged") return mod2; + var range = from.getAttackRange(); + if (range < 1) return false; + var player = from, m, n = 1, i; + var fxy, txy; + if (game.chess) { + fxy = from.getXY(); + txy = to.getXY(); + n = Math.abs(fxy[0] - txy[0]) + Math.abs(fxy[1] - txy[1]); + } + else if (to.isMin(true) || from.isMin(true)) {/* empty */ } + else { + var length = game.players.length; + var totalPopulation = game.players.length + game.dead.length + 1; + for (var iwhile = 0; iwhile < totalPopulation; iwhile++) { + if (player.nextSeat != to) { + player = player.nextSeat; + if (player.isAlive() && !player.isOut() && !player.hasSkill("undist") && !player.isMin(true)) n++; + } + else { + break; + } + } + for (i = 0; i < game.players.length; i++) { + if (game.players[i].isOut() || game.players[i].hasSkill("undist") || game.players[i].isMin(true)) length--; + } + if (from.isDead()) length++; + if (to.isDead()) length++; + var left = from.hasSkillTag("left_hand"); + var right = from.hasSkillTag("right_hand"); + if (left === right) n = Math.min(n, length - n); + else if (left == true) n = length - n; + } + n = game.checkMod(from, to, n, "globalFrom", from); + n = game.checkMod(from, to, n, "globalTo", to); + m = n; + m = game.checkMod(from, to, m, "attackFrom", from); + m = game.checkMod(from, to, m, "attackTo", to); + var equips1 = from.getCards("e", function (card) { + return !ui.selected.cards || !ui.selected.cards.contains(card); + }), equips2 = to.getCards("e", function (card) { + return !ui.selected.cards || !ui.selected.cards.contains(card); + }); + for (i = 0; i < equips1.length; i++) { + var info = get.info(equips1[i]).distance; + if (!info) continue; + if (info.globalFrom) { + m += info.globalFrom; + n += info.globalFrom; + } + } + for (i = 0; i < equips2.length; i++) { + var info = get.info(equips2[i]).distance; + if (!info) continue; + if (info.globalTo) { + m += info.globalTo; + n += info.globalTo; + } + if (info.attaclTo) { + m += info.attaclTo; + } + } + return m <= range; + } + inRangeOf(source) { + return source.inRange(this); + } + //Get the player"s HP not less than 0. Set “raw” to true to get the player"s raw HP instead. + //获取角色的体力值。设置“raw”为true以获取角色的体力。 + getHp(raw) { + return raw ? this.hp : Math.max(0, this.hp); + } + //Set “raw” to true to get the player"s raw damaged HP instead. + //设置“raw”为true以获取角色已损失的体力。 + getDamagedHp(raw) { + return this.maxHp - this.getHp(raw); + } + changeGroup(group, log, broadcast) { + var next = game.createEvent("changeGroup"); + next.player = this; + next.log = true; + for (var i = 0; i < arguments.length; i++) { + var arg = arguments[i]; + if (lib.group.contains(arg)) { + next.group = arg; + } + else if (typeof arg === "boolean") { + next.log = arg; + } + else if (arg === "nobroadcast") { + next.broadcast = false; + } + } + next.setContent("changeGroup"); + return next; + } + chooseToDuiben(target) { + var next = game.createEvent("chooseToDuiben"); + next.player = this; + next.target = target; + next.setContent("chooseToDuiben"); + return next; + } + chooseToPSS(target) { + var next = game.createEvent("chooseToPSS"); + next.player = this; + next.target = target; + next.setContent("chooseToPSS"); + return next; + } + chooseToEnable() { + var next = game.createEvent("chooseToEnable"); + next.player = this; + next.setContent("chooseToEnable"); + return next; + } + chooseToDisable(horse) { + var next = game.createEvent("chooseToDisable"); + next.player = this; + if (horse) next.horse = true; + next.setContent("chooseToDisable"); + return next; + } + isPhaseUsing(notmeisok) { + if (!notmeisok && _status.currentPhase != this) return false; + return _status.event.name == "phaseUse" || _status.event.getParent("phaseUse").name == "phaseUse"; + } + swapEquip(target) { + var next = game.createEvent("swapEquip"); + next.player = this; + next.target = target; + next.setContent("swapEquip"); + return next; + } + canCompare(target) { + if (this == target) return false; + if (!this.countCards("h") || !target.countCards("h")) return false; + if (this.hasSkillTag("noCompareSource") || target.hasSkillTag("noCompareTarget")) return false; + return true; + } + $disableJudge() { + var player = this; + game.addVideo("$disableJudge", player); + player.storage._disableJudge = true; + var card = game.createCard("disable_judge", "", ""); + card.fix(); + card.classList.add("feichu"); + card.style.transform = ""; + card.classList.add("drawinghidden"); + player.node.judges.insertBefore(card, player.node.judges.firstChild); + ui.updatej(player); + } + $enableJudge() { + var player = this; + game.addVideo("$enableJudge", player); + player.storage._disableJudge = false; + for (var i = 0; i < player.node.judges.childNodes.length; i++) { + if (player.node.judges.childNodes[i].name == "disable_judge") { + player.node.judges.removeChild(player.node.judges.childNodes[i]); + break; + } + } + } + disableJudge() { + var next = game.createEvent("disableJudge"); + next.player = this; + next.source = _status.event.player; + next.setContent("disableJudge"); + return next; + } + enableJudge() { + var next = game.createEvent("enableJudge"); + next.player = this; + next.source = _status.event.player; + next.setContent("enableJudge"); + return next; + } + //原有函数 + init(character, character2, skill, update) { + if (typeof character == "string" && !lib.character[character]) { + lib.character[character] = get.character(character); + } + if (typeof character2 == "string" && !lib.character[character2]) { + lib.character[character2] = get.character(character2); + } + if (!lib.character[character]) return; + if (get.is.jun(character2)) { + var tmp = character; + character = character2; + character2 = tmp; + } + if (character2 == false) { + skill = false; + character2 = null; + } + var info = lib.character[character]; + if (!info) { + info = ["", "", 1, [], []]; + } + if (!info[4]) { + info[4] = []; + } + var skills = info[3].slice(0); + this.clearSkills(true); + + var hp1 = get.infoHp(info[2]); + var maxHp1 = get.infoMaxHp(info[2]); + var hujia1 = get.infoHujia(info[2]); + + this.name = character; + this.name1 = character; + this.tempname = []; + this.sex = info[0]; + this.group = info[1]; + this.hp = hp1; + this.maxHp = maxHp1; + this.hujia = hujia1; + this.node.intro.innerHTML = lib.config.intro; + this.node.name.dataset.nature = get.groupnature(this.group); + lib.setIntro(this); + this.node.name.innerHTML = get.slimName(character); + if (this.classList.contains("minskin") && this.node.name.querySelectorAll("br").length >= 4) { + this.node.name.classList.add("long"); + } + if (info[4].contains("hiddenSkill") && !this.noclick) { + if (!this.hiddenSkills) this.hiddenSkills = []; + this.hiddenSkills.addArray(skills); + skills = []; + this.name = "unknown"; + this.sex = "male"; + this.storage.nohp = true; + skills.add("g_hidden_ai"); + } + if (character2 && lib.character[character2]) { + var info2 = lib.character[character2]; + if (!info2) { + info2 = ["", "", 1, [], []]; + } + if (!info2[4]) { + info2[4] = []; + } + + this.name2 = character2; + var hp2 = get.infoHp(info2[2]); + var maxHp2 = get.infoMaxHp(info2[2]); + var hujia2 = get.infoHujia(info2[2]); + this.hujia += hujia2; + var double_hp; + if (_status.connectMode || get.mode() == "single") { + double_hp = "pingjun"; + } + else { + double_hp = get.config("double_hp"); + } + switch (double_hp) { + case "pingjun": { + this.maxHp = Math.floor((maxHp1 + maxHp2) / 2); + this.hp = Math.floor((hp1 + hp2) / 2); + this.singleHp = ((maxHp1 + maxHp2) % 2 === 1); + break; + } + case "zuidazhi": { + this.maxHp = Math.max(maxHp1, maxHp2); + this.hp = Math.max(hp1, hp2); + break; + } + case "zuixiaozhi": { + this.maxHp = Math.min(maxHp1, maxHp2); + this.hp = Math.min(hp1, hp2); + break; + } + case "zonghe": { + this.maxHp = maxHp1 + maxHp2; + this.hp = hp1 + hp2; + break; + } + default: { + this.maxHp = maxHp1 + maxHp2 - 3; + this.hp = hp1 + hp2 - 3; + } + } + if (info2[4].contains("hiddenSkill") && !this.noclick) { + if (!this.hiddenSkills) this.hiddenSkills = []; + this.hiddenSkills.addArray(info2[3]); + this.storage.nohp = true; + skills.add("g_hidden_ai"); + } + else skills = skills.concat(info2[3]); + } + if (this.storage.nohp) { + this.storage.rawHp = this.hp; + this.storage.rawMaxHp = this.maxHp; + this.hp = 1; + this.maxHp = 1; + this.node.hp.hide(); + } + if (skill != false) { + skills = skills.filter(skill => { + var info = get.info(skill); + if (info && info.zhuSkill && !this.isZhu2()) return false; + return true; + }); + for (var i = 0; i < skills.length; i++) { + this.addSkill(skills[i], null, true); + } + this.checkConflict(); + } + lib.group.add(this.group); + + this.$init(character, character2); + + if (this.inits) { + for (var i = 0; i < this.inits.length; i++) { + this.inits[i](this); + } + } + if (this._inits) { + for (var i = 0; i < this._inits.length; i++) { + this._inits[i](this); + } + } + if (update !== false) this.$update(); + return this; + } + $init(character, character2) { + this.classList.add("fullskin"); + var info = lib.character[character]; + if (!info) { + info = ["", "", 1, [], []]; + } + if (!info[4]) { + info[4] = []; + } + + if (!game.minskin && get.is.newLayout() && !info[4].contains("minskin")) { + this.classList.remove("minskin"); + this.node.avatar.setBackground(character, "character"); + } + else { + this.node.avatar.setBackground(character, "character"); + if (info[4].contains("minskin")) { + this.classList.add("minskin"); + } + else if (game.minskin) { + this.classList.add("minskin"); + } + else { + this.classList.remove("minskin"); + } + } + + this.node.avatar.show(); + this.node.count.show(); + this.node.equips.show(); + + this.node.intro.innerHTML = lib.config.intro; + this.node.name.dataset.nature = get.groupnature(this.group); + lib.setIntro(this); + this.node.name.innerHTML = get.slimName(character); + if (this.classList.contains("minskin") && this.node.name.querySelectorAll("br").length >= 4) { + this.node.name.classList.add("long"); + } + if (info[4].contains("hiddenSkill") && !this.noclick) { + this.classList.add(_status.video ? "unseen_v" : "unseen"); + if (!this.node.name_seat && !_status.video) { + this.node.name_seat = ui.create.div(".name.name_seat", get.verticalStr(get.translation(this.name)), this); + this.node.name_seat.dataset.nature = get.groupnature(this.group); + } + } + if (character2 && lib.character[character2]) { + var info2 = lib.character[character2]; + if (!info2) { + info2 = ["", "", 1, [], []]; + } + if (!info2[4]) { + info2[4] = []; + } + this.classList.add("fullskin2"); + this.node.avatar2.setBackground(character2, "character"); + this.node.avatar2.show(); + this.name2 = character2; + + this.node.count.classList.add("p2"); + if (info2[4].contains("hiddenSkill") && !this.noclick) { + this.classList.add(_status.video ? "unseen2_v" : "unseen2"); + } + this.node.name2.innerHTML = get.slimName(character2); + } + if (this.storage.nohp) { + this.node.hp.hide(); + } + + return this; + } + initOL(name, character) { + this.node.avatar.setBackground(character, "character"); + this.node.avatar.show(); + this.node.name.innerHTML = get.verticalStr(name); + this.nickname = name; + this.avatar = character; + this.node.nameol.innerHTML = ""; + if (lib.character[character]) this.sex = lib.character[character][0]; + } + uninitOL() { + this.node.avatar.hide(); + this.node.name.innerHTML = ""; + this.node.identity.firstChild.innerHTML = ""; + delete this.nickname; + delete this.avatar; + delete this.sex; + } + initRoom(info, info2) { + var str = ""; + this.serving = false; + if (!info || info == "server") { + this.roomempty = true; + str = "空房间"; + this.roomfull = false; + this.roomgaming = false; + this.version = null; + if (info == "server") { + this.serving = true; + } + } + else { + var config = info[2]; + this.key = info[4]; + this.roomempty = false; + str += get.modetrans(config); + str += " 模式 "; + for (var i = str.length; i < 11; i++) str += " "; + this.version = config.version; + if (config.gameStarted) { + str += `游戏中 `; + if (config.observe && config.observeReady && this.version == lib.versionOL) { + this.classList.remove("exclude"); + } + else { + this.classList.add("exclude"); + } + } + else { + str += `等待中 `; + if (this.version != lib.versionOL) { + this.classList.add("exclude"); + } + else { + this.classList.remove("exclude"); + } + } + this.maxHp = parseInt(config.number); + this.hp = Math.min(this.maxHp, info[3]); + if (this.hp < this.maxHp || config.gameStarted) str += ("人数:" + this.hp + "/" + this.maxHp); + else str += `人数:${this.hp}/${this.maxHp}`; + + str += (" (" + info[0].slice(0, 12) + " 的房间)"); + if (config.mode != "guozhan" && (config.mode != "doudizhu" || config.doudizhu_mode != "online")) { + str += "【"; + for (var i = 0; i < config.cardPack.length; i++) { + str += (get.translation(config.cardPack[i] + "_card_config").slice(0, 2)); + if (i < config.cardPack.length - 1) str += "+"; + } + str += "】"; + } + this.config = config; + if (this.hp == this.maxHp && !config.gameStarted) { + this.roomfull = true; + } + else { + this.roomfull = false; + } + if (config.gameStarted && (!config.observe || !config.observeReady)) { + this.roomgaming = true; + } + else { + this.roomgaming = false; + } + } + this.firstChild.innerHTML = str; + return this; + } + reinit(from, to, maxHp, online) { + var info1 = lib.character[from]; + var info2 = lib.character[to]; + var smooth = true, replaced = null; + if (maxHp == "nosmooth") { + smooth = false; + maxHp = null; + } + if (this.name2 == from) { + this.name2 = to; + } + else if (this.name == from || this.name1 == from) { + if (this.name1 == from) { + this.name1 = to; + } + if (!this.isUnseen(1)) { + this.name = to; + this.sex = info2[0]; + } + } + else { + return this; + } + if (online) { + return; + } + for (var i = 0; i < info1[3].length; i++) { + this.removeSkill(info1[3][i]); + } + for (var i = 0; i < info2[3].length; i++) { + var info = get.info(info2[3][i]); + if (info && info.zhuSkill && !this.isZhu2()) continue; + this.addSkill(info2[3][i]); + } + if (Array.isArray(maxHp)) { + this.maxHp = maxHp[1]; + this.hp = maxHp[0]; + } + else { + var num; + if (maxHp === false) { + num = 0; + } + else { + if (typeof maxHp != "number") { + maxHp = get.infoMaxHp(info2[2]); + } + num = maxHp - get.infoMaxHp(info1[2]); + } + if (typeof this.singleHp == "boolean") { + if (num % 2 != 0) { + if (this.singleHp) { + this.maxHp += (num + 1) / 2; + this.singleHp = false; + } + else { + this.maxHp += (num - 1) / 2; + this.singleHp = true; + if (!game.online) { + this.doubleDraw(); + } + } + } + else { + this.maxHp += num / 2; + } + } + else { + this.maxHp += num; + } + } + game.broadcast(function (player, from, to, skills) { + player.reinit(from, to, null, true); + player.applySkills(skills); + }, this, from, to, get.skillState(this)); + game.addVideo("reinit3", this, { + from: from, + to: to, + hp: this.maxHp, + avatar2: this.name2 == to + }); + + this.$reinit(from, to, maxHp, online); + this.update(); + } + $reinit(from, to, maxHp, online) { + var smooth = true; + if (maxHp == "nosmooth") { + smooth = false; + maxHp = null; + } + if (this.name2 == to) { + if (smooth) this.smoothAvatar(true); + this.node.avatar2.setBackground(to, "character"); + this.node.name2.innerHTML = get.slimName(to); + } + else if (this.name == to || this.name1 == to) { + if (smooth) this.smoothAvatar(false); + this.node.avatar.setBackground(to, "character"); + this.node.name.innerHTML = get.slimName(to); + + if (this == game.me && ui.fakeme) { + ui.fakeme.style.backgroundImage = this.node.avatar.style.backgroundImage; + } + } + } + uninit() { + this.expandedSlots = {}; + this.disabledSlots = {}; + + delete this.name; + delete this.name1; + delete this.tempname; + delete this.sex; + delete this.group; + delete this.hp; + delete this.maxHp; + delete this.hujia; + this.clearSkills(true); + + if (this.name2) { + delete this.singleHp; + delete this.name2; + } + for (var mark in this.marks) { + this.marks[mark].remove(); + } + ui.updatem(this); + + this.skipList = []; + this.skills = this.skills.filter(skill => { + return lib.skill[skill] && lib.skill[skill].superCharlotte; + }); + this.initedSkills = []; + this.additionalSkills = {}; + this.disabledSkills = {}; + this.hiddenSkills = []; + this.awakenedSkills = []; + this.forbiddenSkills = {}; + this.phaseNumber = 0; + this.stat = [{ card: {}, skill: {} }]; + this.tempSkills = {}; + this.storage = {}; + this.marks = {}; + this.ai = { friend: [], enemy: [], neutral: [] }; + + this.$uninit(); + + return this; + } + $uninit() { + this.$syncDisable(); + if (this.isDisabledJudge()) { + game.broadcastAll(function (player) { + player.storage._disableJudge = false; + for (var i = 0; i < player.node.judges.childNodes.length; i++) { + if (player.node.judges.childNodes[i].name == "disable_judge") { + player.node.judges.removeChild(player.node.judges.childNodes[i]); + break; + } + } + }, this); + } + this.node.avatar.hide(); + this.node.count.hide(); + if (this.node.wuxing) { + this.node.wuxing.hide(); + } + if (this.node.name_seat) { + this.node.name_seat.remove(); + delete this.node.name_seat; + } + this.node.hp.show(); + this.classList.remove("unseen"); + this.classList.remove("unseen2"); + + this.node.identity.style.backgroundColor = ""; + this.node.intro.innerHTML = ""; + this.node.name.innerHTML = ""; + this.node.hp.innerHTML = ""; + this.node.count.innerHTML = "0"; + + this.node.avatar2.hide(); + this.node.name2.innerHTML = ""; + this.classList.remove("fullskin2"); + this.node.count.classList.remove("p2"); + + for (var mark in this.marks) { + this.marks[mark].remove(); + } + ui.updatem(this); + } + getLeft() { + return this.offsetLeft; + } + getTop() { + return this.offsetTop; + } + smoothAvatar(vice, video) { + var div = ui.create.div(".fullsize"); + if (vice) { + div.style.background = getComputedStyle(this.node.avatar2).background; + this.node.avatar2.appendChild(div); + } + else { + div.style.background = getComputedStyle(this.node.avatar).background; + this.node.avatar.appendChild(div); + } + ui.refresh(div); + div.style.transition = "all 1s"; + setTimeout(function () { + div.classList.add("removing"); + setTimeout(function () { + div.remove(); + }, 2000); + }, 100); + if (video != false) { + game.addVideo("smoothAvatar", this, vice); + } + } + changeSeat(position, video) { + var player = this; + if (video !== false) game.addVideo("changeSeat", player, position); + var rect1 = player.getBoundingClientRect(); + player.style.transition = "all 0s"; + ui.refresh(player); + player.dataset.position = position; + var rect2 = player.getBoundingClientRect(); + var dx = rect1.left - rect2.left; + var dy = rect1.top - rect2.top; + if ((game.chess || (player.dataset.position != 0 && position != 0)) && player.classList.contains("linked")) { + player.style.transform = "rotate(-90deg) translate(" + (-dy) + "px," + (dx) + "px)"; + } + else { + player.style.transform = "translate(" + (dx) + "px," + (dy) + "px)"; + } + setTimeout(function () { + player.style.transition = ""; + ui.refresh(player); + player.style.transform = ""; + }, 100); + } + send() { + if (!this.ws || this.ws.closed) return this; + this.ws.send.apply(this.ws, arguments); + return this; + } + getId() { + if (_status.video || _status.connectMode) return this; + if (this.playerid) { + delete game.playerMap[this.playerid]; + } + this.playerid = get.id(); + game.playerMap[this.playerid] = this; + return this; + } + throwEmotion(target, emotion, rotate) { + game.broadcastAll(function (player, target, emotion, rotate) { + player.$throwEmotion(target, emotion, rotate); + }, this, target, emotion, rotate); + } + emotion(pack, id) { + var str = ``; + this.say(str); + game.broadcast(function (id, str) { + if (lib.playerOL[id]) { + lib.playerOL[id].say(str); + } + else if (game.connectPlayers) { + for (var i = 0; i < game.connectPlayers.length; i++) { + if (game.connectPlayers[i].playerid == id) { + game.connectPlayers[i].say(str); + return; + } + } + } + }, this.playerid, str); + } + chat(str) { + if (get.is.banWords(str)) return; + this.say(str); + game.broadcast(function (id, str) { + if (lib.playerOL[id]) { + lib.playerOL[id].say(str); + } + else if (game.connectPlayers) { + for (var i = 0; i < game.connectPlayers.length; i++) { + if (game.connectPlayers[i].playerid == id) { + game.connectPlayers[i].say(str); + return; + } + } + } + }, this.playerid, str); + } + say(str) { + str = str.replace(/##assetURL##/g, lib.assetURL); + var dialog = ui.create.dialog("hidden"); + dialog.classList.add("static"); + dialog.add(`
${str}
`); + dialog.classList.add("popped"); + ui.window.appendChild(dialog); + var width = dialog.content.firstChild.firstChild.offsetWidth; + if (width < 190) { + dialog._mod_height = -16; + } + else { + dialog.content.firstChild.style.textAlign = "left"; + } + dialog.style.width = (width + 16) + "px"; + var refnode; + if (this.node && this.node.avatar && this.parentNode == ui.arena) { + refnode = this.node.avatar; + } + if (refnode) { + lib.placePoppedDialog(dialog, { + clientX: (ui.arena.offsetLeft + this.getLeft() + refnode.offsetLeft + refnode.offsetWidth / 2) * game.documentZoom, + clientY: (ui.arena.offsetTop + this.getTop() + refnode.offsetTop + refnode.offsetHeight / 4) * game.documentZoom + }); + } + else { + lib.placePoppedDialog(dialog, { + clientX: (this.getLeft() + this.offsetWidth / 2) * game.documentZoom, + clientY: (this.getTop() + this.offsetHeight / 4) * game.documentZoom + }); + } + if (dialog._mod_height) { + dialog.content.firstChild.style.padding = 0; + } + setTimeout(function () { + dialog.delete(); + }, lib.quickVoice.includes(str) ? 3800 : 2000); + var name = get.translation(this.name); + var info = [name ? (name + "[" + this.nickname + "]") : this.nickname, str]; + lib.chatHistory.push(info); + if (_status.addChatEntry) { + if (_status.addChatEntry._origin.parentNode) { + _status.addChatEntry(info, false); + } + else { + delete _status.addChatEntry; + } + } + if (lib.config.background_speak && lib.quickVoice.includes(str)) { + game.playAudio("voice", (this.sex == "female" ? "female" : "male"), lib.quickVoice.indexOf(str)); + } + } + showGiveup() { + this._giveUp = true; + if (this == game.me) { + ui.create.giveup(); + } + else if (this.isOnline2()) { + this.send(ui.create.giveup); + } + } + applySkills(skills) { + for (var i in skills) { + if (i == "global") { + lib.skill.global = skills[i]; + } + //else if(i=="skillinfo"){ + // for(var j in skills[i]){ + // if(!lib.skill[j]){ + // lib.skill[j]={}; + // } + // lib.skill[j].chooseButton=skills[i][j]; + // } + //} + else if (i == "stat") { + this.stat = [skills.stat]; + } + else if (lib.playerOL[i]) { + for (var j in skills[i]) { + lib.playerOL[i][j] = skills[i][j]; + } + } + } + } + getState() { + var state = { + hp: this.hp, + maxHp: this.maxHp, + nickname: this.nickname, + sex: this.sex, + group: this.group, + name: this.name, + name1: this.name1, + name2: this.name2, + handcards: this.getCards("hs"), + gaintag: [], + equips: this.getCards("e"), + judges: this.getCards("j"), + specials: this.getCards("s"), + expansions: this.getCards("x"), + expansion_gaintag: [], + disableJudge: this.isDisabledJudge(), + disabledSlots: this.disabledSlots, + expandedSlots: this.expandedSlots, + views: [], + position: parseInt(this.dataset.position), + hujia: this.hujia, + side: this.side, + identityShown: this.identityShown, + identityNode: [this.node.identity.innerHTML, this.node.identity.dataset.color], + identity: this.identity, + dead: this.isDead(), + linked: this.isLinked(), + turnedover: this.isTurnedOver(), + out: this.isOut(), + phaseNumber: this.phaseNumber, + unseen: this.isUnseen(0), + unseen2: this.isUnseen(1), + seatNum: this.seatNum, + } + for (var i = 0; i < state.judges.length; i++) { + state.views[i] = state.judges[i].viewAs; + } + for (var i = 0; i < state.handcards.length; i++) { + state.gaintag[i] = state.handcards[i].gaintag; + } + for (var i = 0; i < state.expansions.length; i++) { + state.expansion_gaintag[i] = state.expansions[i].gaintag; + } + if (this.getModeState) { + state.mode = this.getModeState(); + } + return state; + } + setNickname(str) { + this.node.nameol.innerHTML = (str || this.nickname || "").slice(0, 12); + return this; + } + setAvatar(name, name2, video, fakeme) { + var node; + if (this.name2 == name) { + node = this.node.avatar2; + this.smoothAvatar(true, video); + } + else if (this.name == name) { + node = this.node.avatar; + this.smoothAvatar(false, video); + } + if (node) { + node.setBackground(name2, "character"); + if (this == game.me && ui.fakeme && fakeme !== false) { + ui.fakeme.style.backgroundImage = node.style.backgroundImage; + } + if (video != false) { + game.addVideo("setAvatar", this, [name, name2]); + } + } + game.broadcast(function (player, name, name2) { + player.setAvatar(name, name2, false); + }, this, name, name2); + } + setAvatarQueue(name, list) { + var node; + var player = this; + if (player.name2 == name) { + node = player.node.avatar2; + } + else { + node = player.node.avatar; + } + if (node._avatarqueue) { + for (var i = 0; i < list.length; i++) { + node._avatarqueue.push(list[i]); + } + } + else { + var func = function () { + if (node._avatarqueue.length) { + player.setAvatar(name, node._avatarqueue.shift(), false, false); + } + else { + clearInterval(node._avatarqueueinterval); + delete node._avatarqueue; + delete node._avatarqueueinterval; + player.setAvatar(name, name, false, false); + } + }; + node._avatarqueue = list.slice(0); + node._avatarqueueinterval = setInterval(func, 1000); + func(); + } + game.addVideo("setAvatarQueue", this, [name, list]); + } + flashAvatar(skill, name) { + if (lib.skill[name] && !lib.character[name]) { + var stop = false; + var list = lib.config.all.characters.slice(0); + for (var i in lib.characterPack) { + list.add(i); + } + for (var i = 0; i < list.length; i++) { + for (var j in lib.characterPack[list[i]]) { + if (lib.characterPack[list[i]][j][3].contains(name)) { + name = j; + stop = true; + break; + } + } + if (stop) { + break; + } + } + } + if (lib.character[this.name2] && lib.character[this.name2][3].contains(skill)) { + this.setAvatarQueue(this.name2, [name]); + } + else { + this.setAvatarQueue(this.name, [name]); + } + } + update() { + if (_status.video && arguments.length == 0) return; + if (this.hp >= this.maxHp) this.hp = this.maxHp; + game.broadcast(function (player, hp, maxHp, hujia) { + player.hp = hp; + player.maxHp = maxHp; + player.hujia = hujia; + player.$update(); + }, this, this.hp, this.maxHp, this.hujia); + this.$update(...arguments); + } + $update() { + if (this.hp >= this.maxHp) this.hp = this.maxHp; + var hp = this.node.hp; + hp.style.transition = "none"; + if (!_status.video) { + if (this.hujia) { + this.markSkill("ghujia"); + } + else { + this.unmarkSkill("ghujia"); + } + } + if (!this.storage.nohp) { + if (this.maxHp == Infinity) { + hp.innerHTML = "∞"; + } + else if (game.layout == "default" && this.maxHp > 14) { + hp.innerHTML = this.hp + "/" + this.maxHp; + hp.classList.add("text"); + } + else if (get.is.newLayout() && + ( + this.maxHp > 9 || + (this.maxHp > 5 && this.classList.contains("minskin")) || + ((game.layout == "mobile" || game.layout == "long") && this.dataset.position == 0 && this.maxHp > 7) + )) { + hp.innerHTML = this.hp + "
/
" + this.maxHp + "
"; + if (this.hp == 0) { + hp.lastChild.classList.add("lost"); + } + hp.classList.add("textstyle"); + // hp.classList.remove("long"); + } + else { + hp.innerHTML = ""; + hp.classList.remove("text"); + hp.classList.remove("textstyle"); + while (this.maxHp > hp.childNodes.length) { + ui.create.div(hp); + } + while (Math.max(0, this.maxHp) < hp.childNodes.length) { + hp.removeChild(hp.lastChild); + } + for (var i = 0; i < this.maxHp; i++) { + var index = i; + if (get.is.newLayout()) { + index = this.maxHp - i - 1; + } + if (i < this.hp) { + hp.childNodes[index].classList.remove("lost"); + } + else { + hp.childNodes[index].classList.add("lost"); + } + } + // if(this.maxHp==9){ + // hp.classList.add("long"); + // } + // else{ + // hp.classList.remove("long"); + // } + } + if (hp.classList.contains("room")) { + hp.dataset.condition = "high"; + } + else if (this.hp == 0) { + hp.dataset.condition = ""; + } + else if (this.hp > Math.round(this.maxHp / 2) || this.hp === this.maxHp) { + hp.dataset.condition = "high"; + } + else if (this.hp > Math.floor(this.maxHp / 3)) { + hp.dataset.condition = "mid"; + } + else { + hp.dataset.condition = "low"; + } + + setTimeout(function () { + hp.style.transition = ""; + }); + } + var numh = this.countCards("h"); + if (_status.video) { + numh = arguments[0]; + } + if (numh >= 10) { + numh = numh.toString(); + this.node.count.dataset.condition = "low"; + this.node.count.innerHTML = numh[0] + "
" + numh[1]; + } + else { + if (numh > 5) { + this.node.count.dataset.condition = "higher"; + } + else if (numh > 2) { + this.node.count.dataset.condition = "high"; + } + else if (numh > 0) { + this.node.count.dataset.condition = "mid"; + } + else { + this.node.count.dataset.condition = "none"; + } + this.node.count.innerHTML = numh; + } + if (this.updates) { + for (var i = 0; i < this.updates.length; i++) { + this.updates[i](this); + } + } + if (!_status.video) { + game.addVideo("update", this, [this.countCards("h"), this.hp, this.maxHp, this.hujia]); + } + this.updateMarks(); + return this; + } + clearMark(i, log) { + let num = this.countMark(i); + if (num > 0) this.removeMark(i, num, log) + } + removeMark(i, num, log) { + if (typeof num != "number" || !num) num = 1; + if (typeof this.storage[i] != "number" || !this.storage[i]) return; + if (num > this.storage[i]) num = this.storage[i]; + this.storage[i] -= num; + if (log !== false) { + var str = false; + var info = get.info(i); + if (info && info.intro && (info.intro.name || info.intro.name2)) str = info.intro.name2 || info.intro.name; + else str = lib.translate[i]; + if (str) game.log(this, "移去了", get.cnNumber(num), "个", "#g【" + str + "】"); + } + this.syncStorage(i); + this[(this.storage[i] || (lib.skill[i] && lib.skill[i].mark)) ? "markSkill" : "unmarkSkill"](i); + } + addMark(i, num, log) { + if (typeof num != "number" || !num) num = 1; + if (typeof this.storage[i] != "number") this.storage[i] = 0; + this.storage[i] += num; + if (log !== false) { + var str = false; + var info = get.info(i); + if (info && info.intro && (info.intro.name || info.intro.name2)) str = info.intro.name2 || info.intro.name; + else str = lib.translate[i]; + if (str) game.log(this, "获得了", get.cnNumber(num), "个", "#g【" + str + "】"); + } + this.syncStorage(i); + this.markSkill(i); + } + setMark(name, num, log) { + const count = this.countMark(name); + if (count > num) this.removeMark(name, count - num, log); + else if (count < num) this.addMark(name, num - count, log); + } + countMark(i) { + if (this.storage[i] == undefined) return 0; + if (typeof this.storage[i] == "number") return this.storage[i]; + if (Array.isArray(this.storage[i])) return this.storage[i].length; + return 0; + } + hasMark(i) { + return this.countMark(i) > 0; + } + updateMark(i, storage) { + if (!this.marks[i]) { + if (lib.skill[i] && lib.skill[i].intro && (this.storage[i] || lib.skill[i].intro.markcount)) { + this.markSkill(i); + if (!this.marks[i]) return this; + } + else { + return this; + } + } + if (storage && this.storage[i]) { + this.syncStorage(i); + } + if (i == "ghujia" || ((!this.marks[i].querySelector(".image") || this.storage[i + "_markcount"]) && + lib.skill[i] && lib.skill[i].intro && !lib.skill[i].intro.nocount && + (this.storage[i] || this.storage[i + "_markcount"] || lib.skill[i].intro.markcount))) { + this.marks[i].classList.add("overflowmark") + var num = 0; + if (typeof lib.skill[i].intro.markcount == "function") { + num = lib.skill[i].intro.markcount(this.storage[i], this); + } + else if (lib.skill[i].intro.markcount == "expansion") { + num = this.countCards("x", (card) => card.hasGaintag(i)); + } + else if (typeof this.storage[i + "_markcount"] == "number") { + num = this.storage[i + "_markcount"]; + } + else if (i == "ghujia") { + num = this.hujia; + } + else if (typeof this.storage[i] == "number") { + num = this.storage[i]; + } + else if (Array.isArray(this.storage[i])) { + num = this.storage[i].length; + } + if (num) { + if (!this.marks[i].markcount) { + this.marks[i].markcount = ui.create.div(".markcount.menubutton", this.marks[i]); + } + this.marks[i].markcount.innerHTML = num; + } + else if (this.marks[i].markcount) { + this.marks[i].markcount.delete(); + delete this.marks[i].markcount; + } + } + else { + if (this.marks[i].markcount) { + this.marks[i].markcount.delete(); + delete this.marks[i].markcount; + } + if (lib.skill[i].mark == "auto") { + this.unmarkSkill(i); + } + } + return this; + } + updateMarks(connect) { + if (typeof connect == "string" && _status.connectMode && !game.online) { + game.broadcast(function (player, storage, skill) { + player.storage[skill] = storage; + player.updateMarks(); + }, this, this.storage[connect], connect); + } + for (var i in this.marks) { + this.updateMark(i); + } + } + num(arg1, arg2, arg3) { + if (get.itemtype(arg1) == "position") { + return this.get(arg1, arg2, arg3).length; + } + else if (arg1 == "s") { + if (typeof arg2 == "boolean") { + return game.expandSkills(this.getSkills(arg2).concat(lib.skill.global)).contains(arg3); + } + else { + return game.expandSkills(this.getSkills().concat(lib.skill.global)).contains(arg2); + } + } + } + line(target, config) { + if (get.itemtype(target) == "players") { + for (var i = 0; i < target.length; i++) { + this.line(target[i], config); + } + } + else if (get.itemtype(target) == "player") { + if (target == this) return; + game.broadcast(function (player, target, config) { + player.line(target, config); + }, this, target, config); + game.addVideo("line", this, [target.dataset.position, config]); + game.linexy([ + this.getLeft() + this.offsetWidth / 2, + this.getTop() + this.offsetHeight / 2, + target.getLeft() + target.offsetWidth / 2, + target.getTop() + target.offsetHeight / 2 + ], config, true); + } + } + line2(targets, config) { + this.line(targets[0], config); + targets = targets.slice(0); + for (var i = 1; i < targets.length; i++) { + (function (j) { + setTimeout(function () { + targets[j - 1].line(targets[j], config); + }, lib.config.duration * i); + }(i)); + } + } + getNext() { + if (this.hasSkill("undist")) return null; + var target = this; + for (var i = 0; i < game.players.length - 1; i++) { + target = target.next; + if (!target.hasSkill("undist")) { + return target; + } + } + return null; + } + getPrevious() { + if (this.hasSkill("undist")) return null; + var target = this; + for (var i = 0; i < game.players.length - 1; i++) { + target = target.previous; + if (!target.hasSkill("undist")) { + return target; + } + } + return null; + } + countUsed(card, type) { + if (type === true) { + var num = 0; + var history = this.getHistory("useCard"); + for (var i = 0; i < history.length; i++) { + if (!card) num++; + else if (typeof card == "string" && history[i].card && card == history[i].card.name) num++; + else if (typeof card == "object" && history[i].card && card.name == history[i].card.name) num++; + } + return num; + } + var num; + var stat = this.getStat("card"); + if (!card) { + num = 0; + for (var i in stat) { + if (typeof stat[i] == "number") num += stat[i]; + } + return num; + } + if (typeof card == "object") { + card = card.name; + } + num = stat[card]; + if (typeof num != "number") return 0; + return num; + } + countSkill(skill) { + var num = this.getStat("skill")[skill]; + if (num == undefined) return 0; + return num; + } + getStockSkills(unowned, unique, hidden) { + var list = []; + if (lib.character[this.name] && (hidden || !this.isUnseen(0))) { + list.addArray(lib.character[this.name][3]); + } + if (lib.character[this.name1] && (hidden || !this.isUnseen(0))) { + list.addArray(lib.character[this.name1][3]); + } + if (lib.character[this.name2] && (hidden || !this.isUnseen(1))) { + list.addArray(lib.character[this.name2][3]); + } + if (!unowned) { + for (var i = 0; i < list.length; i++) { + if (!this.hasSkill(list[i])) { + list.splice(i--, 1); + } + } + } + if (!unique) { + for (var i = 0; i < list.length; i++) { + var info = lib.skill[list[i]]; + if (!info || info.unique || info.temp || info.sub || info.charlotte) { + list.splice(i--, 1); + } + } + } + return list; + } + /** + * @param {string} [arg1="h"] + * @param {string | Record | (card: Card) => boolean} [arg2] + * @returns {Card[]} + */ + getCards(arg1, arg2) { + if (typeof arg1 != "string") { + arg1 = "h"; + } + var cards = [], cards1 = []; + var i, j; + for (i = 0; i < arg1.length; i++) { + if (arg1[i] == "h") { + for (j = 0; j < this.node.handcards1.childElementCount; j++) { + if (!this.node.handcards1.childNodes[j].classList.contains("removing") && !this.node.handcards1.childNodes[j].classList.contains("glows")) { + cards.push(this.node.handcards1.childNodes[j]); + } + } + for (j = 0; j < this.node.handcards2.childElementCount; j++) { + if (!this.node.handcards2.childNodes[j].classList.contains("removing") && !this.node.handcards2.childNodes[j].classList.contains("glows")) { + cards.push(this.node.handcards2.childNodes[j]); + } + } + } + else if (arg1[i] == "s") { + for (j = 0; j < this.node.handcards1.childElementCount; j++) { + if (!this.node.handcards1.childNodes[j].classList.contains("removing") && this.node.handcards1.childNodes[j].classList.contains("glows")) { + cards.push(this.node.handcards1.childNodes[j]); + } + } + for (j = 0; j < this.node.handcards2.childElementCount; j++) { + if (!this.node.handcards2.childNodes[j].classList.contains("removing") && this.node.handcards2.childNodes[j].classList.contains("glows")) { + cards.push(this.node.handcards2.childNodes[j]); + } + } + } + else if (arg1[i] == "e") { + for (j = 0; j < this.node.equips.childElementCount; j++) { + if (!this.node.equips.childNodes[j].classList.contains("removing") && !this.node.equips.childNodes[j].classList.contains("feichu")) { + cards.push(this.node.equips.childNodes[j]); + } + } + } + else if (arg1[i] == "j") { + for (j = 0; j < this.node.judges.childElementCount; j++) { + if (!this.node.judges.childNodes[j].classList.contains("removing") && !this.node.judges.childNodes[j].classList.contains("feichu")) { + cards.push(this.node.judges.childNodes[j]); + if (this.node.judges.childNodes[j].viewAs && arguments.length > 1) { + this.node.judges.childNodes[j].tempJudge = this.node.judges.childNodes[j].name; + this.node.judges.childNodes[j].name = this.node.judges.childNodes[j].viewAs; + cards1.push(this.node.judges.childNodes[j]); + } + } + } + } + else if (arg1[i] == "x") { + for (j = 0; j < this.node.expansions.childElementCount; j++) { + if (!this.node.expansions.childNodes[j].classList.contains("removing")) { + cards.push(this.node.expansions.childNodes[j]); + } + } + } + } + if (arguments.length == 1) { + return cards; + } + if (arg2) { + if (typeof arg2 == "string") { + for (i = 0; i < cards.length; i++) { + if (get.name(cards[i]) != arg2) { + cards.splice(i, 1); i--; + } + } + } + else if (typeof arg2 == "object") { + for (i = 0; i < cards.length; i++) { + for (j in arg2) { + var value; + if (j == "type" || j == "subtype" || j == "color" || j == "suit" || j == "number") { + value = get[j](cards[i]); + } + else { + value = cards[i][j]; + } + if ((typeof arg2[j] == "string" && value != arg2[j]) || + (Array.isArray(arg2[j]) && !arg2[j].contains(value))) { + cards.splice(i--, 1); break; + } + } + } + } + else if (typeof arg2 == "function") { + for (i = 0; i < cards.length; i++) { + if (!arg2(cards[i])) { + cards.splice(i--, 1); + } + } + } + } + for (i = 0; i < cards1.length; i++) { + if (cards1[i].tempJudge) { + cards1[i].name = cards1[i].tempJudge; + delete cards1[i].tempJudge; + } + } + return cards; + } + getDiscardableCards(player, arg1, arg2) { + var cards = this.getCards(arg1, arg2); + for (var i = 0; i < cards.length; i++) { + if (!lib.filter.canBeDiscarded(cards[i], player, this)) { + cards.splice(i--, 1); + } + } + return cards; + } + getGainableCards(player, arg1, arg2) { + var cards = this.getCards(arg1, arg2); + for (var i = 0; i < cards.length; i++) { + if (!lib.filter.canBeGained(cards[i], player, this)) { + cards.splice(i--, 1); + } + } + return cards; + } + getGainableSkills(func) { + var list = []; + var names = [this.name, this.name1, this.name2]; + for (var i = 0; i < names.length; i++) { + list.addArray(get.gainableSkillsName(names[i], func)); + } + return list; + } + countCards(arg1, arg2) { + return this.getCards(arg1, arg2).length; + } + countDiscardableCards(player, arg1, arg2) { + return this.getDiscardableCards(player, arg1, arg2).length; + } + countGainableCards(player, arg1, arg2) { + return this.getGainableCards(player, arg1, arg2).length; + } + getOriginalSkills() { + var skills = []; + if (lib.character[this.name] && !this.isUnseen(0)) { + skills.addArray(lib.character[this.name][3]); + } + if (this.name2 && lib.character[this.name2] && !this.isUnseen(1)) { + skills.addArray(lib.character[this.name2][3]); + } + return skills; + } + getModableSkills(useCache) { + var func = function (player) { + var skills = player.getSkills().concat(lib.skill.global); + game.expandSkills(skills); + skills = skills.filter(function (skill) { + var info = get.info(skill); + return info && info.mod; + }); + skills.sort((a, b) => get.priority(a) - get.priority(b)); + return skills; + }; + if (!useCache) return func(this); + return game.callFuncUseStepCache("player.getModableSkills", func, [this]); + } + getSkills(arg2, arg3, arg4) { + var skills = this.skills.slice(0); + var es = []; + var i, j; + if (arg3 !== false) { + for (i = 0; i < this.node.equips.childElementCount; i++) { + if (!this.node.equips.childNodes[i].classList.contains("removing")) { + var equipskills = get.info(this.node.equips.childNodes[i], false).skills; + if (equipskills) { + es.addArray(equipskills); + } + } + } + if (arg2 == "e") { + return es; + } + } + for (var i in this.additionalSkills) { + if (Array.isArray(this.additionalSkills[i]) && (arg2 || i.indexOf("hidden:") !== 0)) { + for (j = 0; j < this.additionalSkills[i].length; j++) { + if (this.additionalSkills[i][j]) { + skills.add(this.additionalSkills[i][j]); + } + } + } + else if (this.additionalSkills[i] && typeof this.additionalSkills[i] == "string") { + skills.add(this.additionalSkills[i]); + } + } + for (var i in this.tempSkills) { + skills.add(i); + } + if (arg2) skills.addArray(this.hiddenSkills); + if (arg2 === false || arg2 == "invisible") skills.addArray(this.invisibleSkills); + if (arg3 !== false) skills.addArray(es); + for (var i in this.forbiddenSkills) { + skills.remove(i); + } + if (arg4 !== false) { + skills = game.filterSkills(skills, this, es); + } + return skills; + } + get(arg1, arg2, arg3, arg4) { + var i, j; + if (arg1 == "s") { + var skills = this.skills.slice(0); + var es = []; + if (arg3 !== false) { + for (i = 0; i < this.node.equips.childElementCount; i++) { + if (!this.node.equips.childNodes[i].classList.contains("removing") && !this.node.equips.childNodes[i].classList.contains("feichu")) { + var equipskills = get.info(this.node.equips.childNodes[i]).skills; + if (equipskills) { + es.addArray(equipskills); + } + } + } + if (arg2 == "e") { + return es; + } + } + for (var i in this.additionalSkills) { + if (Array.isArray(this.additionalSkills[i])) { + for (j = 0; j < this.additionalSkills[i].length; j++) { + if (this.additionalSkills[i][j]) { + skills.add(this.additionalSkills[i][j]); + } + } + } + else if (this.additionalSkills[i] && typeof this.additionalSkills[i] == "string") { + skills.add(this.additionalSkills[i]); + } + } + for (var i in this.tempSkills) { + skills.add(i); + } + if (arg2) skills.addArray(this.hiddenSkills); + if (arg3 !== false) skills.addArray(es); + for (var i in this.forbiddenSkills) { + skills.remove(i); + } + if (arg4 !== false) { + skills = game.filterSkills(skills, this, es); + } + return skills; + } + else if (get.is.pos(arg1)) { + var cards = [], cards1 = []; + for (i = 0; i < arg1.length; i++) { + if (arg1[i] == "h") { + for (j = 0; j < this.node.handcards1.childElementCount; j++) { + if (!this.node.handcards1.childNodes[j].classList.contains("removing") && !this.node.handcards1.childNodes[j].classList.contains("feichu") && !this.node.handcards1.childNodes[j].classList.contains("glows")) { + cards.push(this.node.handcards1.childNodes[j]); + } + } + for (j = 0; j < this.node.handcards2.childElementCount; j++) { + if (!this.node.handcards2.childNodes[j].classList.contains("removing") && !this.node.handcards2.childNodes[j].classList.contains("feichu") && !this.node.handcards2.childNodes[j].classList.contains("glows")) { + cards.push(this.node.handcards2.childNodes[j]); + } + } + } + else if (arg1[i] == "e") { + for (j = 0; j < this.node.equips.childElementCount; j++) { + if (!this.node.equips.childNodes[j].classList.contains("removing") && !this.node.equips.childNodes[j].classList.contains("feichu")) { + cards.push(this.node.equips.childNodes[j]); + } + } + if (arguments.length == 2 && typeof arg2 == "string" && /1|2|3|4|5/.test(arg2)) { + for (j = 0; j < cards.length; j++) { + if (get.subtype(cards[j]) == "equip" + arg2) return cards[j]; + } + return; + } + } + else if (arg1[i] == "j") { + for (j = 0; j < this.node.judges.childElementCount; j++) { + if (!this.node.judges.childNodes[j].classList.contains("removing") && !this.node.judges.childNodes[j].classList.contains("feichu")) { + cards.push(this.node.judges.childNodes[j]); + if (this.node.judges.childNodes[j].viewAs && arguments.length > 1) { + this.node.judges.childNodes[j].tempJudge = this.node.judges.childNodes[j].name; + this.node.judges.childNodes[j].name = this.node.judges.childNodes[j].viewAs; + cards1.push(this.node.judges.childNodes[j]); + } + } + } + } + } + if (arguments.length == 1) { + return cards; + } + if (arg2 != undefined) { + if (typeof arg3 == "function") { + var cards2 = cards.slice(0); + cards.sort(function (a, b) { + return arg3(b, cards2) - arg3(a, cards2); + }); + } + if (typeof arg2 == "string") { + for (i = 0; i < cards.length; i++) { + if (cards[i].name != arg2) { + cards.splice(i, 1); i--; + } + } + } + else if (typeof arg2 == "object") { + for (i = 0; i < cards.length; i++) { + for (j in arg2) { + if (j == "type") { + if (typeof arg2[j] == "object") { + if (arg2[j].contains(get.type(cards[i])) == false) { + cards.splice(i, 1); i--; break; + } + } + else if (typeof arg2[j] == "string") { + if (get.type(cards[i]) != arg2[j]) { + cards.splice(i, 1); i--; break; + } + } + } + else if (j == "subtype") { + if (typeof arg2[j] == "object") { + if (arg2[j].contains(get.subtype(cards[i])) == false) { + cards.splice(i, 1); i--; break; + } + } + else if (typeof arg2[j] == "string") { + if (get.subtype(cards[i]) != arg2[j]) { + cards.splice(i, 1); i--; break; + } + } + } + else if (j == "color") { + if (typeof arg2[j] == "object") { + if (arg2[j].contains(get.color(cards[i])) == false) { + cards.splice(i, 1); i--; break; + } + } + else if (typeof arg2[j] == "string") { + if (get.color(cards[i]) != arg2[j]) { + cards.splice(i, 1); i--; break; + } + } + } + else if (j == "suit") { + if (typeof arg2[j] == "object") { + if (arg2[j].contains(get.suit(cards[i])) == false) { + cards.splice(i, 1); i--; break; + } + } + else if (typeof arg2[j] == "string") { + if (get.suit(cards[i]) != arg2[j]) { + cards.splice(i, 1); i--; break; + } + } + } + else if (j == "number") { + if (typeof arg2[j] == "object") { + if (arg2[j].contains(get.number(cards[i])) == false) { + cards.splice(i, 1); i--; break; + } + } + else if (typeof arg2[j] == "string") { + if (get.number(cards[i]) != arg2[j]) { + cards.splice(i, 1); i--; break; + } + } + } + else if (typeof arg2[j] == "object") { + if (arg2[j].contains(cards[i][j]) == false) { + cards.splice(i, 1); i--; break; + } + } + else if (typeof arg2[j] == "string") { + if (cards[i][j] != arg2[j]) { + cards.splice(i, 1); i--; break; + } + } + } + } + } + else if (typeof arg2 == "number" && arg2 > 0) { + cards.splice(arg2); + } + else if (typeof arg2 == "function") { + for (i = 0; i < cards.length; i++) { + if (!arg2(cards[i])) { + cards.splice(i, 1); i--; + } + } + } + } + for (i = 0; i < cards1.length; i++) { + if (cards1[i].tempJudge) { + cards1[i].name = cards1[i].tempJudge; + delete cards1[i].tempJudge; + } + } + if (arg2 === 0) return cards[0]; + if (typeof arg3 == "number") { + if (arg3 == 0) return cards[0]; + cards.splice(arg3); + } + if (typeof arg4 == "number") { + if (arg4 == 0) return cards[0]; + cards.splice(arg4); + } + return cards; + } + } + syncStorage(skill) { + switch (get.itemtype(this.storage[skill])) { + case "cards": game.addVideo("storage", this, [skill, get.cardsInfo(this.storage[skill]), "cards"]); break; + case "card": game.addVideo("storage", this, [skill, get.cardInfo(this.storage[skill]), "card"]); break; + default: + try { + game.addVideo("storage", this, [skill, JSON.parse(JSON.stringify(this.storage[skill]))]); + } + catch (e) { + console.log(this.storage[skill]); + } + } + } + syncSkills() { + game.broadcast(function (player, skills) { + player.applySkills(skills); + }, this, get.skillState(this)); + } + playerfocus(time) { + time = time || 1000; + this.classList.add("playerfocus"); + ui.arena.classList.add("playerfocus"); + var that = this; + setTimeout(function () { + that.classList.remove("playerfocus"); + ui.arena.classList.remove("playerfocus"); + }, time); + game.addVideo("playerfocus", this, time); + game.broadcast(function (player, time) { + player.playerfocus(time); + }, this, time); + return this; + } + setIdentity(identity, nature) { + if (!identity) identity = this.identity; + if (get.is.jun(this)) { + this.node.identity.firstChild.innerHTML = "君"; + } + else { + this.node.identity.firstChild.innerHTML = get.translation(identity); + } + this.node.identity.dataset.color = nature || identity; + return this; + } + insertPhase(skill, insert) { + var evt = _status.event.getParent("phase"); + var next; + if (evt && evt.parent && evt.parent.next) { + evt = evt.parent; + next = game.createEvent("phase", false, evt); + } + else if (_status.event.parent && _status.event.parent.next) { + evt = _status.event.parent; + next = game.createEvent("phase", false, evt); + } + else { + evt = null; + next = game.createEvent("phase", false); + } + if (evt && insert && evt.next.contains(next)) { + evt.next.remove(next); + evt.next.unshift(next); + } + next.player = this; + next.forceDie = true; + next.includeOut = true; + next.skill = skill || _status.event.name; + next.setContent("phase"); + return next; + } + insertEvent(name, content, arg) { + var evt = _status.event.getParent("phase"); + var next; + if (evt && evt.parent && evt.parent.next) { + next = game.createEvent(name, null, evt.parent); + } + else { + next = game.createEvent(name); + } + for (var i in arg) { + next[i] = arg[i]; + } + next.player = this; + next.setContent(content); + return next; + } + phase(skill) { + var next = game.createEvent("phase", false); + next.player = this; + next.setContent("phase"); + if (!_status.roundStart) { + _status.roundStart = this; + } + if (skill) { + next.skill = skill; + } + next.forceDie = true; + next.includeOut = true; + return next; + } + phaseZhunbei() { + var next = game.createEvent("phaseZhunbei"); + next.player = this; + next.setContent("phaseZhunbei"); + return next; + } + phaseJudge() { + var next = game.createEvent("phaseJudge"); + next.player = this; + next.setContent("phaseJudge"); + return next; + } + phaseDraw() { + var next = game.createEvent("phaseDraw"); + next.player = this; + next.num = 2; + if ((get.config("first_less") || _status.connectMode || _status.first_less_forced) && game.phaseNumber == 1 && _status.first_less) { + next.num--; + } + next.setContent("phaseDraw"); + return next; + } + phaseUse() { + var next = game.createEvent("phaseUse"); + next.player = this; + next.setContent("phaseUse"); + return next; + } + phaseDiscard() { + var next = game.createEvent("phaseDiscard"); + next.player = this; + next.setContent("phaseDiscard"); + return next; + } + phaseJieshu() { + var next = game.createEvent("phaseJieshu"); + next.player = this; + next.setContent("phaseJieshu"); + return next; + } + chooseToUse(use) { + var next = game.createEvent("chooseToUse"); + next.player = this; + if (arguments.length == 1 && get.objtype(arguments[0]) == "object") { + for (var i in use) { + next[i] = use[i]; + } + } + else { + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "number" || get.itemtype(arguments[i]) == "select") { + next.selectTarget = arguments[i]; + } + else if ((typeof arguments[i] == "object" && arguments[i]) || typeof arguments[i] == "function") { + if (get.itemtype(arguments[i]) == "player" || next.filterCard) { + next.filterTarget = arguments[i]; + } + else next.filterCard = arguments[i]; + } + else if (typeof arguments[i] == "boolean") { + next.forced = arguments[i]; + } + else if (typeof arguments[i] == "string") { + next.prompt = arguments[i]; + } + } + } + if (typeof next.filterCard == "object") { + next.filterCard = get.filter(next.filterCard); + } + if (typeof next.filterTarget == "object") { + next.filterTarget = get.filter(next.filterTarget, 2); + } + if (next.filterCard == undefined) { + next.filterCard = lib.filter.filterCard; + } + if (next.selectCard == undefined) { + next.selectCard = [1, 1]; + } + if (next.filterTarget == undefined) { + next.filterTarget = lib.filter.filterTarget; + } + if (next.selectTarget == undefined) { + next.selectTarget = lib.filter.selectTarget; + } + if (next.position == undefined) { + next.position = "hs"; + } + if (next.ai1 == undefined) next.ai1 = get.order; + if (next.ai2 == undefined) next.ai2 = get.effect_use; + next.setContent("chooseToUse"); + next._args = Array.from(arguments); + return next; + } + chooseToRespond() { + var next = game.createEvent("chooseToRespond"); + next.player = this; + var filter; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "number") { + next.selectCard = [arguments[i], arguments[i]]; + } + else if (get.itemtype(arguments[i]) == "select") { + next.selectCard = arguments[i]; + } + else if (typeof arguments[i] == "boolean") { + next.forced = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "position") { + next.position = arguments[i]; + } + else if (typeof arguments[i] == "function") { + if (next.filterCard) next.ai = arguments[i]; + else next.filterCard = arguments[i]; + } + else if (typeof arguments[i] == "object" && arguments[i]) { + next.filterCard = get.filter(arguments[i]); + filter = arguments[i]; + } + else if (arguments[i] == "nosource") { + next.nosource = true; + } + else if (typeof arguments[i] == "string") { + next.prompt = arguments[i]; + } + } + if (next.filterCard == undefined) next.filterCard = lib.filter.all; + if (next.selectCard == undefined) next.selectCard = [1, 1]; + if (next.source == undefined && !next.nosource) next.source = _status.event.player; + if (next.ai == undefined) next.ai = get.unuseful2; + if (next.prompt != false) { + if (typeof next.prompt == "string") { + //next.dialog=next.prompt; + } + else { + var str = "请打出" + get.cnNumber(next.selectCard[0]) + "张" + if (filter) { + if (filter.name) { + str += get.translation(filter.name); + } + else { + str += "牌"; + } + } + else { + str += "牌"; + } + if (_status.event.getParent().name == "useCard") { + var cardname = _status.event.name; + if (lib.card[cardname] && lib.translate[cardname]) { + str += "响应" + lib.translate[cardname]; + } + } + next.prompt = str; + } + } + next.position = "hs"; + if (next.ai2 == undefined) next.ai2 = (() => 1); + next.setContent("chooseToRespond"); + next._args = Array.from(arguments); + return next; + } + chooseToDiscard() { + var next = game.createEvent("chooseToDiscard"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "number") { + next.selectCard = [arguments[i], arguments[i]]; + } + else if (get.itemtype(arguments[i]) == "select") { + next.selectCard = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "dialog") { + next.dialog = arguments[i]; + next.prompt = false; + } + else if (typeof arguments[i] == "boolean") { + next.forced = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "position") { + next.position = arguments[i]; + } + else if (typeof arguments[i] == "function") { + if (next.filterCard) next.ai = arguments[i]; + else next.filterCard = arguments[i]; + } + else if (typeof arguments[i] == "object" && arguments[i]) { + next.filterCard = get.filter(arguments[i]); + } + else if (typeof arguments[i] == "string") { + get.evtprompt(next, arguments[i]); + } + if (arguments[i] === null) { + for (var i = 0; i < arguments.length; i++) { + console.log(arguments[i]); + } + } + } + if (next.isMine() == false && next.dialog) next.dialog.style.display = "none"; + if (next.filterCard == undefined) next.filterCard = lib.filter.all; + if (next.selectCard == undefined) next.selectCard = [1, 1]; + if (next.ai == undefined) next.ai = get.unuseful; + next.autochoose = function () { + if (!this.forced) return false; + if (typeof this.selectCard == "function") return false; + var cards = this.player.getCards(this.position); + var num = cards.length; + for (var i = 0; i < cards.length; i++) { + if (!lib.filter.cardDiscardable(cards[i], this.player, this)) num--; + } + return get.select(this.selectCard)[0] >= num; + } + next.setContent("chooseToDiscard"); + next._args = Array.from(arguments); + return next; + } + chooseToCompare(target, check) { + var next = game.createEvent("chooseToCompare"); + next.player = this; + if (Array.isArray(target)) { + next.targets = target; + if (check) next.ai = check; + else next.ai = function (card) { + if (typeof card == "string" && lib.skill[card]) { + var ais = lib.skill[card].check || function () { return 0 }; + return ais(); + } + var addi = (get.value(card) >= 8 && get.type(card) != "equip") ? -3 : 0; + if (card.name == "du") addi -= 3; + var source = _status.event.source; + var player = _status.event.player; + var event = _status.event.getParent(); + var getn = function (card) { + if (player.hasSkill("tianbian") && get.suit(card) == "heart") return 13 * (event.small ? -1 : 1); + return get.number(card) * (event.small ? -1 : 1); + } + if (source && source != player) { + if (get.attitude(player, source) > 1) { + if (event.small) return getn(card) - get.value(card) / 2 + addi; + return -getn(card) - get.value(card) / 2 + addi; + } + if (event.small) return -getn(card) - get.value(card) / 2 + addi; + return getn(card) - get.value(card) / 2 + addi; + } + else { + if (event.small) return -getn(card) - get.value(card) / 2 + addi; + return getn(card) - get.value(card) / 2 + addi; + } + } + next.setContent("chooseToCompareMultiple"); + } + else { + next.target = target; + if (check) next.ai = check; + else next.ai = function (card) { + if (typeof card == "string" && lib.skill[card]) { + var ais = lib.skill[card].check || function () { return 0 }; + return ais(); + } + var player = get.owner(card); + var getn = function (card) { + if (player.hasSkill("tianbian") && get.suit(card) == "heart") return 13; + return get.number(card); + } + var event = _status.event.getParent(); + var to = (player == event.player ? event.target : event.player); + var addi = (get.value(card) >= 8 && get.type(card) != "equip") ? -6 : 0; + if (card.name == "du") addi -= 5; + if (player == event.player) { + if (event.small) { + return -getn(card) - get.value(card) / 2 + addi; + } + return getn(card) - get.value(card) / 2 + addi; + } + else { + if ((get.attitude(player, to) <= 0) == Boolean(event.small)) { + return -getn(card) - get.value(card) / 2 + addi; + } + return getn(card) - get.value(card) / 2 + addi; + } + } + next.setContent("chooseToCompare"); + } + next.forceDie = true; + next._args = Array.from(arguments); + return next; + } + chooseSkill(target) { + var next = game.createEvent("chooseSkill"); + next.player = this; + next.setContent("chooseSkill"); + next.target = target; + for (var i = 1; i < arguments.length; i++) { + if (typeof arguments[i] == "string") { + next.prompt = arguments[i]; + } + else if (typeof arguments[i] == "function") { + next.func = arguments[i]; + } + } + } + discoverCard(list) { + var next = game.createEvent("discoverCard"); + next.player = this; + next.setContent("discoverCard"); + next.list = list || lib.inpile.slice(0); + next.forced = true; + for (var i = 1; i < arguments.length; i++) { + if (typeof arguments[i] == "boolean") { + next.forced = arguments[i]; + } + else if (typeof arguments[i] == "string") { + switch (arguments[i]) { + case "use": next.use = true; break; + case "nogain": next.nogain = true; break; + default: next.prompt = arguments[i]; + } + } + else if (typeof arguments[i] == "number") { + next.num = arguments[i]; + } + else if (typeof arguments[i] === "function") { + next.ai = arguments[i]; + } + } + return next; + } + chooseCardButton() { + var cards, prompt, forced, select; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "cards") cards = arguments[i]; + else if (typeof arguments[i] == "boolean") forced = arguments[i]; + else if (typeof arguments[i] == "string") prompt = arguments[i]; + else if (get.itemtype(arguments[i]) == "select" || typeof arguments[i] == "number") select = arguments[i]; + } + if (prompt == undefined) prompt = "请选择卡牌"; + return this.chooseButton(forced, select, "hidden", [prompt, cards, "hidden"]); + } + chooseVCardButton() { + var list, prompt, forced, select, notype = false; + for (var i = 0; i < arguments.length; i++) { + if (Array.isArray(arguments[i])) { + list = arguments[i]; + } + else if (arguments[i] == "notype") { + notype = true; + } + else if (typeof arguments[i] == "boolean") forced = arguments[i]; + else if (typeof arguments[i] == "string") prompt = arguments[i]; + else if (get.itemtype(arguments[i]) == "select" || typeof arguments[i] == "number") select = arguments[i]; + } + for (var i = 0; i < list.length; i++) { + list[i] = [notype ? "" : (get.subtype(list[i], false) || get.type(list[i])), "", list[i]]; + } + if (prompt == undefined) prompt = "请选择卡牌"; + return this.chooseButton(forced, select, "hidden", [prompt, [list, "vcard"], "hidden"]); + } + chooseButton() { + var next = game.createEvent("chooseButton"); + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "boolean") { + next.forced = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "dialog") { + next.dialog = arguments[i]; + next.closeDialog = true; + } + else if (get.itemtype(arguments[i]) == "select") { + next.selectButton = arguments[i]; + } + else if (typeof arguments[i] == "number") { + next.selectButton = [arguments[i], arguments[i]]; + } + else if (typeof arguments[i] == "function") { + if (next.ai) next.filterButton = arguments[i]; + else next.ai = arguments[i]; + } + else if (Array.isArray(arguments[i])) { + next.createDialog = arguments[i]; + } + } + next.player = this; + if (typeof next.forced != "boolean") next.forced = false; + if (next.isMine() == false && next.dialog) next.dialog.style.display = "none"; + if (next.filterButton == undefined) next.filterButton = lib.filter.filterButton; + if (next.selectButton == undefined) next.selectButton = [1, 1]; + if (next.ai == undefined) next.ai = function () { return 1 }; + next.setContent("chooseButton"); + next._args = Array.from(arguments); + next.forceDie = true; + return next; + } + chooseButtonOL(list, callback, ai) { + var next = game.createEvent("chooseButtonOL"); + next.list = list; + next.setContent("chooseButtonOL"); + next.ai = ai; + next.callback = callback; + next._args = Array.from(arguments); + return next; + } + chooseCardOL() { + var next = game.createEvent("chooseCardOL"); + next._args = []; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "players") { + next.list = arguments[i].slice(0); + } + else { + next._args.push(arguments[i]); + } + } + next.setContent("chooseCardOL"); + next._args.add("glow_result"); + return next; + } + chooseCard(choose) { + var next = game.createEvent("chooseCard"); + next.player = this; + if (arguments.length == 1 && get.is.object(choose)) { + for (var i in choose) { + next[i] = choose[i]; + } + } + else { + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "number") { + next.selectCard = [arguments[i], arguments[i]]; + } + else if (get.itemtype(arguments[i]) == "select") { + next.selectCard = arguments[i]; + } + else if (typeof arguments[i] == "boolean") { + next.forced = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "position") { + next.position = arguments[i]; + } + else if (typeof arguments[i] == "function") { + if (next.filterCard) next.ai = arguments[i]; + else next.filterCard = arguments[i]; + } + else if (typeof arguments[i] == "object" && arguments[i]) { + next.filterCard = get.filter(arguments[i]); + } + else if (arguments[i] == "glow_result") { + next.glow_result = true; + } + else if (typeof arguments[i] == "string") { + get.evtprompt(next, arguments[i]); + } + } + } + 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.setContent("chooseCard"); + next._args = Array.from(arguments); + return next; + } + chooseUseTarget() { + var next = game.createEvent("chooseUseTarget"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "cards") { + next.cards = arguments[i].slice(0); + } + else if (get.itemtype(arguments[i]) == "card") { + next.card = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "players") { + next.targets = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "player") { + next.targets = [arguments[i]]; + } + else if (get.itemtype(arguments[i]) == "select") { + next.selectTarget = arguments[i]; + } + else if (typeof arguments[i] == "number") { + next.selectTarget = [arguments[i], arguments[i]]; + } + else if (get.is.object(arguments[i]) && arguments[i].name) { + next.card = arguments[i]; + } + else if (typeof arguments[i] == "string") { + if (arguments[i] == "nopopup") { + next.nopopup = true; + } + else if (arguments[i] == "noanimate") { + next.animate = false; + } + else if (arguments[i] == "nothrow") { + next.throw = false; + } + else if (arguments[i] == "nodistance") { + next.nodistance = true; + } + else if (arguments[i] == "noTargetDelay") { + next.noTargetDelay = true; + } + else if (arguments[i] == "nodelayx") { + next.nodelayx = true; + } + else if (lib.card[arguments[i]] && !next.card) { + next.card = { name: arguments[i], isCard: true }; + } + else get.evtprompt(next, arguments[i]); + } + else if (arguments[i] === true) { + next.forced = true; + } + else if (arguments[i] === false) { + next.addCount = false; + } + } + if (!next.targets) next.targets = game.players.slice(0); + if (next.cards == undefined) { + if (get.itemtype(next.card) == "card") { + next.cards = [next.card]; + } + else next.cards = []; + } + else if (next.card == undefined) { + if (next.cards) { + next.card = next.cards[0]; + } + } + next.setContent("chooseUseTarget"); + next._args = Array.from(arguments); + return next; + // Fully Online-Ready! Enjoy It! + } + chooseTarget() { + var next = game.createEvent("chooseTarget"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "number") { + next.selectTarget = [arguments[i], arguments[i]]; + } + else if (get.itemtype(arguments[i]) == "select") { + next.selectTarget = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "dialog") { + next.dialog = arguments[i]; + next.prompt = false; + } + else if (typeof arguments[i] == "boolean") { + next.forced = arguments[i]; + } + else if (typeof arguments[i] == "function") { + if (next.filterTarget) next.ai = arguments[i]; + else next.filterTarget = arguments[i]; + } + else if (typeof arguments[i] == "string") { + get.evtprompt(next, arguments[i]); + } + } + if (next.filterTarget == undefined) next.filterTarget = lib.filter.all; + if (next.selectTarget == undefined) next.selectTarget = [1, 1]; + if (next.ai == undefined) next.ai = get.attitude2; + next.setContent("chooseTarget"); + next._args = Array.from(arguments); + next.forceDie = true; + return next; + } + chooseCardTarget(choose) { + var next = game.createEvent("chooseCardTarget"); + next.player = this; + if (arguments.length == 1) { + for (var i in choose) { + next[i] = choose[i]; + } + } + if (typeof next.filterCard == "object") { + next.filterCard = get.filter(next.filterCard); + } + if (typeof next.filterTarget == "object") { + next.filterTarget = get.filter(next.filterTarget, 2); + } + if (next.filterCard == undefined || next.filterCard === true) { + next.filterCard = lib.filter.all; + } + if (next.selectCard == undefined) { + next.selectCard = 1; + } + if (next.filterTarget == undefined || next.filterTarget === true) { + next.filterTarget = lib.filter.all; + } + if (next.selectTarget == undefined) { + next.selectTarget = 1; + } + if (next.ai1 == undefined) next.ai1 = get.unuseful2; + if (next.ai2 == undefined) next.ai2 = get.attitude2; + next.setContent("chooseCardTarget"); + next._args = Array.from(arguments); + return next; + } + chooseControlList() { + var list = []; + var prompt = null; + var forced = "cancel2"; + var func = null; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "string") { + if (!prompt) { + prompt = arguments[i]; + } + else { + list.push(arguments[i]); + } + } + else if (Array.isArray(arguments[i])) { + list = arguments[i]; + } + else if (arguments[i] === true) { + forced = null; + } + else if (typeof arguments[i] == "function") { + func = arguments[i]; + } + } + return this.chooseControl(forced, func).set("choiceList", list).set("prompt", prompt); + } + chooseControl() { + var next = game.createEvent("chooseControl"); + next.controls = []; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "string") { + if (arguments[i] == "dialogcontrol") { + next.dialogcontrol = true; + } + else if (arguments[i] == "seperate") { + next.seperate = true; + } + else { + next.controls.push(arguments[i]); + } + } + else if (Array.isArray(arguments[i])) { + next.controls = next.controls.concat(arguments[i]); + } + else if (typeof arguments[i] == "function") { + next.ai = arguments[i]; + } + else if (typeof arguments[i] == "number") { + next.choice = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "dialog") { + next.dialog = arguments[i]; + } + } + next.player = this; + if (next.choice == undefined) next.choice = 0; + next.setContent("chooseControl"); + next._args = Array.from(arguments); + next.forceDie = true; + return next; + } + chooseBool() { + var next = game.createEvent("chooseBool"); + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "boolean") { + next.choice = arguments[i]; + } + else if (typeof arguments[i] == "function") { + next.ai = arguments[i]; + } + else if (typeof arguments[i] == "string") { + get.evtprompt(next, arguments[i]); + } + else if (get.itemtype(arguments[i]) == "dialog") { + next.dialog = arguments[i]; + } + if (next.choice == undefined) next.choice = true; + } + next.player = this; + next.setContent("chooseBool"); + next._args = Array.from(arguments); + next.forceDie = true; + return next; + } + chooseDrawRecover() { + var next = game.createEvent("chooseDrawRecover", false); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "number") { + if (typeof next.num1 == "number") { + next.num2 = arguments[i]; + } + else { + next.num1 = arguments[i]; + } + } + else if (typeof arguments[i] == "boolean") { + next.forced = arguments[i]; + } + else if (typeof arguments[i] == "string") { + next.prompt = arguments[i]; + } + else if (typeof arguments[i] == "function") { + next.ai = arguments[i]; + } + } + if (typeof next.num1 != "number") { + next.num1 = 1; + } + if (typeof next.num2 != "number") { + next.num2 = 1; + } + next.setContent("chooseDrawRecover"); + return next; + } + choosePlayerCard() { + var next = game.createEvent("choosePlayerCard"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + next.target = arguments[i]; + } + else if (typeof arguments[i] == "number") { + next.selectButton = [arguments[i], arguments[i]]; + } + else if (get.itemtype(arguments[i]) == "select") { + next.selectButton = arguments[i]; + } + else if (typeof arguments[i] == "boolean") { + next.forced = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "position") { + next.position = arguments[i]; + } + else if (arguments[i] == "visible") { + next.visible = true; + } + else if (typeof arguments[i] == "function") { + if (next.ai) next.filterButton = arguments[i]; + else next.ai = arguments[i]; + } + else if (typeof arguments[i] == "object" && arguments[i]) { + next.filterButton = get.filter(arguments[i]); + } + else if (typeof arguments[i] == "string") { + next.prompt = arguments[i]; + } + } + if (next.filterButton == undefined) next.filterButton = lib.filter.all; + if (next.position == undefined) next.position = "he"; + if (next.selectButton == undefined) next.selectButton = [1, 1]; + if (next.ai == undefined) next.ai = function (button) { + var val = get.buttonValue(button); + if (get.attitude(_status.event.player, get.owner(button.link)) > 0) return -val; + return val; + }; + next.setContent("choosePlayerCard"); + next._args = Array.from(arguments); + return next; + } + discardPlayerCard() { + var next = game.createEvent("discardPlayerCard"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + next.target = arguments[i]; + } + else if (typeof arguments[i] == "number") { + next.selectButton = [arguments[i], arguments[i]]; + } + else if (get.itemtype(arguments[i]) == "select") { + next.selectButton = arguments[i]; + } + else if (typeof arguments[i] == "boolean") { + next.forced = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "position") { + next.position = arguments[i]; + } + else if (arguments[i] == "visible") { + next.visible = true; + } + else if (typeof arguments[i] == "function") { + if (next.ai) next.filterButton = arguments[i]; + else next.ai = arguments[i]; + } + else if (typeof arguments[i] == "object" && arguments[i]) { + next.filterButton = get.filter(arguments[i]); + } + else if (typeof arguments[i] == "string") { + next.prompt = arguments[i]; + } + } + if (next.filterButton == undefined) next.filterButton = lib.filter.all; + if (next.position == undefined) next.position = "he"; + if (next.selectButton == undefined) next.selectButton = [1, 1]; + if (next.ai == undefined) next.ai = function (button) { + var val = get.buttonValue(button); + if (get.attitude(_status.event.player, get.owner(button.link)) > 0) return -val; + return val; + }; + next.setContent("discardPlayerCard"); + next._args = Array.from(arguments); + return next; + } + gainPlayerCard() { + var next = game.createEvent("gainPlayerCard"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + next.target = arguments[i]; + } + else if (typeof arguments[i] == "number") { + next.selectButton = [arguments[i], arguments[i]]; + } + else if (get.itemtype(arguments[i]) == "select") { + next.selectButton = arguments[i]; + } + else if (typeof arguments[i] == "boolean") { + next.forced = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "position") { + next.position = arguments[i]; + } + else if (arguments[i] == "visible") { + next.visible = true; + } + else if (arguments[i] == "visibleMove") { + next.visibleMove = true; + } + else if (typeof arguments[i] == "function") { + if (next.ai) next.filterButton = arguments[i]; + else next.ai = arguments[i]; + } + else if (typeof arguments[i] == "object" && arguments[i]) { + next.filterButton = get.filter(arguments[i]); + } + else if (typeof arguments[i] == "string") { + next.prompt = arguments[i]; + } + } + if (next.filterButton == undefined) next.filterButton = lib.filter.all; + if (next.position == undefined) next.position = "he"; + if (next.selectButton == undefined) next.selectButton = [1, 1]; + if (next.ai == undefined) next.ai = function (button) { + var val = get.buttonValue(button); + if (get.attitude(_status.event.player, get.owner(button.link)) > 0) return -val; + return val; + }; + next.setContent("gainPlayerCard"); + next._args = Array.from(arguments); + return next; + } + showHandcards(str) { + var next = game.createEvent("showHandcards"); + next.player = this; + if (typeof str == "string") { + next.prompt = str; + } + next.setContent("showHandcards"); + next._args = Array.from(arguments); + return next; + } + showCards(cards, str) { + var next = game.createEvent("showCards"); + next.player = this; + next.str = str; + if (typeof cards == "string") { + str = cards; + cards = next.str; + next.str = str; + } + if (get.itemtype(cards) == "card") next.cards = [cards]; + else if (get.itemtype(cards) == "cards") next.cards = cards.slice(0); + else _status.event.next.remove(next); + next.setContent("showCards"); + next._args = Array.from(arguments); + return next; + } + viewCards(str, cards) { + var next = game.createEvent("viewCards"); + next.player = this; + next.str = str; + next.cards = cards.slice(0); + next.setContent("viewCards"); + next._args = Array.from(arguments); + return next; + } + viewHandcards(target) { + var cards = target.getCards("h"); + if (cards.length) { + return this.viewCards(get.translation(target) + "的手牌", cards); + } + else { + return false; + } + } + canMoveCard(withatt, nojudge) { + const player = this; + const args = Array.from(arguments).slice(2); + let sourceTargets, aimTargets, filterCard, canReplace; + args.forEach(arg => { + if (get.itemtype(arg) == "players") { + if (!sourceTargets) sourceTargets = arg; + else if (!aimTargets) aimTargets = arg; + } + else if (get.itemtype(arg) == "player") { + if (!sourceTargets) sourceTargets = [arg]; + else if (!aimTargets) aimTargets = [arg]; + } + else if (typeof arg == "function") { + filterCard = arg; + } + else if (typeof arg == "object" && arg) { + filterCard = get.filter(arg); + } + else if (arg == "canReplace") { + canReplace = true; + } + }); + if (!sourceTargets) sourceTargets = game.filterPlayer(); + if (!aimTargets) aimTargets = game.filterPlayer(); + return sourceTargets.some(current => { + const att = get.sgn(get.attitude(player, current)); + if (!withatt || att != 0) { + var es = current.getCards("e", filterCard); + for (var i = 0; i < es.length; i++) { + if (aimTargets.some(current2 => { + if (withatt) { + if (get.sgn(get.value(es[i], current)) != -att) return false; + var att2 = get.sgn(get.attitude(player, current2)); + if (!canReplace || att < 0 && current2.countEquipableSlot(get.subtype(es[i]))) { + if (att == att2 || att2 != get.sgn(get.effect(current2, es[i], player, current2))) return false; + } + } + return current != current2 && !current2.isMin() && current2.canEquip(es[i], canReplace); + })) { + return true; + } + } + } + if (!nojudge && (!withatt || att > 0)) { + var js = current.getCards("j", filterCard); + for (var i = 0; i < js.length; i++) { + if (game.hasPlayer(function (current2) { + if (withatt) { + var att2 = get.attitude(player, current2); + if (att2 >= 0) return false; + } + return current != current2 && current2.canAddJudge(js[i]); + })) { + return true; + } + } + } + }); + } + moveCard() { + var next = game.createEvent("moveCard"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "boolean") { + next.forced = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "players") { + if (!next.sourceTargets) next.sourceTargets = arguments[i]; + else if (!next.aimTargets) next.aimTargets = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "player") { + if (!next.sourceTargets) next.sourceTargets = [arguments[i]]; + else if (!next.aimTargets) next.aimTargets = [arguments[i]]; + } + else if (typeof arguments[i] == "string") { + if (arguments[i] == "canReplace") { + next.canReplace = true; + } + else { + get.evtprompt(next, arguments[i]); + } + } + else if (Array.isArray(arguments[i])) { + for (var j = 0; j < arguments[i].length; j++) { + if (typeof arguments[i][j] != "string") break; + } + if (j == arguments[i].length) { + next.targetprompt = arguments[i]; + } + } + else if (typeof arguments[i] == "function") { + next.filter = arguments[i]; + } + else if (typeof arguments[i] == "object" && arguments[i]) { + next.filter = get.filter(arguments[i]); + } + } + if (!next.sourceTargets) next.sourceTargets = game.filterPlayer(); + if (!next.aimTargets) next.aimTargets = game.filterPlayer(); + if (next.filter == undefined) next.filter = lib.filter.all; + next.setContent("moveCard"); + next._args = Array.from(arguments); + return next; + } + useResult(result, event) { + event = event || _status.event; + if (result._sendskill) { + lib.skill[result._sendskill[0]] = result._sendskill[1]; + } + if (event.onresult) { + event.onresult(result); + } + if (result.skill) { + var info = get.info(result.skill); + if (info.onuse) { + info.onuse(result, this); + } + // if(info.direct&&!info.clearTime){ + // _status.noclearcountdown=true; + // } + } + if (event.logSkill) { + if (typeof event.logSkill == "string") { + this.logSkill(event.logSkill); + } + else if (Array.isArray(event.logSkill)) { + this.logSkill.apply(this, event.logSkill); + } + } + if (result.card || !result.skill) { + result.used = result.card || result.cards[0]; + var next = this.useCard(result.used, result.cards, result.targets, result.skill); + next.oncard = event.oncard; + next.respondTo = event.respondTo; + if (event.addCount === false) { + next.addCount = false; + } + if (result._apply_args) { + for (var i in result._apply_args) { + next[i] = result._apply_args[i]; + } + } + return next; + } + else if (result.skill) { + result.used = result.skill; + return this.useSkill(result.skill, result.cards, result.targets); + } + } + useCard() { + var next = game.createEvent("useCard"); + next.player = this; + next.num = 0; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "cards") { + next.cards = arguments[i].slice(0); + } + else if (get.itemtype(arguments[i]) == "players") { + next.targets = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "player") { + next.targets = [arguments[i]]; + } + else if (get.itemtype(arguments[i]) == "card") { + next.card = arguments[i]; + } + else if (typeof arguments[i] == "object" && arguments[i] && arguments[i].name) { + next.card = arguments[i]; + } + else if (typeof arguments[i] == "string") { + if (arguments[i] == "noai") { + next.noai = true; + } + else if (arguments[i] == "nowuxie") { + next.nowuxie = true; + } + else { + next.skill = arguments[i]; + } + } + else if (typeof arguments[i] == "boolean") { + next.addCount = arguments[i]; + } + } + if (next.cards == undefined) { + if (get.itemtype(next.card) == "card") { + next.cards = [next.card]; + } + else next.cards = []; + } + else if (next.card == undefined) { + if (next.cards) { + next.card = next.cards[0]; + } + } + if (!next.targets) { + next.targets = []; + } + if (next.card) { + next.card = get.autoViewAs(next.card, next.cards); + var info = get.info(next.card); + if (info.changeTarget) { + info.changeTarget(next.player, next.targets); + } + if (info.singleCard) { + next._targets = next.targets.slice(0); + next.target = next.targets[0]; + next.addedTargets = next.targets.splice(1); + if (next.addedTargets.length) { + next.addedTarget = next.addedTargets[0]; + } + } + } + for (var i = 0; i < next.targets.length; i++) { + if (get.attitude(this, next.targets[i]) >= -1 && get.attitude(this, next.targets[i]) < 0) { + if (!this.ai.tempIgnore) this.ai.tempIgnore = []; + this.ai.tempIgnore.add(next.targets[i]); + } + } + if (typeof this.logAi == "function" && !next.noai && !get.info(next.card).noai) { + var postAi = get.info(next.card).postAi; + if (postAi && postAi(next.targets)) { + next.postAi = true; + } + else { + this.logAi(next.targets, next.card); + } + } + next.stocktargets = next.targets.slice(0); + next.setContent("useCard"); + return next; + } + useSkill() { + var next = game.createEvent("useSkill"); + next.player = this; + next.num = 0; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "cards") { + next.cards = arguments[i].slice(0); + } + else if (get.itemtype(arguments[i]) == "players") { + next.targets = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "card") { + next.card = arguments[i]; + } + else if (typeof arguments[i] == "string") { + next.skill = arguments[i]; + } + else if (typeof arguments[i] == "boolean") { + next.addCount = arguments[i]; + } + } + if (next.cards == undefined) { + next.cards = []; + } + if (next.skill && get.info(next.skill) && get.info(next.skill).changeTarget) { + get.info(next.skill).changeTarget(next.player, next.targets); + } + if (next.targets) { + for (var i = 0; i < next.targets.length; i++) { + if (get.attitude(this, next.targets[i]) >= -1 && get.attitude(this, next.targets[i]) < 0) { + if (!this.ai.tempIgnore) this.ai.tempIgnore = []; + this.ai.tempIgnore.add(next.targets[i]); + } + } + if (typeof this.logAi == "function") { + this.logAi(next.targets, next.skill); + } + } + else { + next.targets = []; + } + next.setContent("useSkill"); + return next; + } + drawTo(num, args) { + var num2 = num - this.countCards("h"); + if (!num2) return; + var next = this.draw(num2); + if (Array.isArray(args)) { + for (var i = 0; i < args.length; i++) { + if (get.itemtype(args[i]) == "player") { + next.source = args[i]; + } + else if (typeof args[i] == "boolean") { + next.animate = args[i]; + } + else if (args[i] == "nodelay") { + next.animate = false; + next.$draw = true; + } + else if (args[i] == "visible") { + next.visible = true; + } + else if (args[i] == "bottom") { + next.bottom = true; + } + else if (typeof args[i] == "object" && args[i] && args[i].drawDeck != undefined) { + next.drawDeck = args[i].drawDeck; + } + } + } + return next; + } + draw() { + var next = game.createEvent("draw"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + next.source = arguments[i]; + } + else if (typeof arguments[i] == "number") { + next.num = arguments[i]; + } + else if (typeof arguments[i] == "boolean") { + next.animate = arguments[i]; + } + else if (arguments[i] == "nodelay") { + next.animate = false; + next.$draw = true; + } + else if (arguments[i] == "visible") { + next.visible = true; + } + else if (arguments[i] == "bottom") { + next.bottom = true; + } + else if (typeof arguments[i] == "object" && arguments[i] && arguments[i].drawDeck != undefined) { + next.drawDeck = arguments[i].drawDeck; + } + } + if (next.num == undefined) next.num = 1; + if (next.num <= 0) _status.event.next.remove(next); + next.setContent("draw"); + if (lib.config.mode == "stone" && _status.mode == "deck" && + next.drawDeck == undefined && !next.player.isMin() && next.num > 1) { + next.drawDeck = 1; + } + next.result = []; + return next; + } + randomDiscard() { + var position = "he", num = 1, delay = null; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "number") { + num = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "position") { + position = arguments[i]; + } + else if (typeof arguments[i] == "boolean") { + delay = arguments[i]; + } + } + var cards = this.getCards(position).randomGets(num); + if (cards.length) { + var next = this.discard(cards, "notBySelf"); + if (typeof delay == "boolean") { + next.delay = delay; + } + } + return cards; + } + randomGain() { + var position = "he", num = 1, target = null, line = false; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "number") { + num = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "position") { + position = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "player") { + target = arguments[i]; + } + else if (typeof arguments[i] == "boolean") { + line = arguments[i]; + } + } + if (target) { + var cards = target.getCards(position).randomGets(num); + if (cards.length) { + if (line) { + this.line(target, "green"); + } + this.gain(cards, target, "log", "bySelf"); + target.$giveAuto(cards, this); + } + return cards; + } + return []; + } + discard() { + var next = game.createEvent("discard"); + next.player = this; + next.num = 0; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + next.source = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "cards") { + next.cards = arguments[i].slice(0); + } + else if (get.itemtype(arguments[i]) == "card") { + next.cards = [arguments[i]]; + } + else if (typeof arguments[i] == "boolean") { + next.animate = arguments[i]; + } + else if (get.objtype(arguments[i]) == "div") { + next.position = arguments[i]; + } + else if (arguments[i] == "notBySelf") { + next.notBySelf = true; + } + } + if (next.cards == undefined) _status.event.next.remove(next); + next.setContent("discard"); + return next; + } + loseToDiscardpile() { + var next = game.createEvent("loseToDiscardpile"); + next.player = this; + next.num = 0; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + next.source = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "cards") { + next.cards = arguments[i].slice(0); + } + else if (get.itemtype(arguments[i]) == "card") { + next.cards = [arguments[i]]; + } + else if (typeof arguments[i] == "boolean") { + next.animate = arguments[i]; + } + else if (get.objtype(arguments[i]) == "div") { + next.position = arguments[i]; + } + else if (arguments[i] == "notBySelf") { + next.notBySelf = true; + } + else if (arguments[i] == "insert") { + next.insert_card = true; + } + else if (arguments[i] == "blank") { + next.blank = true; + } + } + if (next.cards == undefined) _status.event.next.remove(next); + next.setContent("loseToDiscardpile"); + return next; + } + respond() { + var next = game.createEvent("respond"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "cards") { + next.cards = arguments[i].slice(0); + } + else if (get.itemtype(arguments[i]) == "card") { + next.card = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "player") { + next.source = arguments[i]; + } + else if (typeof arguments[i] == "object" && arguments[i] && arguments[i].name) { + next.card = arguments[i]; + } + else if (typeof arguments[i] == "boolean") next.animate = arguments[i]; + else if (arguments[i] == "highlight") next.highlight = true; + else if (arguments[i] == "noOrdering") next.noOrdering = true; + else if (typeof arguments[i] == "string") next.skill = arguments[i]; + } + if (next.cards == undefined) { + if (get.itemtype(next.card) == "card") { + next.cards = [next.card]; + } + else { + next.cards = []; + } + } + else if (next.card == undefined) { + if (next.cards) { + next.card = next.cards[0]; + if (!next.skill) { + next.card = get.autoViewAs(next.card, next.cards); + } + } + } + next.setContent("respond"); + return next; + } + swapHandcards(target, cards1, cards2) { + var next = game.createEvent("swapHandcards", false); + next.player = this; + next.target = target; + if (cards1) next.cards1 = cards1; + if (cards2) next.cards2 = cards2; + next.setContent("swapHandcards"); + return next; + } + directequip(cards) { + for (var i = 0; i < cards.length; i++) { + this.$equip(cards[i]); + } + if (!_status.video) { + game.addVideo("directequip", this, get.cardsInfo(cards)); + } + } + $addToExpansion(cards, broadcast, gaintag) { + var hs = this.getCards("x"); + for (var i = 0; i < cards.length; i++) { + if (hs.contains(cards[i])) { + cards.splice(i--, 1); + } + } + for (var i = 0; i < cards.length; i++) { + cards[i].fix(); + if (gaintag) cards[i].addGaintag(gaintag); + var sort = lib.config.sort_card(cards[i]); + this.node.expansions.insertBefore(cards[i], this.node.expansions.firstChild); + } + if (broadcast !== false) game.broadcast(function (player, cards, gaintag) { + player.$addToExpansion(cards, null, gaintag); + }, this, cards, gaintag); + return this; + } + directgain(cards, broadcast, gaintag) { + var hs = this.getCards("hs"); + for (var i = 0; i < cards.length; i++) { + if (hs.contains(cards[i])) { + cards.splice(i--, 1); + } + } + for (var i = 0; i < cards.length; i++) { + cards[i].fix(); + if (gaintag) cards[i].addGaintag(gaintag); + var sort = lib.config.sort_card(cards[i]); + if (this == game.me) { + cards[i].classList.add("drawinghidden"); + } + if (get.is.singleHandcard() || sort > 0) { + this.node.handcards1.insertBefore(cards[i], this.node.handcards1.firstChild); + } + else { + this.node.handcards2.insertBefore(cards[i], this.node.handcards2.firstChild); + } + } + if (this == game.me || _status.video) ui.updatehl(); + if (!_status.video) { + game.addVideo("directgain", this, get.cardsInfo(cards)); + this.update(); + } + if (broadcast !== false) game.broadcast(function (player, cards) { + player.directgain(cards); + }, this, cards); + return this; + } + directgains(cards, broadcast, gaintag) { + var hs = this.getCards("hs"); + for (var i = 0; i < cards.length; i++) { + if (hs.contains(cards[i])) { + cards.splice(i--, 1); + } + } + var addLast = function (card, node) { + if (gaintag) { + for (var i = 0; i < node.childNodes.length; i++) { + var add = node.childNodes[node.childNodes.length - i - 1]; + if (!add.classList.contains("glows")) break; + if (add.hasGaintag(gaintag)) { + node.insertBefore(card, add.nextSibling); + return; + } + } + } + node.appendChild(card); + } + for (var i = 0; i < cards.length; i++) { + cards[i].fix(); + cards[i].remove(); + if (gaintag) cards[i].addGaintag(gaintag); + cards[i].classList.add("glows"); + if (this == game.me) { + cards[i].classList.add("drawinghidden"); + } + if (get.is.singleHandcard()) { + addLast(cards[i], this.node.handcards1); + } + else { + addLast(cards[i], this.node.handcards2); + } + } + if (this == game.me || _status.video) ui.updatehl(); + if (!_status.video) { + game.addVideo("directgains", this, get.cardsInfo(cards)); + this.update(); + } + if (broadcast !== false) game.broadcast(function (player, cards, gaintag) { + player.directgains(cards, null, gaintag); + }, this, cards, gaintag); + return this; + } + gainMultiple(targets, position) { + var next = game.createEvent("gainMultiple", false); + next.setContent("gainMultiple"); + next.player = this; + next.targets = targets; + next.position = position || "h"; + return next; + } + gain() { + var next = game.createEvent("gain"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + next.source = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "cards") { + next.cards = arguments[i].slice(0); + } + else if (get.itemtype(arguments[i]) == "card") { + next.cards = [arguments[i]]; + } + else if (arguments[i] === "log") { + next.log = true; + } + else if (arguments[i] == "fromStorage") { + next.fromStorage = true; + } + else if (arguments[i] == "fromRenku") { + next.fromStorage = true; + next.fromRenku = true; + } + else if (arguments[i] == "bySelf") { + next.bySelf = true; + } + else if (typeof arguments[i] == "string") { + next.animate = arguments[i]; + } + else if (typeof arguments[i] == "boolean") { + next.delay = arguments[i]; + } + } + if (next.animate == "gain2" || next.animate == "draw2") { + if (!Object.prototype.hasOwnProperty.call(next, "log")) { + next.log = true; + } + } + next.setContent("gain"); + next.getd = function (player, key, position) { + if (!position) position = ui.discardPile; + if (!key) key = "cards"; + var cards = [], event = this; + game.checkGlobalHistory("cardMove", function (evt) { + if (evt.name != "lose" || evt.position != position || evt.getParent() != event) return; + if (player && player != evt.player) return; + cards.addArray(evt[key]); + }); + return cards; + }; + next.getl = function (player) { + const that = this; + const map = { + player: player, + hs: [], + es: [], + js: [], + ss: [], + xs: [], + cards: [], + cards2: [], + gaintag_map: {}, + }; + player.checkHistory("lose", function (evt) { + if (evt.parent == that) { + map.hs.addArray(evt.hs); + map.es.addArray(evt.es); + map.js.addArray(evt.js); + map.ss.addArray(evt.ss); + map.xs.addArray(evt.xs); + map.cards.addArray(evt.cards); + map.cards2.addArray(evt.cards2); + for (let key in evt.gaintag_map) { + if (!map.gaintag_map[key]) map.gaintag_map[key] = []; + map.gaintag_map[key].addArray(evt.gaintag_map[key]); + } + } + }); + return map; + }; + next.getg = function (player) { + if (this.getlx === false || player != this.player || !this.cards) return []; + return this.cards.slice(0); + } + next.gaintag = []; + return next; + } + addToExpansion() { + var next = game.createEvent("addToExpansion"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + next.source = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "cards") { + next.cards = arguments[i].slice(0); + } + else if (get.itemtype(arguments[i]) == "card") { + next.cards = [arguments[i]]; + } + else if (arguments[i] === "log") { + next.log = true; + } + else if (arguments[i] == "fromStorage") { + next.fromStorage = true; + } + else if (arguments[i] == "fromRenku") { + next.fromStorage = true; + next.fromRenku = true; + } + else if (arguments[i] == "bySelf") { + next.bySelf = true; + } + else if (typeof arguments[i] == "string") { + next.animate = arguments[i]; + } + else if (typeof arguments[i] == "boolean") { + next.delay = arguments[i]; + } + } + if (next.animate == "gain2" || next.animate == "draw2" || next.animate == "give") { + if (!Object.prototype.hasOwnProperty.call(next, "log")) { + next.log = true; + } + } + next.setContent("addToExpansion"); + next.getd = function (player, key, position) { + if (!position) position = ui.discardPile; + if (!key) key = "cards"; + var cards = [], event = this; + game.checkGlobalHistory("cardMove", function (evt) { + if (evt.name != "lose" || evt.position != position || evt.getParent() != event) return; + if (player && player != evt.player) return; + cards.addArray(evt[key]); + }); + return cards; + }; + next.getl = function (player) { + const that = this; + const map = { + player: player, + hs: [], + es: [], + js: [], + ss: [], + xs: [], + cards: [], + cards2: [], + gaintag_map: {}, + }; + player.checkHistory("lose", function (evt) { + if (evt.parent == that) { + map.hs.addArray(evt.hs); + map.es.addArray(evt.es); + map.js.addArray(evt.js); + map.ss.addArray(evt.ss); + map.xs.addArray(evt.xs); + map.cards.addArray(evt.cards); + map.cards2.addArray(evt.cards2); + for (let key in evt.gaintag_map) { + if (!map.gaintag_map[key]) map.gaintag_map[key] = []; + map.gaintag_map[key].addArray(evt.gaintag_map[key]); + } + } + }); + return map; + }; + next.gaintag = []; + return next; + } + give(cards, target, visible) { + var next = target.gain(cards, this); + next.animate = visible ? "give" : "giveAuto"; + next.giver = this; + return next; + } + lose() { + var next = game.createEvent("lose"); + next.player = this; + next.forceDie = true; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "player") { + next.source = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "cards") { + next.cards = arguments[i].slice(0); + } + else if (get.itemtype(arguments[i]) == "card") { + next.cards = [arguments[i]]; + } + else if (get.objtype(arguments[i]) == "div") { + next.position = arguments[i]; + } + else if (arguments[i] == "toStorage") { + next.toStorage = true; + } + else if (arguments[i] == "toRenku") { + next.toStorage = true; + next.toRenku = true; + } + else if (arguments[i] == "visible") { + next.visible = true; + } + else if (arguments[i] == "insert") { + next.insert_card = true; + } + } + if (next.cards) { + var hej = this.getCards("hejsx"); + for (var i = 0; i < next.cards.length; i++) { + if (!hej.contains(next.cards[i])) { + next.cards.splice(i--, 1); + } + } + } + if (!next.cards || !next.cards.length) { + _status.event.next.remove(next); + } + else { + if (next.position == undefined) next.position = ui.discardPile; + next.cards = next.cards.slice(0); + } + next.setContent("lose"); + next.getd = function (player, key, position) { + if (!position) position = ui.discardPile; + if (!key) key = "cards"; + if (this.getlx === false || this.position != position || (player && this.player != player) || !Array.isArray(this[key])) return []; + return this[key].slice(0); + }; + next.getl = function (player) { + if (this.getlx !== false && this.player == player) return this; + return { + player: player, + hs: [], + es: [], + js: [], + ss: [], + xs: [], + cards: [], + cards2: [], + gaintag_map: {}, + }; + }; + return next; + } + damage() { + const next = game.createEvent("damage"); + //next.forceDie=true; + next.player = this; + let noCard, noSource; + const event = _status.event; + for (const argument of arguments) { + if (get.itemtype(argument) == "cards") next.cards = argument.slice(); + else if (get.itemtype(argument) == "card") next.card = argument; + else if (typeof argument == "number") next.num = argument; + else if (get.itemtype(argument) == "player") next.source = argument; + else if (argument && typeof argument == "object" && argument.name) next.card = argument; + else if (argument == "nocard") noCard = true; + else if (argument == "nosource") noSource = true; + else if (argument == "notrigger") { + next._triggered = null; + next.notrigger = true; + } + else if (argument == "unreal") next.unreal = true; + else if (get.itemtype(argument) == "nature" && argument != "stab") next.nature = argument; + else if (get.itemtype(argument) == "natures") { + const natures = argument.split(lib.natureSeparator).remove("stab"); + if (natures.length) next.nature = natures.join(lib.natureSeparator); + } + } + if (!next.card && !noCard) next.card = event.card; + if (!next.cards && !noCard) next.cards = event.cards; + if (!next.source && !noSource) { + const source = event.customSource || event.player; + if (source && !source.isDead()) next.source = source; + } + if (typeof next.num != "number") next.num = (event.baseDamage || 1) + (event.extraDamage || 0); + next.original_num = next.num; + next.change_history = []; + next.hasNature = function (nature) { + if (!nature) return Boolean(this.nature && this.nature.length > 0); + let natures = get.natureList(nature), naturesx = get.natureList(this.nature); + if (nature == "linked") return naturesx.some(n => lib.linked.includes(n)); + return get.is.sameNature(natures, naturesx); + }; + if (next.hasNature("poison")) delete next._triggered; + next.setContent("damage"); + next.filterStop = function () { + if (this.source && this.source.isDead()) delete this.source; + var num = this.original_num; + for (var i of this.change_history) num += i; + if (num != this.num) this.change_history.push(this.num - num); + if (this.num <= 0) { + delete this.filterStop; + this.trigger("damageZero"); + this.finish(); + this._triggered = null; + return true; + } + }; + return next; + } + recover() { + var next = game.createEvent("recover"); + next.player = this; + var nocard, nosource; + var event = _status.event; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "cards") { + next.cards = arguments[i].slice(0); + } + else if (get.itemtype(arguments[i]) == "card") { + next.card = arguments[i]; + } + else if (get.itemtype(arguments[i]) == "player") { + next.source = arguments[i]; + } + else if (typeof arguments[i] == "object" && arguments[i] && arguments[i].name) { + next.card = arguments[i]; + } + else if (typeof arguments[i] == "number") { + next.num = arguments[i]; + } + else if (arguments[i] == "nocard") { + nocard = true; + } + else if (arguments[i] == "nosource") { + nosource = true; + } + } + if (next.card == undefined && !nocard) next.card = event.card; + if (next.cards == undefined && !nocard) next.cards = event.cards; + if (next.source == undefined && !nosource) next.source = event.customSource || event.player; + if (next.num == undefined) next.num = (event.baseDamage || 1) + (event.extraDamage || 0); + if (next.num <= 0) _status.event.next.remove(next); + next.setContent("recover"); + return next; + } + doubleDraw() { + if (get.is.changban()) return; + var next = game.createEvent("doubleDraw"); + next.player = this; + next.setContent("doubleDraw"); + return next; + } + loseHp(num) { + var next = game.createEvent("loseHp"); + next.num = num; + next.player = this; + if (next.num == undefined) next.num = 1; + next.setContent("loseHp"); + return next; + } + loseMaxHp() { + var next = game.createEvent("loseMaxHp"); + next.player = this; + next.num = 1; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] === "number") { + next.num = arguments[i]; + } + else if (typeof arguments[i] === "boolean") { + next.forced = arguments[i]; + } + } + next.setContent("loseMaxHp"); + return next; + } + gainMaxHp() { + var next = game.createEvent("gainMaxHp"); + next.player = this; + next.num = 1; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] === "number") { + next.num = arguments[i]; + } + else if (typeof arguments[i] === "boolean") { + next.forced = arguments[i]; + } + } + next.setContent("gainMaxHp"); + return next; + } + changeHp(num, popup) { + var next = game.createEvent("changeHp"); + next.num = num; + if (popup != undefined) next.popup = popup; + next.player = this; + next.setContent("changeHp"); + return next; + } + + changeHujia(num, type, limit) { + var next = game.createEvent("changeHujia"); + if (typeof num != "number") { + num = 1; + } + if (limit === true) limit = 5; + if (typeof limit == "number" && this.hujia + num > parseInt(limit)) { + num = Math.max(0, parseInt(limit) - this.hujia); + } + if (typeof type != "string") { + if (num > 0) type = "gain"; + else if (num < 0) type = "lose"; + else type = "null"; + } + next.num = num; + next.player = this; + next.type = type; + next.setContent("changeHujia"); + return next; + } + getBuff() { + var list = [1, 2, 3, 4, 5, 6]; + var nodelay = false; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "number") { + list.remove(arguments[i]); + } + else if (arguments[i] === false) { + nodelay = true; + } + } + if (this.isHealthy()) { + list.remove(2); + } + if (!this.countCards("j")) { + list.remove(5); + } + if (!this.isLinked() && !this.isTurnedOver()) { + list.remove(6); + } + if (this.hasSkill("qianxing")) { + list.remove(4); + } + switch (list.randomGet()) { + case 1: this.draw(nodelay ? "nodelay" : 1); break; + case 2: this.recover(); break; + case 3: this.changeHujia(); break; + case 4: this.tempHide(); break; + case 5: this.discard(this.getCards("j")).delay = (!nodelay); break; + case 6: { + if (this.isLinked()) this.link(); + if (this.isTurnedOver()) this.turnOver(); + break; + } + } + return this; + } + getDebuff() { + var list = [1, 2, 3, 4, 5, 6]; + var nodelay = false; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "number") { + list.remove(arguments[i]); + } + else if (arguments[i] === false) { + nodelay = true; + } + } + if (this.countCards("he") == 0) { + list.remove(1); + } + if (this.isLinked()) { + list.remove(4); + } + if (this.hasSkill("fengyin")) { + list.remove(5); + } + if (this.hp == 1) { + list.remove(3); + if (list.length > 1) list.remove(2); + } + if (!list.length) return this; + var num = list.randomGet(); + switch (list.randomGet()) { + case 1: this.randomDiscard(nodelay ? false : "he"); break; + case 2: this.loseHp(); break; + case 3: this.damage(); break; + case 4: if (!this.isLinked()) this.link(); break; + case 5: this.addTempSkill("fengyin", { player: "phaseAfter" }); break; + case 6: { + var list = []; + for (var i = 0; i < lib.inpile.length; i++) { + var info = lib.card[lib.inpile[i]]; + if (info.type == "delay" && !info.cancel && !this.hasJudge(lib.inpile[i])) { + list.push(lib.inpile[i]); + } + } + if (list.length) { + var card = game.createCard(list.randomGet()); + this.addJudge(card); + this.$draw(card); + if (!nodelay) game.delay(); + } + else { + this.getDebuff(6); + } + break; + } + } + return this; + } + dying(reason) { + if (this.nodying || this.hp > 0 || this.isDying()) return; + var next = game.createEvent("dying"); + next.player = this; + next.reason = reason; + if (reason && reason.source) next.source = reason.source; + next.setContent("dying"); + next.filterStop = function () { + if (this.player.hp > 0 || this.nodying) { + delete this.filterStop; + return true; + } + }; + return next; + } + die(reason) { + var next = game.createEvent("die"); + next.player = this; + next.reason = reason; + if (reason) next.source = reason.source; + next.setContent("die"); + return next; + } + revive(hp, log) { + if (log !== false) game.log(this, "复活"); + if (this.maxHp < 1) this.maxHp = 1; + if (hp) this.hp = hp; + else { + this.hp = 1; + } + game.addVideo("revive", this); + this.classList.remove("dead"); + this.removeAttribute("style"); + this.node.avatar.style.transform = ""; + this.node.avatar2.style.transform = ""; + this.node.hp.show(); + this.node.equips.show(); + this.node.count.show(); + this.update(); + var player; + player = this.previousSeat; + while (player.isDead()) player = player.previousSeat; + player.next = this; + this.previous = player; + player = this.nextSeat; + while (player.isDead()) player = player.nextSeat; + player.previous = this; + this.next = player; + game.players.add(this); + game.dead.remove(this); + if (this == game.me) { + if (ui.auto) ui.auto.show(); + if (ui.wuxie) ui.wuxie.show(); + if (ui.revive) { + ui.revive.close(); + delete ui.revive; + } + if (ui.exit) { + ui.exit.close(); + delete ui.exit; + } + if (ui.swap) { + ui.swap.close(); + delete ui.swap; + } + if (ui.restart) { + ui.restart.close(); + delete ui.restart; + } + if (ui.continue_game) { + ui.continue_game.close(); + delete ui.continue_game; + } + } + } + isMad() { + return this.hasSkill("mad"); + } + goMad(end) { + if (end) { + this.addTempSkill("mad", end); + } + else { + this.addSkill("mad"); + } + game.log(this, "进入混乱状态"); + } + unMad() { + this.removeSkill("mad"); + } + tempHide() { + this.addTempSkill("qianxing", { player: "phaseBeginStart" }); + } + addExpose(num) { + if (typeof this.ai.shown == "number" && !this.identityShown && this.ai.shown < 1) { + this.ai.shown += num; + if (this.ai.shown > 0.95) { + this.ai.shown = 0.95; + } + } + return this; + } + equip(card, draw) { + var next = game.createEvent("equip"); + next.card = card; + next.player = this; + if (draw) { + next.draw = true; + } + next.setContent(lib.element.content.equip); + if (get.is.object(next.card) && next.card.cards) next.card = next.card.cards[0]; + next.cards = [next.card]; + next.getd = function (player, key, position) { + if (!position) position = ui.discardPile; + if (!key) key = "cards"; + var cards = [], event = this; + game.checkGlobalHistory("cardMove", function (evt) { + if (evt.name != "lose" || evt.position != position || evt.getParent() != event) return; + if (player && player != evt.player) return; + cards.addArray(evt[key]); + }); + return cards; + }; + next.getl = function (player) { + const that = this; + const map = { + player: player, + hs: [], + es: [], + js: [], + ss: [], + xs: [], + cards: [], + cards2: [], + gaintag_map: {}, + }; + player.checkHistory("lose", function (evt) { + if (evt.parent == that) { + map.hs.addArray(evt.hs); + map.es.addArray(evt.es); + map.js.addArray(evt.js); + map.ss.addArray(evt.ss); + map.xs.addArray(evt.xs); + map.cards.addArray(evt.cards); + map.cards2.addArray(evt.cards2); + for (let key in evt.gaintag_map) { + if (!map.gaintag_map[key]) map.gaintag_map[key] = []; + map.gaintag_map[key].addArray(evt.gaintag_map[key]); + } + } + }); + return map; + }; + return next; + } + addJudge(card, cards) { + var next = game.createEvent("addJudge"); + if (get.itemtype(card) == "card") { + next.card = card; + next.cards = [card]; + } + else { + next.cards = cards; + if (get.itemtype(next.cards) == "card") next.cards = [next.cards]; + if (typeof card == "string") { + card = { name: card }; + } + next.card = get.autoViewAs(card, next.cards) + } + next.player = this; + next.setContent("addJudge"); + next.getd = function (player, key, position) { + if (!position) position = ui.discardPile; + if (!key) key = "cards"; + var cards = [], event = this; + game.checkGlobalHistory("cardMove", function (evt) { + if (evt.name != "lose" || evt.position != position || evt.getParent() != event) return; + if (player && player != evt.player) return; + cards.addArray(evt[key]); + }); + return cards; + }; + next.getl = function (player) { + const that = this; + const map = { + player: player, + hs: [], + es: [], + js: [], + ss: [], + xs: [], + cards: [], + cards2: [], + gaintag_map: {}, + }; + player.checkHistory("lose", function (evt) { + if (evt.parent == that) { + map.hs.addArray(evt.hs); + map.es.addArray(evt.es); + map.js.addArray(evt.js); + map.ss.addArray(evt.ss); + map.xs.addArray(evt.xs); + map.cards.addArray(evt.cards); + map.cards2.addArray(evt.cards2); + for (let key in evt.gaintag_map) { + if (!map.gaintag_map[key]) map.gaintag_map[key] = []; + map.gaintag_map[key].addArray(evt.gaintag_map[key]); + } + } + }); + return map; + }; + return next; + } + canAddJudge(card) { + if (this.isDisabledJudge()) return false; + var name; + if (typeof card == "string") { + name = card; + } + else { + name = card.viewAs || card.name; + } + if (!name) return false; + if (this.hasJudge(name)) return false; + if (this.isOut()) return false; + var mod = game.checkMod(card, this, this, "unchanged", "targetEnabled", this); + if (mod != "unchanged") return mod; + return true; + } + addJudgeNext(card, unlimited) { + if (!card.expired) { + let target = this.next; + const name = card.viewAs || card.name; + const cards = (get.itemtype(card) == "card") ? [card] : card.cards; + if (get.itemtype(cards) != "cards") return; + let bool = false; + if (!unlimited && cards.some(card => { + const position = get.position(card, true); + return position != "j" && position != "o"; + })) { + game.log(card, "已被移出处理区,无法置入判定区"); + return; + } + for (let iwhile = 0; iwhile < 20; iwhile++) { + if (target.canAddJudge(card)) { + bool = true; break; + } + target = target.next; + } + if (bool) { + if (card.cards && card.cards.length) { + target.addJudge(name, card.cards[0]); + } + else if (card.name != name) { + target.addJudge(name, card); + } + else { + target.addJudge(card); + } + } + } + else { + card.expired = false; + } + } + judge() { + var next = game.createEvent("judge"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (get.itemtype(arguments[i]) == "card") { + next.card = arguments[i]; + } + else if (typeof arguments[i] == "string") { + next.skill = arguments[i]; + } + else if (typeof arguments[i] == "function") { + next.judge = arguments[i]; + } + else if (typeof arguments[i] == "boolean") { + next.clearArena = arguments[i]; + } + else if (get.objtype(arguments[i]) == "div") { + next.position = arguments[i]; + } + } + if (next.card && next.judge == undefined) { + next.judge = get.judge(next.card); + next.judge2 = get.judge2(next.card); + } + if (next.judge == undefined) next.judge = function () { return 0 }; + if (next.position == undefined) next.position = ui.discardPile; + if (next.card) next.cardname = next.card.viewAs || next.card.name; + + var str = ""; + if (next.card) str = get.translation(next.card.viewAs || next.card.name); + else if (next.skill) str = get.translation(next.skill); + else str = get.translation(_status.event.name); + next.judgestr = str; + next.setContent("judge"); + return next; + } + turnOver(bool) { + if (typeof bool == "boolean") { + if (bool) { + if (this.isTurnedOver()) return; + } + else { + if (!this.isTurnedOver()) return; + } + } + var next = game.createEvent("turnOver"); + next.player = this; + next.includeOut = true; + next.setContent("turnOver"); + return next; + } + out(skill) { + if (typeof skill == "number") { + this.outCount += skill; + } + else if (typeof skill == "string") { + if (!this.outSkills) { + this.outSkills = []; + } + this.outSkills.add(skill); + } + else { + this.outCount++; + } + if (!this.classList.contains("out")) { + this.classList.add("out"); + game.log(this, "离开游戏"); + } + if (!game.countPlayer()) { + game.over(); + } + } + in(skill) { + if (this.isOut()) { + if (typeof skill == "string") { + if (this.outSkills) { + this.outSkills.remove(skill); + if (!this.outSkills.length) { + delete this.outSkills; + } + } + } + else if (typeof skill == "number") { + this.outCount -= skill; + } + else { + if (skill === true) { + delete this.outSkills; + } + this.outCount = 0; + } + if (this.outCount <= 0 && !this.outSkills) { + this.outCount = 0; + this.classList.remove("out"); + game.log(this, "进入游戏"); + } + } + } + link(bool) { + if (typeof bool == "boolean") { + if (bool) { + if (this.isLinked()) return; + } + else { + if (!this.isLinked()) return; + } + } + var next = game.createEvent("link"); + next.player = this; + next.setContent("link"); + return next; + } + skip(name) { + this.skipList.add(name); + } + wait(callback) { + if (lib.node) { + if (typeof callback == "function") { + callback._noname_waiting = true; + lib.node.torespond[this.playerid] = callback; + } + else { + lib.node.torespond[this.playerid] = "_noname_waiting"; + } + clearTimeout(lib.node.torespondtimeout[this.playerid]); + if (this.ws && !this.ws.closed) { + var player = this; + var time = parseInt(lib.configOL.choose_timeout) * 1000; + if (_status.event._global_timer || _status.event.getParent().skillHidden) { + for (var i = 0; i < game.players.length; i++) { + game.players[i].showTimer(time); + } + player._hide_all_timer = true; + } + else if (!_status.event._global_waiting && _status.noclearcountdown !== "direct") { + player.showTimer(time); + } + lib.node.torespondtimeout[this.playerid] = setTimeout(function () { + player.unwait("ai"); + player.ws.ws.close(); + }, time + 5000); + } + } + } + unwait(result) { + if (this._hide_all_timer) { + delete this._hide_all_timer; + for (var i = 0; i < game.players.length; i++) { + game.players[i].hideTimer(); + } + } + else if (!get.event("_global_waiting") && (_status.noclearcountdown !== "direct" || result && result.bool) && !(result && result._noHidingTimer)) { + this.hideTimer(); + } + clearTimeout(lib.node.torespondtimeout[this.playerid]); + delete lib.node.torespondtimeout[this.playerid]; + if (!Object.prototype.hasOwnProperty.call(lib.node.torespond, this.playerid)) { + return; + } + var noresume = false; + var proceed = null; + if (typeof lib.node.torespond[this.playerid] == "function" && lib.node.torespond[this.playerid]._noname_waiting) { + proceed = lib.node.torespond[this.playerid](result, this); + if (proceed === false) { + noresume = true; + } + } + lib.node.torespond[this.playerid] = result; + for (var i in lib.node.torespond) { + if (lib.node.torespond[i] == "_noname_waiting") { + return; + } + else if (lib.node.torespond[i] && lib.node.torespond[i]._noname_waiting) { + return; + } + } + _status.event.result = result; + _status.event.resultOL = lib.node.torespond; + lib.node.torespond = {}; + if (typeof proceed == "function") proceed(); + else if (_status.paused && !noresume) game.resume(); + } + tempUnwait(result) { + if (!Object.prototype.hasOwnProperty.call(lib.node.torespond, this.playerid)) { + return; + } + var proceed; + if (typeof lib.node.torespond[this.playerid] == "function" && lib.node.torespond[this.playerid]._noname_waiting) { + proceed = lib.node.torespond[this.playerid](result, this); + } + if (typeof proceed == "function") proceed(); + } + logSkill(name, targets, nature, logv) { + if (get.itemtype(targets) == "player") targets = [targets]; + var nopop = false; + var popname = name; + if (Array.isArray(name)) { + popname = name[1]; + name = name[0]; + } + var checkShow = this.checkShow(name); + if (lib.translate[name]) { + this.trySkillAnimate(name, popname, checkShow); + if (Array.isArray(targets) && targets.length) { + var str; + if (targets[0] == this) { + str = "#b自己"; + if (targets.length > 1) { + str += "、"; + str += get.translation(targets.slice(1)); + } + } + else str = targets; + game.log(this, "对", str, "发动了", "【" + get.skillTranslation(name, this) + "】"); + } + else { + game.log(this, "发动了", "【" + get.skillTranslation(name, this) + "】"); + } + } + if (nature != false) { + if (nature === undefined) { + nature = "green"; + } + this.line(targets, nature); + } + var info = lib.skill[name]; + if (info && info.ai && info.ai.expose != undefined && + this.logAi && (!targets || targets.length != 1 || targets[0] != this)) { + this.logAi(lib.skill[name].ai.expose); + } + if (info && info.round) { + var roundname = name + "_roundcount"; + this.storage[roundname] = game.roundNumber; + this.syncStorage(roundname); + this.markSkill(roundname); + } + game.trySkillAudio(name, this, true); + if (game.chess) { + this.chessFocus(); + } + if (logv === true) { + game.logv(this, name, targets, null, true); + } + else if (info && info.logv !== false) { + game.logv(this, name, targets); + } + if (info) { + var player = this; + var players = player.getSkills(false, false, false); + var equips = player.getSkills("e"); + var global = lib.skill.global.slice(0); + var logInfo = { + skill: name, + targets: targets, + event: _status.event, + }; + if (info.sourceSkill) { + logInfo.sourceSkill = info.sourceSkill; + if (global.contains(info.sourceSkill)) { + logInfo.type = "global"; + } + else if (players.contains(info.sourceSkill)) { + logInfo.type = "player"; + } + else if (equips.contains(info.sourceSkill)) { + logInfo.type = "equip"; + } + } + else { + if (global.contains(name)) { + logInfo.sourceSkill = name; + logInfo.type = "global"; + } + else if (players.contains(name)) { + logInfo.sourceSkill = name; + logInfo.type = "player"; + } + else if (equips.contains(name)) { + logInfo.sourceSkill = name; + logInfo.type = "equip"; + } + else { + var bool = false; + for (var i of players) { + var expand = [i]; + game.expandSkills(expand); + if (expand.contains(name)) { + bool = true; + logInfo.sourceSkill = i; + logInfo.type = "player"; + break; + } + } + if (!bool) { + for (var i of players) { + var expand = [i]; + game.expandSkills(expand); + if (expand.contains(name)) { + logInfo.sourceSkill = i; + logInfo.type = "equip"; + break; + } + } + } + } + } + var next = game.createEvent("logSkill", false), evt = _status.event; + next.player = player; + next.forceDie = true; + next.includeOut = true; + evt.next.remove(next); + if (evt.logSkill) evt = evt.getParent(); + for (var i in logInfo) { + if (i == "event") next.log_event = logInfo[i]; + else next[i] = logInfo[i]; + } + evt.after.push(next); + next.setContent("emptyEvent"); + player.getHistory("useSkill").push(logInfo); + //尽可能别往这写插入结算 + //不能用来终止技能发动!!! + var next2 = game.createEvent("logSkillBegin", false); + next2.player = player; + next2.forceDie = true; + next2.includeOut = true; + for (var i in logInfo) { + if (i == "event") next2.log_event = logInfo[i]; + else next2[i] = logInfo[i]; + } + next2.setContent("emptyEvent"); + } + if (this._hookTrigger) { + for (var i = 0; i < this._hookTrigger.length; i++) { + var info = lib.skill[this._hookTrigger[i]].hookTrigger; + if (info && info.log) { + info.log(this, name, targets); + } + } + } + } + unprompt() { + if (this.node.prompt) { + this.node.prompt.delete(); + delete this.node.prompt; + } + } + prompt(str, nature) { + var node; + if (this.node.prompt) { + node = this.node.prompt; + node.innerHTML = ""; + node.className = "damage normal-font damageadded"; + } + else { + node = ui.create.div(".damage.normal-font", this); + this.node.prompt = node; + ui.refresh(node); + node.classList.add("damageadded"); + } + node.innerHTML = str; + node.dataset.nature = nature || "soil"; + } + prompt_old(name2, className) { + var node; + if (this.node.prompt) { + node = this.node.prompt; + node.innerHTML = ""; + node.className = "popup"; + } + else { + node = ui.create.div(".popup", this.parentNode); + this.node.prompt = node; + } + node.dataset.position = this.dataset.position; + if (this.dataset.position == 0 || parseInt(this.dataset.position) == parseInt(ui.arena.dataset.number) / 2 || + typeof name2 == "number" || this.classList.contains("minskin")) { + node.innerHTML = name2; + } + else { + for (var i = 0; i < name2.length; i++) { + node.innerHTML += name2[i] + "
"; + } + } + if (className) { + node.classList.add(className); + } + } + popup(name, className, nobroadcast) { + var name2 = get.translation(name); + if (!name2) return; + this.$damagepop(name2, className || "water", true, nobroadcast); + } + popup_old(name, className) { + var name2 = get.translation(name); + var node = ui.create.div(".popup", this.parentNode); + if (!name2) { + node.remove(); + return node; + } + game.addVideo("popup", this, [name, className]); + node.dataset.position = this.dataset.position; + if (this.dataset.position == 0 || parseInt(this.dataset.position) == parseInt(ui.arena.dataset.number) / 2 || + typeof name2 == "number" || this.classList.contains("minskin")) { + node.innerHTML = name2; + } + else { + for (var i = 0; i < name2.length; i++) { + node.innerHTML += name2[i] + "
"; + } + } + if (className) { + node.classList.add(className); + } + this.popups.push(node); + if (this.popups.length > 1) { + node.hide(); + } + else { + var that = this; + setTimeout(function () { that._popup(); }, 1000); + } + return node; + } + _popup() { + if (this.popups.length) { + this.popups.shift().delete(); + if (this.popups.length) { + this.popups[0].show(); + var that = this; + setTimeout(function () { that._popup(); }, 1000); + } + } + } + showTimer(time) { + if (!time && lib.configOL) { + time = parseInt(lib.configOL.choose_timeout) * 1000; + } + if (_status.connectMode && !game.online) { + game.broadcast(function (player, time) { + player.showTimer(time); + }, this, time); + } + if (this == game.me) { + return; + } + if (this.node.timer) { + this.node.timer.remove(); + } + var timer = ui.create.div(".timerbar", this); + this.node.timer = timer; + ui.create.div(this.node.timer); + var bar = ui.create.div(this.node.timer); + ui.refresh(bar); + bar.style.transitionDuration = (time / 1000) + "s"; + bar.style.transform = "scale(0,1)"; + } + hideTimer() { + if (_status.connectMode && !game.online && this.playerid) { + game.broadcast(function (player) { + player.hideTimer(); + }, this); + } + if (this.node.timer) { + this.node.timer.delete(); + delete this.node.timer; + } + } + markAuto(name, info) { + if (typeof info != "undefined") { + if (!Array.isArray(this.storage[name])) this.storage[name] = []; + if (Array.isArray(info)) { + this.storage[name].addArray(info); + } + else this.storage[name].add(info); + this.markSkill(name); + } + else { + var storage = this.storage[name]; + if (Array.isArray(storage)) { + this[storage.length > 0 ? "markSkill" : "unmarkSkill"](name); + } + else if (typeof storage == "number") { + this[storage > 0 ? "markSkill" : "unmarkSkill"](name); + } + } + } + unmarkAuto(name, info) { + var storage = this.storage[name] + if (Array.isArray(info) && Array.isArray(storage)) { + storage.removeArray(info.slice(0)); + this.markAuto(name); + } + } + getExpansions(tag) { + return this.getCards("x", (card) => card.hasGaintag(tag)); + } + countExpansions(tag) { + return this.getExpansions(tag).length; + } + hasExpansions(tag) { + return this.countExpansions(tag) > 0; + } + setStorage(name, value, mark) { + this.storage[name] = value; + if (mark) this.markAuto(name); + return value; + } + getStorage(name) { + return this.storage[name] || []; + } + hasStorage(name, value) { + if (!(name in this.storage)) return false; + if (typeof value == "undefined") return true; + const storage = this.storage[name]; + if (storage === value) return true; + return Array.isArray(storage) && storage.includes(value); + } + hasStorageAny(name, values) { + const storage = this.storage[name]; + if (!Array.isArray(values)) values = Array.from(arguments).slice(1); + if (!storage) return false; + if (!Array.isArray(storage)) return values.contains(storage); + return values.some(item => storage.contains(item)); + } + hasStorageAll(name, values) { + const storage = this.storage[name]; + if (!Array.isArray(values)) values = Array.from(arguments).slice(1); + if (!storage) return false; + if (!Array.isArray(storage)) return false; + return values.every(item => storage.contains(item)); + } + initStorage(name, value, mark) { + return this.hasStorage(name) ? this.getStorage(name) : this.setStorage(name, value, mark); + } + updateStorage(name, operation, mark) { + return this.setStorage(name, operation(this.getStorage(name)), mark); + } + updateStorageAsync(name, operation, mark) { + return Promise.resolve(this.getStorage(name)) + .then(value => operation(value)) + .then(value => this.setStorage(name, value, mark)); + } + removeStorage(name, mark) { + if (!this.hasStorage(name)) return false; + delete this.storage[name] + if (mark) { + this.unmarkSkill(name); + } + return true; + } + markSkill(name, info, card, nobroadcast) { + if (info === true) { + this.syncStorage(name); + info = null; + } + if (get.itemtype(card) == "card") { + game.addVideo("markSkill", this, [name, get.cardInfo(card)]); + } + else { + game.addVideo("markSkill", this, [name]); + } + const func = function (storage, player, name, info, card) { + player.storage[name] = storage; + if (!info) { + if (player.marks[name]) { + player.updateMarks(); + return; + } + if (lib.skill[name]) { + info = lib.skill[name].intro; + } + if (!info) { + return; + } + } + if (player.marks[name]) { + player.marks[name].info = info; + } + else { + if (card) { + player.marks[name] = player.mark(card, info, name); + } + else { + player.marks[name] = player.mark(name, info); + } + } + player.updateMarks(); + }; + func(this.storage[name], this, name, info, card); + if (!nobroadcast) game.broadcast(func, this.storage[name], this, name, info, card); + return this; + } + unmarkSkill(name, nobroadcast) { + game.addVideo("unmarkSkill", this, name); + if (!nobroadcast) game.broadcast(function (player, name) { + if (player.marks[name]) { + player.marks[name].delete(); + player.marks[name].style.transform += " scale(0.2)"; + delete player.marks[name]; + ui.updatem(player); + } + }, this, name); + if (this.marks[name]) { + this.marks[name].delete(); + this.marks[name].style.transform += " scale(0.2)"; + delete this.marks[name]; + ui.updatem(this); + var info = lib.skill[name]; + if (!game.online && info && info.intro && info.intro.onunmark) { + if (info.intro.onunmark == "throw") { + if (get.itemtype(this.storage[name]) == "cards") { + this.$throw(this.storage[name], 1000); + game.cardsDiscard(this.storage[name]); + game.log(this.storage[name], "进入了弃牌堆"); + this.storage[name].length = 0; + } + } + else if (typeof info.intro.onunmark == "function") { + info.intro.onunmark(this.storage[name], this); + } + else delete this.storage[name]; + } + } + return this; + } + markSkillCharacter(id, target, name, content, nobroadcast) { + if (typeof target == "object") { + target = target.name; + } + const func = function (player, target, name, content, id) { + if (player.marks[id]) { + player.marks[id].name = name + "_charactermark"; + player.marks[id]._name = target; + player.marks[id].info = { + name: name, + content: content, + id: id + }; + player.marks[id].setBackground(target, "character"); + game.addVideo("changeMarkCharacter", player, { + id: id, + name: name, + content: content, + target: target + }); + } + else { + player.marks[id] = player.markCharacter(target, { + name: name, + content: content, + id: id + }); + player.marks[id]._name = target; + game.addVideo("markCharacter", player, { + name: name, + content: content, + id: id, + target: target + }); + } + } + func(this, target, name, content, id); + if (!nobroadcast) game.broadcast(func, this, target, name, content, id); + return this; + } + markCharacter(name, info, learn, learn2) { + if (typeof name == "object") { + name = name.name; + } + var node; + if (name.startsWith("unknown")) { + node = ui.create.div(".card.mark.drawinghidden"); + ui.create.div(".background.skillmark", node).innerHTML = get.translation(name)[0]; + } + else { + if (!lib.character[name]) return; + node = ui.create.div(".card.mark.drawinghidden").setBackground(name, "character"); + } + this.node.marks.insertBefore(node, this.node.marks.childNodes[1]); + node.name = name + "_charactermark"; + if (!info) { + info = {}; + } + if (!info.name) { + info.name = get.translation(name); + } + if (!info.content) { + info.content = get.skillintro(name, learn, learn2) + } + node.info = info; + node.addEventListener(lib.config.touchscreen ? "touchend" : "click", ui.click.card); + if (!lib.config.touchscreen) { + if (lib.config.hover_all) { + lib.setHover(node, ui.click.hoverplayer); + } + if (lib.config.right_info) { + node.oncontextmenu = ui.click.rightplayer; + } + } + ui.updatem(this); + return node; + } + mark(name, info, skill) { + if (get.itemtype(name) == "cards") { + var marks = []; + for (var i = 0; i < name.length; i++) { + marks.push(this.mark(name[i], info)); + } + return marks; + } + else { + var node; + if (get.itemtype(name) == "card") { + node = name.copy("mark"); + node.classList.add("drawinghidden"); + this.node.marks.insertBefore(node, this.node.marks.childNodes[1]); + node.suit = name.suit; + node.number = name.number; + // if(name.name&&lib.card[name.name]&&lib.card[name.name].markimage){ + // node.node.image.style.left=lib.card[name.name].markimage; + // } + + if (name.classList.contains("fullborder")) { + node.classList.add("fakejudge"); + node.classList.add("fakemark"); + (node.querySelector(".background") || ui.create.div(".background", node)).innerHTML = lib.translate[name.name + "_bg"] || get.translation(name.name)[0]; + } + + name = name.name; + } + else { + node = ui.create.div(".card.mark.drawinghidden"); + this.node.marks.insertBefore(node, this.node.marks.childNodes[1]); + if (lib.skill[name] && lib.skill[name].markimage) { + node.setBackgroundImage(lib.skill[name].markimage); + node.style["box-shadow"] = "none"; + node.style["background-size"] = "contain"; + } + else if (lib.skill[name] && lib.skill[name].markimage2) { + let img = ui.create.div(".background.skillmark", node); + img.setBackgroundImage(lib.skill[name].markimage2); + img.style["background-size"] = "contain"; + } + else { + var str = lib.translate[name + "_bg"]; + if (!str || str[0] == "+" || str[0] == "-") { + str = get.translation(name)[0]; + } + ui.create.div(".background.skillmark", node).innerHTML = str; + } + } + node.name = name; + node.skill = skill || name; + if (typeof info == "object") { + node.info = info; + } + else if (typeof info == "string") { + node.markidentifer = info; + } + node.addEventListener(lib.config.touchscreen ? "touchend" : "click", ui.click.card); + if (!lib.config.touchscreen) { + if (lib.config.hover_all) { + lib.setHover(node, ui.click.hoverplayer); + } + if (lib.config.right_info) { + node.oncontextmenu = ui.click.rightplayer; + } + } + this.updateMarks(); + ui.updatem(this); + return node; + } + } + unmark(name, info) { + game.addVideo("unmarkname", this, name); + if (get.itemtype(name) == "card") { + this.unmark(name.name, info); + } + else if (get.itemtype(name) == "cards") { + for (var i = 0; i < name.length; i++) { + this.unmark(name[i].name, info); + } + } + else { + for (var i = 0; i < this.node.marks.childNodes.length; i++) { + if (this.node.marks.childNodes[i].name == name && + (!info || this.node.marks.childNodes[i].markidentifer == info)) { + this.node.marks.childNodes[i].delete(); + this.node.marks.childNodes[i].style.transform += " scale(0.2)"; + ui.updatem(this); + return; + } + } + } + } + addLink() { + if (get.is.linked2(this)) { + this.classList.add("linked2"); + } + else { + this.classList.add("linked"); + } + } + removeLink() { + if (get.is.linked2(this)) { + this.classList.remove("linked2"); + } + else { + this.classList.remove("linked"); + } + } + canUse(card, target, distance, includecard) { + if (typeof card == "string") card = { name: card, isCard: true }; + var info = get.info(card); + if (info.multicheck && !info.multicheck(card, this)) return false; + if (!lib.filter.cardEnabled(card, this)) return false; + if (includecard && !lib.filter.cardUsable(card, this)) return false; + if (distance !== false && !lib.filter.targetInRange(card, this, target)) return false; + return lib.filter[includecard ? "targetEnabledx" : "targetEnabled"](card, this, target); + } + hasUseTarget(card, distance, includecard) { + var player = this; + return game.hasPlayer(function (current) { + return player.canUse(card, current, distance, includecard); + }); + } + hasValueTarget() { + return this.getUseValue.apply(this, arguments) > 0; + } + getUseValue(card, distance, includecard) { + if (typeof (card) == "string") { + card = { name: card, isCard: true }; + } + var player = this; + var targets = game.filterPlayer(); + var value = []; + var min = 0; + var info = get.info(card); + if (!info || info.notarget) return 0; + var range; + var select = get.copy(info.selectTarget); + if (select == undefined) { + if (info.filterTarget == undefined) return true; + range = [1, 1]; + } + else if (typeof select == "number") range = [select, select]; + else if (get.itemtype(select) == "select") range = select; + else if (typeof select == "function") range = select(card, player); + if (info.singleCard) range = [1, 1]; + game.checkMod(card, player, range, "selectTarget", player); + if (!range) return 0; + + for (var i = 0; i < targets.length; i++) { + if (player.canUse(card, targets[i], distance, includecard)) { + var eff = get.effect(targets[i], card, player, player); + value.push(eff); + } + } + value.sort(function (a, b) { + return b - a; + }); + for (var i = 0; i < value.length; i++) { + if (i == range[1] || range[1] != -1 && value[i] <= 0) break; + min += value[i]; + } + return min; + } + addSubPlayer(cfg) { + var skill = "subplayer_" + cfg.name + "_" + get.id(); + game.log(this, "获得了随从", "#g" + get.translation(cfg.name)) + cfg.hs = cfg.hs || []; + cfg.es = cfg.es || []; + cfg.skills = cfg.skills || []; + cfg.hp = cfg.hp || 1; + cfg.maxHp = cfg.maxHp || 1; + cfg.sex = cfg.sex || "male"; + cfg.group = cfg.group || "qun"; + cfg.skill = cfg.skill || _status.event.name; + if (!cfg.source) { + if (this.hasSkill(_status.event.name) && this.name2 && lib.character[this.name2] && + lib.character[this.name2][3].contains(_status.event.name)) { + cfg.source = this.name2; + } + else { + cfg.source = this.name; + } + } + game.broadcastAll(function (player, skill, cfg) { + lib.skill[skill] = { + intro: { + content: cfg.intro || "" + }, + mark: "character", + subplayer: cfg.skill, + ai: { + subplayer: true + } + } + lib.character[skill] = [cfg.sex, cfg.group, cfg.maxHp, cfg.skills, []]; + if (Array.isArray(cfg.image)) { + cfg.image.forEach(image => lib.character[skill][4].push(image)); + } else if (typeof cfg.image == "string") { + lib.character[skill][4].push(cfg.image); + } else { + lib.character[skill][4].push("character:" + cfg.name); + } + lib.translate[skill] = cfg.caption || get.rawName(cfg.name); + player.storage[skill] = cfg; + }, this, skill, cfg); + game.addVideo("addSubPlayer", this, [skill, lib.skill[skill], lib.character[skill], lib.translate[skill], { name: cfg.name }]); + this.addSkill(skill); + return skill; + } + removeSubPlayer(name) { + if (this.hasSkill("subplayer") && this.name == name) { + this.exitSubPlayer(true); + } + else { + if (player.storage[name].onremove) { + player.storage[name].onremove(player); + } + this.removeSkill(name); + delete this.storage[name]; + game.log(player, "牺牲了随从", "#g" + name); + _status.event.trigger("removeSubPlayer"); + } + } + callSubPlayer() { + if (this.hasSkill("subplayer")) return; + var next = game.createEvent("callSubPlayer"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "string") { + next.directresult = arguments[i]; + } + } + next.setContent("callSubPlayer"); + return next; + } + toggleSubPlayer() { + if (!this.hasSkill("subplayer")) return; + var next = game.createEvent("toggleSubPlayer"); + next.player = this; + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "string") { + next.directresult = arguments[i]; + } + } + next.setContent("toggleSubPlayer"); + return next; + } + exitSubPlayer(remove) { + if (!this.hasSkill("subplayer")) return; + var next = game.createEvent("exitSubPlayer"); + next.player = this; + next.remove = remove; + next.setContent("exitSubPlayer"); + return next; + } + getSubPlayers(tag) { + var skills = this.getSkills(); + var list = []; + for (var i = 0; i < skills.length; i++) { + var name = skills[i]; + var info = lib.skill[name]; + if (tag && info.subplayer != tag) continue; + if (info.ai && info.ai.subplayer && this.storage[name] && this.storage[name].name) { + list.push(name); + } + } + return list; + } + addSkillTrigger(skills, hidden, triggeronly) { + if (typeof skills == "string") skills = [skills]; + game.expandSkills(skills); + for (const skill of skills) { + const info = lib.skill[skill]; + if (!info) { + console.error(new ReferenceError(`Cannot find ${skill} in lib.skill, failed to add ${skill}"s trigger to ${this.name}`)); + continue; + } + if (!triggeronly) { + if (info.global && (!hidden || info.globalSilent)) { + let global = info.global; + if (!Array.isArray(global)) global = [global]; + global.forEach(skill => game.addGlobalSkill(skill, this)); + } + if (this.initedSkills.includes(skill)) continue; + this.initedSkills.push(skill); + if (info.init && !_status.video) info.init(this, skill); + } + if (info.trigger && this.playerid) { + const setTrigger = (role, evt) => { + const name = this.playerid + "_" + role + "_" + evt; + if (!lib.hook[name]) lib.hook[name] = []; + lib.hook[name].add(skill); + lib.hookmap[evt] = true; + } + for (const role in info.trigger) { + let evts = info.trigger[role]; + if (!Array.isArray(evts)) evts = [evts]; + evts.forEach(evt => setTrigger(role, evt)); + } + } + if (info.hookTrigger) { + if (!this._hookTrigger) this._hookTrigger = []; + this._hookTrigger.add(skill); + } + if (_status.event && _status.event.addTrigger) _status.event.addTrigger(skill, this); + _status.event.clearStepCache(); + } + return this; + } + addSkillLog(skill) { + if (!skill) return this; + this.addSkill(skill); + if (!Array.isArray(skill)) skill = [skill]; + game.log(this, "获得了技能", ...skill.map(i => { + this.popup(i); + return "#g【" + get.translation(i) + "】"; + })); + } + removeSkillLog(skill, popup) { + if (!skill) return this; + this.removeSkill(skill); + if (!Array.isArray(skill)) skill = [skill]; + game.log(this, "失去了技能", ...skill.map(i => { + if (popup === true) this.popup(i); + return "#g【" + get.translation(i) + "】"; + })); + } + addInvisibleSkill(skill) { + if (Array.isArray(skill)) { + _status.event.clearStepCache(); + for (var i = 0; i < skill.length; i++) { + this.addInvisibleSkill(skill[i]); + } + } + else { + if (this.invisibleSkills.contains(skill)) return; + _status.event.clearStepCache(); + var info = lib.skill[skill]; + if (!info) return; + this.invisibleSkills.add(skill); + this.addSkillTrigger(skill); + if (this.awakenedSkills.contains(skill)) { + this.awakenSkill(skill); + return; + } + } + } + removeInvisibleSkill(skill) { + if (!skill) return; + if (Array.isArray(skill)) { + for (var i = 0; i < skill.length; i++) { + this.removeSkill(skill[i]); + } + } + else { + var info = lib.skill[skill]; + if (info && info.fixed && arguments[1] !== true) return skill; + game.broadcastAll(function (player, skill) { + player.invisibleSkills.remove(skill); + }, this, skill); + if (!player.hasSkill(skill, true)) player.removeSkill(skill); + } + return skill; + } + addSkill(skill, checkConflict, nobroadcast, addToSkills) { + if (Array.isArray(skill)) { + _status.event.clearStepCache(); + for (var i = 0; i < skill.length; i++) { + this.addSkill(skill[i]); + } + } + else { + if (this.skills.contains(skill)) return; + _status.event.clearStepCache(); + var info = lib.skill[skill]; + if (!info) return; + if (!addToSkills) { + this.skills.add(skill); + if (!nobroadcast) { + game.broadcast(function (player, skill) { + player.skills.add(skill); + }, this, skill); + } + } + this.addSkillTrigger(skill); + if (this.awakenedSkills.contains(skill)) { + this.awakenSkill(skill); + return; + } + if (info.init2 && !_status.video) { + info.init2(this, skill); + } + if (info.mark) { + if (info.mark == "card" && + get.itemtype(this.storage[skill]) == "card") { + this.markSkill(skill, null, this.storage[skill], nobroadcast); + } + else if (info.mark == "card" && + get.itemtype(this.storage[skill]) == "cards") { + this.markSkill(skill, null, this.storage[skill][0], nobroadcast); + } + else if (info.mark == "image") { + this.markSkill(skill, null, ui.create.card(null, "noclick").init([null, null, skill]), nobroadcast); + } + else if (info.mark == "character") { + var intro = info.intro.content; + if (typeof intro == "function") { + intro = intro(this.storage[skill], this); + } + else if (typeof intro == "string") { + intro = intro.replace(/#/g, this.storage[skill]); + intro = intro.replace(/&/g, get.cnNumber(this.storage[skill])); + intro = intro.replace(/\$/g, get.translation(this.storage[skill])); + } + var caption; + if (typeof info.intro.name == "function") { + caption = info.intro.name(this.storage[skill], this); + } + else if (typeof info.intro.name == "string") { + caption = info.name; + } + else { + caption = get.translation(skill); + } + this.markSkillCharacter(skill, this.storage[skill], caption, intro, nobroadcast); + } + else { + this.markSkill(skill, null, null, nobroadcast); + } + } + } + if (checkConflict) this.checkConflict(); + return skill; + } + addAdditionalSkill(skill, skills, keep) { + if (this.additionalSkills[skill]) { + if (keep) { + if (typeof this.additionalSkills[skill] == "string") { + this.additionalSkills[skill] = [this.additionalSkills[skill]]; + } + } + else { + this.removeAdditionalSkill(skill); + this.additionalSkills[skill] = []; + } + } + else { + this.additionalSkills[skill] = []; + } + if (typeof skills == "string") { + skills = [skills]; + } + for (var i = 0; i < skills.length; i++) { + this.addSkill(skills[i], null, true, true); + //this.skills.remove(skills[i]); + this.additionalSkills[skill].push(skills[i]); + } + this.checkConflict(); + _status.event.clearStepCache(); + return this; + } + removeAdditionalSkill(skill, target) { + const player = this; + if (this.additionalSkills[skill]) { + const additionalSkills = this.additionalSkills[skill]; + const hasAnotherSKill = function (skillkey, skill) { + return (player.skills.contains(skill) || player.tempSkills[skill] || Object.keys(player.additionalSkills).some(key => { + if (key === skillkey) return false; + if (Array.isArray(player.additionalSkills[key])) return player.additionalSkills[key].includes(skill); + return player.additionalSkills[key] == skill; + })) + } + if (Array.isArray(additionalSkills) && typeof target == "string") { + if (additionalSkills.contains(target)) { + additionalSkills.remove(target); + if (!hasAnotherSKill(skill, target)) this.removeSkill(target); + } + } + else { + delete this.additionalSkills[skill]; + if (typeof additionalSkills == "string") { + if (!hasAnotherSKill(skill, additionalSkills)) this.removeSkill(additionalSkills); + } + else if (Array.isArray(additionalSkills)) { + const skillsToRemove = additionalSkills.filter(target => !hasAnotherSKill(skill, target)) + this.removeSkill(skillsToRemove); + } + } + } + _status.event.clearStepCache(); + return this; + } + awakenSkill(skill, nounmark) { + if (!nounmark) this.unmarkSkill(skill); + this.disableSkill(skill + "_awake", skill); + this.awakenedSkills.add(skill); + if (this.storage[skill] === false) this.storage[skill] = true; + _status.event.clearStepCache(); + return this; + } + restoreSkill(skill, nomark) { + if (this.storage[skill] === true) this.storage[skill] = false; + this.awakenedSkills.remove(skill); + this.enableSkill(skill + "_awake", skill); + if (!nomark) this.markSkill(skill); + _status.event.clearStepCache(); + return this; + } + disableSkill(skill, skills) { + if (typeof skills == "string") { + if (!this.disabledSkills[skills]) { + this.disabledSkills[skills] = []; + var info = get.info(skills); + if (info.ondisable && info.onremove) { + if (typeof info.onremove == "function") { + info.onremove(this, skill); + } + else if (typeof info.onremove == "string") { + if (info.onremove == "storage") { + delete this.storage[skill]; + } + else { + var cards = this.storage[skill]; + if (get.itemtype(cards) == "card") { + cards = [cards]; + } + if (get.itemtype(cards) == "cards") { + if (this.onremove == "discard") { + this.$throw(cards); + } + if (this.onremove == "discard" || this.onremove == "lose") { + game.cardsDiscard(cards); + delete this.storage[skill]; + } + } + } + } + else if (Array.isArray(info.onremove)) { + for (var i = 0; i < info.onremove.length; i++) { + delete this.storage[info.onremove[i]]; + } + } + else if (info.onremove === true) { + delete this.storage[skill]; + } + } + } + this.disabledSkills[skills].add(skill); + var group = lib.skill[skills].group; + if (typeof group == "string" || Array.isArray(group)) { + this.disableSkill(skill, group); + } + } + else if (Array.isArray(skills)) { + for (var i = 0; i < skills.length; i++) { + this.disableSkill(skill, skills[i]); + } + } + _status.event.clearStepCache(); + return this; + } + enableSkill(skill) { + for (var i in this.disabledSkills) { + this.disabledSkills[i].remove(skill); + if (this.disabledSkills[i].length == 0) { + delete this.disabledSkills[i]; + } + } + _status.event.clearStepCache(); + return this; + } + checkMarks() { + var skills = this.getSkills(); + game.expandSkills(skills); + for (var i in this.marks) { + if (!skills.contains(i) && !this.marks[i].info.fixed) { + this.unmarkSkill(i); + } + } + return this; + } + addEquipTrigger(card) { + if (card) { + var info = get.info(card); + if (info.skills) { + for (var j = 0; j < info.skills.length; j++) { + this.addSkillTrigger(info.skills[j]); + } + } + } + else { + var es = this.getCards("e"); + for (var i = 0; i < es.length; i++) { + this.addEquipTrigger(es[i]); + } + } + _status.event.clearStepCache(); + return this; + } + removeEquipTrigger(card) { + if (card) { + var info = get.info(card); + var skills = this.getSkills(null, false); + if (info.skills) { + for (var j = 0; j < info.skills.length; j++) { + if (skills.contains(info.skills[j])) continue; + this.removeSkillTrigger(info.skills[j]); + } + } + if (info.clearLose && typeof info.onLose == "function") { + var next = game.createEvent("lose_" + card.name); + next.setContent(info.onLose); + next.player = this; + next.card = card; + } + } + else { + var es = this.getCards("e"); + for (var i = 0; i < es.length; i++) { + this.removeEquipTrigger(es[i]); + } + } + _status.event.clearStepCache(); + return this; + } + removeSkillTrigger(skills, triggeronly) { + if (typeof skills == "string") skills = [skills]; + game.expandSkills(skills); + for (const skill of skills) { + const info = lib.skill[skill]; + if (!info) { + console.error(new ReferenceError(`Cannot find ${skill} in lib.skill, failed to remove ${skill}"s trigger to ${this.name}`)); + continue; + } + if (!triggeronly) { + if (info.global) { + let global = info.global; + if (!Array.isArray(global)) global = [global]; + global.forEach(skill => game.removeGlobalSkill(skill, this)); + } + if (!this.initedSkills.includes(skill)) continue; + this.initedSkills.remove(skill); + // if(info.onremove&&!_status.video) info.onremove(this,skill); + } + if (info.trigger && this.playerid) { + const removeTrigger = (role, evt) => { + const name = this.playerid + "_" + role + "_" + evt; + if (!lib.hook[name]) return; + lib.hook[name].remove(skill); + if (lib.hook[name].length == 0) delete lib.hook[name]; + } + for (const role in info.trigger) { + let evts = info.trigger[role]; + if (!Array.isArray(evts)) evts = [evts]; + evts.forEach(evt => removeTrigger(role, evt)); + } + } + if (info.hookTrigger && this._hookTrigger) { + this._hookTrigger.remove(skill); + if (!this._hookTrigger.length) delete this._hookTrigger; + } + if (_status.event && _status.event.removeTrigger) _status.event.removeTrigger(skill, this); + _status.event.clearStepCache(); + } + return this; + } + removeSkill(skill) { + if (!skill) return; + _status.event.clearStepCache(); + if (Array.isArray(skill)) { + for (var i = 0; i < skill.length; i++) { + this.removeSkill(skill[i]); + } + } + else { + var info = lib.skill[skill]; + if (info && info.fixed && arguments[1] !== true) return skill; + this.unmarkSkill(skill); + game.broadcastAll(function (player, skill) { + player.skills.remove(skill); + player.hiddenSkills.remove(skill); + player.invisibleSkills.remove(skill); + delete player.tempSkills[skill]; + for (var i in player.additionalSkills) { + player.additionalSkills[i].remove(skill); + } + }, this, skill); + this.checkConflict(skill); + if (info) { + if (info.onremove) { + if (typeof info.onremove == "function") { + info.onremove(this, skill); + } + else if (typeof info.onremove == "string") { + if (info.onremove == "storage") { + delete this.storage[skill]; + } + else { + var cards = this.storage[skill]; + if (get.itemtype(cards) == "card") { + cards = [cards]; + } + if (get.itemtype(cards) == "cards") { + if (this.onremove == "discard") { + this.$throw(cards); + } + if (this.onremove == "discard" || this.onremove == "lose") { + game.cardsDiscard(cards); + delete this.storage[skill]; + } + } + } + } + else if (Array.isArray(info.onremove)) { + for (var i = 0; i < info.onremove.length; i++) { + delete this.storage[info.onremove[i]]; + } + } + else if (info.onremove === true) { + delete this.storage[skill]; + } + } + this.removeSkillTrigger(skill); + if (!info.keepSkill) { + this.removeAdditionalSkill(skill); + } + } + this.enableSkill(skill + "_awake"); + } + return skill; + } + addTempSkill(skill, expire, checkConflict) { + if (this.hasSkill(skill) && this.tempSkills[skill] == undefined) return; + this.addSkill(skill, checkConflict, true, true); + + if (!expire) expire = { global: ["phaseAfter", "phaseBeforeStart"] }; + else if (typeof expire == "string" || Array.isArray(expire)) expire = { global: expire }; + this.tempSkills[skill] = expire; + + if (get.objtype(expire) == "object") { + const roles = ["player", "source", "target", "global"]; + for (const i of roles) { + let triggers = expire[i]; + if (!Array.isArray(triggers)) triggers = [triggers]; + triggers.forEach(trigger => lib.hookmap[trigger] = true); + } + } + + return skill; + } + tempBanSkill(skill, expire, log) { + if (this.isTempBanned(skill)) return; + this.setStorage(`temp_ban_${skill}`, true); + + if (log !== false && this.hasSkill(skill)) game.log(this, "的技能", `#g【${get.translation(skill)}】`, "暂时失效了"); + + if (!expire) expire = { global: ["phaseAfter", "phaseBeforeStart"] }; + else if (typeof expire == "string" || Array.isArray(expire)) expire = { global: expire }; + this.when(expire).assign({ + firstDo: true, + }).vars({ + bannedSkill: skill, + }).then(() => { + delete player.storage[`temp_ban_${bannedSkill}`]; + }) + return skill; + } + isTempBanned(skill) { + return this.hasStorage(`temp_ban_${skill}`); + } + attitudeTo(target) { + if (typeof get.attitude == "function") return get.attitude(this, target); + return 0; + } + clearSkills(all) { + var list = []; + var exclude = []; + for (var i = 0; i < arguments.length; i++) { + exclude.push(arguments[i]); + } + for (i = 0; i < this.skills.length; i++) { + if (lib.skill[this.skills[i]].superCharlotte) continue; + if (!all && (lib.skill[this.skills[i]].temp || lib.skill[this.skills[i]].charlotte)) continue; + if (!exclude.contains(this.skills[i])) { + list.push(this.skills[i]); + } + } + if (all) { + for (var i in this.additionalSkills) { + this.removeAdditionalSkill(i); + } + } + this[all ? "removeSkill" : "removeSkillLog"](list); + this.checkConflict(); + this.checkMarks(); + return list; + } + checkConflict(skill) { + if (skill) { + if (this.forbiddenSkills[skill]) { + delete this.forbiddenSkills[skill]; + } + else { + for (var i in this.forbiddenSkills) { + if (this.forbiddenSkills[i].includes(skill)) { + this.forbiddenSkills[i].remove(skill) + if (!this.forbiddenSkills[i].length) { + delete this.forbiddenSkills[i]; + } + } + } + } + } + else { + this.forbiddenSkills = {}; + var forbid = []; + var getName = function (arr) { + var str = ""; + for (var i = 0; i < arr.length; i++) { + str += arr[i] + "+"; + } + return str.slice(0, str.length - 1); + } + var forbidlist = lib.config.forbid.concat(lib.config.customforbid); + var skills = this.getSkills(); + for (var i = 0; i < forbidlist.length; i++) { + if (lib.config.customforbid.contains(forbidlist[i]) || + !lib.config.forbidlist.contains(getName(forbidlist[i]))) { + for (var j = 0; j < forbidlist[i].length; j++) { + if (!skills.contains(forbidlist[i][j])) break; + } + if (j == forbidlist[i].length) { + forbid.push(forbidlist[i]); + } + } + } + for (var i = 0; i < forbid.length; i++) { + if (forbid[i][1] || this.name2) { + this.forbiddenSkills[forbid[i][0]] = this.forbiddenSkills[forbid[i][0]] || []; + if (forbid[i][1]) { + this.forbiddenSkills[forbid[i][0]].add(forbid[i][1]); + } + } + } + } + } + getHistory(key, filter, last) { + if (!key) return this.actionHistory[this.actionHistory.length - 1]; + if (!filter) return this.actionHistory[this.actionHistory.length - 1][key]; + else { + const history = this.getHistory(key); + if (last) { + const lastIndex = history.indexOf(last); + return history.filter((event, index) => { + if (index > lastIndex) return false; + return filter(event); + }) + } + return history.filter(filter); + } + } + checkHistory(key, filter, last) { + if (!key || !filter) return; + else { + const history = this.getHistory(key); + if (last) { + const lastIndex = history.indexOf(last); + history.forEach((event, index) => { + if (index > lastIndex) return false; + filter(event); + }) + } + else { + history.forEach(filter); + } + } + } + hasHistory(key, filter, last) { + const history = this.getHistory(key); + if (!filter || typeof filter != "function") filter = lib.filter.all; + if (last) { + const lastIndex = history.indexOf(last); + return history.some((event, index) => { + if (index > lastIndex) return false; + return filter(event); + }) + } + return history.some(filter); + } + getLastHistory(key, filter, last) { + let history = false; + for (let i = this.actionHistory.length - 1; i >= 0; i--) { + if (this.actionHistory[i].isMe) { + history = this.actionHistory[i]; break; + } + } + if (!history) return null; + if (!key) return history; + if (!filter) return history[key]; + else { + if (last) { + const lastIndex = history.indexOf(last); + return history.filter((event, index) => { + if (index > lastIndex) return false; + return filter(event); + }) + } + return history.filter(filter); + } + } + checkAllHistory(key, filter, last) { + if (!key || !filter) return; + this.actionHistory.forEach((value) => { + let history = value[key]; + if (last && history.includes(last)) { + const lastIndex = history.indexOf(last); + history.forEach((event, index) => { + if (index > lastIndex) return false; + return filter(event); + }); + } + else { + history.forEach(filter); + } + }); + } + getAllHistory(key, filter, last) { + const history = []; + this.actionHistory.forEach((value) => { + if (!key || !value[key]) { + history.push(value); + } + else { + history.push(...value[key]); + } + }) + if (filter) { + if (last) { + const lastIndex = history.indexOf(last); + return history.filter((event, index) => { + if (index > lastIndex) return false; + return filter(event); + }); + } + return history.filter(filter); + } + return history; + } + hasAllHistory(key, filter, last) { + return this.actionHistory.some((value) => { + let history = value[key]; + if (last && history.includes(last)) { + const lastIndex = history.indexOf(last); + if (history.some(function (event, index) { + if (index > lastIndex) return false; + return filter(event); + })) return true; + } + else { + if (history.some(filter)) return true; + } + return false; + }) + } + getLastUsed(num) { + if (typeof num != "number") num = 0; + var history = this.getHistory("useCard"); + if (history.length <= num) return null; + return history[history.length - num - 1]; + } + getStat(key) { + if (!key) return this.stat[this.stat.length - 1]; + return this.stat[this.stat.length - 1][key]; + } + getLastStat(key) { + var stat = false; + for (var i = this.stat.length - 1; i >= 0; i--) { + if (this.stat[i].isMe) { + stat = this.stat[i]; break; + } + } + if (!stat) return null + if (!key) return stat; + return stat[key]; + } + queue(time) { + if (time == false) { + clearTimeout(this.queueTimeout); + this.queueCount = 0; + return; + } + if (time == undefined) time = 500; + var player = this; + player.queueCount++; + this.queueTimeout = setTimeout(function () { + player.queueCount--; + if (player.queueCount == 0) { + player.style.transform = ""; + player.node.avatar.style.transform = ""; + player.node.avatar2.style.transform = ""; + if (game.chess) { + ui.placeChess(player, player.dataset.position); + } + if (player == game.me) ui.me.removeAttribute("style"); + } + }, time) + } + getCardUsable(card, pure) { + var player = this; + if (typeof card == "string") { + card = { name: card }; + } + card = get.autoViewAs(card); + var num = get.info(card).usable; + if (typeof num == "function") num = num(card, player); + num = game.checkMod(card, player, num, "cardUsable", player); + if (typeof num != "number") return Infinity; + if (!pure && _status.currentPhase == player) { + return num - player.countUsed(card); + } + return num; + } + getAttackRange(raw) { + const player = this; + let range = 0; + if (raw) { + range = game.checkMod(player, player, range, "globalFrom", player); + range = game.checkMod(player, player, range, "attackFrom", player); + const equips = player.getCards("e", function (card) { + return !ui.selected.cards || !ui.selected.cards.contains(card); + }); + equips.forEach(card => { + const info = get.info(card, false).distance; + if (info && info.globalFrom) { + range += info.globalFrom; + } + }) + return (player.getEquipRange() - range); + } + let base = game.checkMod(player, "unchanged", "attackRangeBase", player); + if (base != "unchanged") { + range = base; + } + else { + range = player.getEquipRange(); + } + range = game.checkMod(player, range, "attackRange", player); + return range; + } + getEquipRange(cards) { + const player = this; + if (!cards) cards = player.getCards("e", function (card) { + return !ui.selected.cards || !ui.selected.cards.contains(card); + }); + const range = cards.reduce((range, card) => { + let newRange = false; + const info = get.info(card, false); + if (info.distance) { + //如果存在attackRange 则通过attackRange动态获取攻击范围 + if (typeof info.distance.attackRange == "function") { + newRange = info.distance.attackRange(card, player); + } + //否则采用祖宗之法 + else if (typeof info.distance.attackFrom == "number") { + newRange = (1 - info.distance.attackFrom); + } + } + let isN1 = (typeof range == "number"); + let isN2 = (typeof newRange == "number"); + if (isN1 && isN2) return Math.max(range, newRange); + else return (isN1 ? range : newRange); + }, false); + return (typeof range == "number") ? range : 1; + } + getGlobalFrom() { + var player = this; + var range = 0; + range = game.checkMod(player, player, range, "globalFrom", player); + var equips = player.getCards("e", function (card) { + return !ui.selected.cards || !ui.selected.cards.contains(card); + }); + for (var i = 0; i < equips.length; i++) { + var info = get.info(equips[i]).distance; + if (!info) continue; + if (info.globalFrom) { + range += info.globalFrom; + } + } + return (-range); + } + getGlobalTo() { + var player = this; + var range = 0; + range = game.checkMod(player, player, range, "globalTo", player); + var equips = player.getCards("e", function (card) { + return !ui.selected.cards || !ui.selected.cards.contains(card); + }); + for (var i = 0; i < equips.length; i++) { + var info = get.info(equips[i]).distance; + if (!info) continue; + if (info.globalTo) { + range += info.globalTo; + } + } + return (range); + } + getHandcardLimit() { + var num = Math.max(this.hp, 0); + num = game.checkMod(this, num, "maxHandcardBase", this); + num = game.checkMod(this, num, "maxHandcard", this); + num = game.checkMod(this, num, "maxHandcardFinal", this); + return Math.max(0, num); + } + getEnemies(func) { + var player = this; + var targets; + var mode = get.mode(); + if (mode == "identity") { + if (_status.mode == "purple") { + switch (player.identity) { + case "bZhu": case "bZhong": case "rNei": targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return ["rZhu", "rZhong", "bNei"].contains(target.identity); + }); break; + case "rZhu": case "rZhong": case "bNei": targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return ["bZhu", "bZhong", "rNei"].contains(target.identity); + }); break; + case "rYe": case "bYe": targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return !["rYe", "bYe"].contains(target.identity); + }); break; + } + } + else { + var num = get.population("fan"); + switch (player.identity) { + case "zhu": case "zhong": case "mingzhong": targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + if (num >= 3) return target.identity == "fan"; + return target.identity == "nei" || target.identity == "fan"; + }); break; + case "nei": targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + if (num >= 3) return target.identity == "fan"; + if (game.players.length == 2) return target != player; + return target.identity == "zhong" || target.identity == "mingzhong" || target.identity == "fan"; + }); break; + case "fan": targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return target.identity != "fan"; + }); break; + case "commoner": targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + if (num >= 3) return target.identity != "fan"; + return target.identity == "fan"; + }); break; + } + } + } + else if (mode == "guozhan") { + if (player.identity == "ye") { + targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return true; + }); + } + else { + var group = lib.character[player.name1][1]; + targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return target.identity == "ye" || lib.character[target.name1][1] != group; + }); + } + } + else if (mode == "doudizhu") { + targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return target.identity != player.identity; + }); + } + else { + targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return target.side != player.side; + }); + } + targets.remove(player); + return targets; + } + getFriends(func) { + var player = this; + var targets; + var mode = get.mode(); + var self = false; + if (func === true) { + func = null; + self = true; + } + if (mode == "identity") { + if (_status.mode == "purple") { + switch (player.identity) { + case "rZhu": case "rZhong": case "bNei": targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return ["rZhu", "rZhong", "bNei"].contains(target.identity); + }); break; + case "bZhu": case "bZhong": case "rNei": targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return ["bZhu", "bZhong", "rNei"].contains(target.identity); + }); break; + case "rYe": case "bYe": targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return ["rYe", "bYe"].contains(target.identity); + }); break; + } + } + else { + switch (player.identity) { + case "zhu": case "zhong": case "mingzhong": targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return ["zhu", "zhong", "mingzhong"].contains(target.identity); + }); break; + case "nei": targets = []; break; + case "fan": targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return target.identity == "fan"; + }); break; + case "commoner": targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return true; + }); break; + } + } + } + else if (mode == "guozhan") { + if (player.identity == "ye") { + targets = []; + } + else { + var group = lib.character[player.name1][1]; + targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return target.identity != "ye" && lib.character[target.name1][1] == group; + }); + } + } + else if (mode == "doudizhu") { + targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return target.identity == player.identity; + }); + } + else { + targets = game.filterPlayer(function (target) { + if (func && !func(target)) return false; + return target.side == player.side; + }); + } + if (self) { + targets.add(player); + } + else { + targets.remove(player); + } + return targets; + } + isEnemyOf() { + return !this.isFriendOf.apply(this, arguments); + } + isFriendOf(player) { + if (get.mode() == "guozhan") { + if (this == player) return true; + if (this.getStorage("yexinjia_friend").includes(player) || player.getStorage("yexinjia_friend").includes(this)) return true; + if (this.identity == "unknown" || this.identity == "ye") return false; + if (player.identity == "unknown" || player.identity == "ye") return false; + return this.identity == player.identity; + } + if (get.mode() == "doudizhu") { + return this.identity == player.identity; + } + if (this.side != undefined && typeof player.side == "boolean") { + return this.side == player.side; + } + return this == player; + } + isFriendsOf(player) { + return player.getFriends(true).contains(this); + } + isEnemiesOf(player) { + return player.getEnemies().contains(this); + } + isAlive() { + return this.classList.contains("dead") == false; + } + isDead() { + return this.classList.contains("dead"); + } + isDying() { + return _status.dying.contains(this) && this.hp <= 0 && this.isAlive(); + } + isDamaged() { + return this.hp < this.maxHp && !this.storage.nohp; + } + isHealthy() { + return this.hp >= this.maxHp || this.storage.nohp; + } + isMaxHp(only, raw) { + return game.players.every(value => { + if (value.isOut() || value == this) return true; + return only ? value.getHp(raw) < this.getHp(raw) : value.getHp(raw) <= this.getHp(raw); + }); + } + isMinHp(only, raw) { + return game.players.every(value => { + if (value.isOut() || value == this) return true; + return only ? value.getHp(raw) > this.getHp(raw) : value.getHp(raw) >= this.getHp(raw); + }); + } + isMaxCard(only) { + const numberOfCards = this.countCards("he"); + return game.players.every(value => { + if (value.isOut() || value == this) return true; + return only ? value.countCards("he") < numberOfCards : value.countCards("he") <= numberOfCards; + }); + } + isMinCard(only) { + const numberOfCards = this.countCards("he"); + return game.players.every(value => { + if (value.isOut() || value == this) return true; + return only ? value.countCards("he") > numberOfCards : value.countCards("he") >= numberOfCards; + }); + } + isMaxHandcard(only) { + const numberOfHandCards = this.countCards("h"); + return game.players.every(value => { + if (value.isOut() || value == this) return true; + return only ? value.countCards("h") < numberOfHandCards : value.countCards("h") <= numberOfHandCards; + }); + } + isMinHandcard(only) { + const numberOfHandCards = this.countCards("h"); + return game.players.every(value => { + if (value.isOut() || value == this) return true; + return only ? value.countCards("h") > numberOfHandCards : value.countCards("h") >= numberOfHandCards; + }); + } + isMaxEquip(only) { + const numberOfEquipAreaCards = this.countCards("e"); + return game.players.every(value => { + if (value.isOut() || value == this) return true; + return only ? value.countCards("e") < numberOfEquipAreaCards : value.countCards("e") <= numberOfEquipAreaCards; + }); + } + isMinEquip(only) { + const numberOfEquipAreaCards = this.countCards("e"); + return game.players.every(value => { + if (value.isOut() || value == this) return true; + return only ? value.countCards("e") > numberOfEquipAreaCards : value.countCards("e") >= numberOfEquipAreaCards; + }); + } + isLinked() { + if (get.is.linked2(this)) { + return this.classList.contains("linked2"); + } + return this.classList.contains("linked"); + } + isTurnedOver() { + return this.classList.contains("turnedover"); + } + isOut() { + return this.classList.contains("out"); + } + isMin(distance) { + if (distance && lib.config.mode != "stone") return false; + if (this.forcemin) return true; + return this.classList.contains("minskin") && !game.chess; + } + isIn() { + return this.classList.contains("dead") == false && this.classList.contains("out") == false && !this.removed; + } + isUnseen(num) { + switch (num) { + case 0: return this.classList.contains("unseen"); + case 1: return this.classList.contains("unseen2"); + case 2: return this.classList.contains("unseen") || this.classList.contains("unseen2"); + default: return this.classList.contains("unseen") && (!this.name2 || this.classList.contains("unseen2")); + } + } + isUnderControl(self, me) { + me = (me || game.me); + var that = this._trueMe || this; + if (that.isMad() || game.notMe) return false; + if (this === me) { + if (self) return true; + return false; + } + if (that === me || this == me._trueMe) return true; + if (_status.connectMode) return false; + if (lib.config.mode == "versus") { + if (_status.mode == "three") return this.side == me.side; + if (_status.mode == "standard") return lib.storage.single_control && this.side == me.side; + if (_status.mode == "four") return get.config("four_phaseswap") && this.side == me.side; + if (_status.mode == "two") return get.config("two_phaseswap") && this.side == me.side; + return false; + } + else if (lib.config.mode == "boss") { + if (me.side) return false; + return this.side == me.side && get.config("single_control"); + } + else if (game.chess) { + if (lib.config.mode == "chess") { + if (_status.mode == "combat" && !get.config("single_control")) return false; + } + return this.side == me.side; + } + return false; + } + isOnline() { + if (this.ws && lib.node && !this.ws.closed && this.ws.inited && !this.isAuto) { + return true; + } + return false; + } + isOnline2() { + if (this.ws && lib.node && !this.ws.closed) { + return true; + } + return false; + } + isOffline() { + if (this.ws && lib.node && this.ws.closed) { + return true; + } + return false; + } + checkShow(skill, showonly) { + var sourceSkill = get.info(skill); + var noshow = false; + if (sourceSkill && sourceSkill.sourceSkill) { + skill = sourceSkill.sourceSkill; + } + if (lib.skill.global.contains(skill)) return false; + if (get.mode() != "guozhan" || game.expandSkills(this.getSkills()).contains(skill)) { + if (showonly) { + return false; + } + else { + noshow = true; + } + } + var unseen0 = this.isUnseen(0); + var name1 = this.name1 || this.name; + if (lib.character[name1] && (!showonly || unseen0)) { + var skills = game.expandSkills(lib.character[name1][3].slice(0)); + if (skills.contains(skill)) { + if (!noshow && this.isUnseen(0)) this.showCharacter(0); + return "main"; + } + } + var unseen1 = this.isUnseen(1); + var name2 = this.name2; + if (lib.character[name2] && (!showonly || unseen1)) { + var skills = game.expandSkills(lib.character[name2][3].slice(0)); + if (skills.contains(skill)) { + if (!noshow && this.isUnseen(1)) this.showCharacter(1); + return "vice"; + } + } + return false; + } + needsToDiscard(filter, add) { + let cards = this.getCards("h", card => !this.canIgnoreHandcard(card)), num = 0; + if (get.itemtype(add) === "cards") cards.addArray(add); + else if (get.itemtype(add) === "card") cards.push(add); + if (typeof filter === "number") num = filter; + else if (typeof filter === "function") cards = cards.filter(card => { + return filter(card); + }); + return Math.max(0, num + cards.length - this.getHandcardLimit()); + } + distanceTo(target, method) { + return get.distance(this, target, method); + } + distanceFrom(target, method) { + return get.distance(target, this, method); + } + hasSkill(skill, arg2, arg3, arg4) { + return game.expandSkills(this.getSkills(arg2, arg3, arg4)).contains(skill); + } + hasStockSkill(skill, arg1, arg2, arg3) { + return game.expandSkills(this.getStockSkills(arg1, arg2, arg3)).contains(skill); + } + isZhu2() { + var player = this, mode = get.mode(); + if (!this.isZhu) return false; + if (mode == "identity") { + if (_status.mode == "stratagem" && !this.identityShown) return false; + return true; + } + if (mode == "versus" && (_status.mode == "four" || _status.mode == "guandu")) return true; + return false; + } + hasZhuSkill(skill, player) { + if (!this.hasSkill(skill)) return false; + if (player) { + var mode = get.mode(); + if (mode == "identity" && _status.mode == "purple") { + if (this.identity.slice(0, 1) != player.identity.slice(0, 1)) return false; + } + if (mode == "versus" && (_status.mode == "four" || _status.mode == "guandu")) { + if (this.side != player.side) return false; + } + } + return true; + } + hasGlobalTag(tag, arg) { + var skills = lib.skill.global.slice(0); + game.expandSkills(skills); + for (var i = 0; i < skills.length; i++) { + var info = lib.skill[skills[i]]; + if (info && info.ai) { + if (info.ai.skillTagFilter && info.ai[tag] && + info.ai.skillTagFilter(this, tag, arg) === false) continue; + if (typeof info.ai[tag] == "string") { + if (info.ai[tag] == arg) return true; + } + else if (info.ai[tag]) { + return true; + } + } + } + return false; + } + hasSkillTag(tag, hidden, arg, globalskill) { + var skills = this.getSkills(hidden); + if (globalskill) { + skills.addArray(lib.skill.global); + } + game.expandSkills(skills); + for (var i = 0; i < skills.length; i++) { + var info = lib.skill[skills[i]]; + if (info && info.ai) { + if (info.ai.skillTagFilter && info.ai[tag] && + info.ai.skillTagFilter(this, tag, arg) === false) continue; + if (typeof info.ai[tag] == "string") { + if (info.ai[tag] == arg) return true; + } + else if (info.ai[tag]) { + return true; + } + } + } + return false; + } + hasJudge(name) { + if (name && typeof name == "object") { + name = name.viewAs || name.name; + } + var judges = this.getCards("j"); + for (var i = 0; i < judges.length; i++) { + if ((judges[i].viewAs || judges[i].name) == name) { + return true; + } + } + return false; + } + hasFriend() { + for (var i = 0; i < game.players.length; i++) { + if (game.players[i].isOut()) continue; + if (game.players[i] != this && get.attitude(game.players[i], this) > 0) { + return true; + } + } + return false; + } + hasUnknown(num) { + var mode = get.mode(); + if (typeof num != "number") { + num = 0; + } + if (mode == "identity" || mode == "guozhan") { + for (var i = 0; i < game.players.length; i++) { + if (game.players[i].ai.shown == 0 && game.players[i] != this) { + num--; + if (num <= 0) { + return true; + } + } + } + } + return false; + } + isUnknown(player) { + var mode = get.mode(); + if (mode == "identity" || mode == "guozhan") { + if (this.ai.shown == 0 && this != player) { + return true; + } + } + return false; + } + hasWuxie(info) { + if (this.countCards("hs", "wuxie")) return true; + var skills = this.getSkills("invisible").concat(lib.skill.global); + game.expandSkills(skills); + for (var i = 0; i < skills.length; i++) { + var ifo = get.info(skills[i]); + if (ifo.hiddenWuxie && info) { + if (typeof ifo.hiddenWuxie == "function" && ifo.hiddenWuxie(this, info)) { + return true; + } + } + else if (ifo.viewAs && typeof ifo.viewAs != "function" && ifo.viewAs.name == "wuxie") { + if (!ifo.viewAsFilter || ifo.viewAsFilter(this)) { + return true; + } + } + else { + var hiddenCard = ifo.hiddenCard; + if (typeof hiddenCard == "function" && hiddenCard(this, "wuxie")) { + return true; + } + } + } + return false; + } + hasSha(respond, noauto) { + if (this.countCards("hs", "sha")) return true; + if (this.countCards("hs", "hufu")) return true; + if (!noauto && this.countCards("hs", "yuchanqian")) return true; + if (this.hasSkillTag("respondSha", true, respond ? "respond" : "use", true)) return true; + return this.hasUsableCard("sha"); + } + hasShan() { + if (this.countCards("hs", "shan")) return true; + if (this.countCards("hs", "hufu")) return true; + if (this.hasSkillTag("respondShan", true, null, true)) return true; + return this.hasUsableCard("shan"); + } + mayHaveSha(viewer, type, ignore) { + if ((this.hp > 2 || !this.isZhu && this.hp > 1) && this.hasSkillTag("respondSha", true, type, true)) return true; + if (get.itemtype(viewer) !== "player") viewer = _status.event.player; + let cards, selected = get.copy(ui.selected.cards); + if (get.itemtype(ignore) === "cards") selected.addArray(ignore); + else if (get.itemtype(ignore) === "card") selected.add(ignore); + /*if(this===viewer||get.itemtype(viewer)==="player"&&viewer.hasSkillTag("viewHandcard",null,this,true)) cards=this.getCards("h"); + else cards=this.getShownCards();*/ + if (this === viewer || get.itemtype(viewer) == "player") { + cards = this.getKnownCards(viewer); + } else { + cards = this.getShownCards(); + } + if (cards.some(card => { + if (selected.includes(card)) return false; + let name = get.name(card, this); + if (name == "sha" || name == "hufu" || name == "yuchanqian") { + if (type === "use") return lib.filter.cardEnabled(card, this); + if (type === "respond") return lib.filter.cardRespondable(card, this); + return true; + } + return false; + })) return true; + let hs = this.getCards("hs").filter(i => !cards.includes(i) && !selected.includes(i)).length; + if (hs === 0) return false; + return Math.pow(hs + (this.isPhaseUsing() ? 6 : 4), 2) > 100 * _status.event.getRand("mayHaveSha"); + } + mayHaveShan(viewer, type, ignore) { + if ((this.hp > 2 || !this.isZhu && this.hp > 1) && this.hasSkillTag("respondShan", true, type, true)) return true; + if (get.itemtype(viewer) !== "player") viewer = _status.event.player; + let cards, selected = get.copy(ui.selected.cards); + if (get.itemtype(ignore) === "cards") selected.addArray(ignore); + else if (get.itemtype(ignore) === "card") selected.add(ignore); + /*if(this===viewer||get.itemtype(viewer)==="player"&&viewer.hasSkillTag("viewHandcard",null,this,true)) cards=this.getCards("h"); + else cards=this.getShownCards();*/ + if (this === viewer || get.itemtype(viewer) == "player") { + cards = this.getKnownCards(viewer); + } else { + cards = this.getShownCards(); + } + if (cards.some(card => { + if (selected.includes(card)) return false; + let name = get.name(card, this); + if (name === "shan" || name === "hufu") { + if (type === "use") return lib.filter.cardEnabled(card, this, "forceEnable"); + if (type === "respond") return lib.filter.cardRespondable(card, this); + return true; + } + return false; + })) return true; + let hs = this.getCards("hs").filter(i => !cards.includes(i) && !selected.includes(i)).length; + if (hs === 0) return false; + return Math.pow(hs + (this.isPhaseUsing() ? 3 : 5), 2) > 100 * _status.event.getRand("mayHaveShan"); + } + hasCard(name, position) { + if (typeof name == "function") { + var hs = this.getCards(position); + for (var i = 0; i < hs.length; i++) { + if (name(hs[i])) return true; + } + } + else { + if (this.countCards(position, name)) return true; + } + return false; + } + getEquip(name) { + var es = this.getCards("e"); + if (typeof name == "object" && get.info(name)) { + name = get.info(name).subtype; + if (name) { + name = parseInt(name[5]); + } + } + else if (typeof name == "string" && name.startsWith("equip") && name.length == 6) { + name = parseInt(name[5]); + } + if (!name) { + return null; + } + for (var i = 0; i < es.length; i++) { + if (typeof name === "number") { + if (get.info(es[i]).subtype === "equip" + name) { + return es[i]; + } + } + else { + if (es[i].name === name) return es[i]; + var source = get.info(es[i]).source; + if (Array.isArray(source) && source.contains(name)) { + return es[i]; + } + } + } + return null; + } + getJudge(name) { + var judges = this.node.judges.childNodes; + for (var i = 0; i < judges.length; i++) { + if (judges[i].classList.contains("removing")) continue; + if ((judges[i].viewAs || judges[i].name) == name) { + return judges[i]; + } + } + return null; + } + $drawAuto(cards, target) { + if (this.isUnderControl(true, target)) { + this.$draw(cards); + } + else { + this.$draw(cards.length); + } + } + $draw(num, init, config) { + if (init !== false && init !== "nobroadcast") { + game.broadcast(function (player, num, init, config) { + player.$draw(num, init, config) + }, this, num, init, config); + } + var cards, node; + if (get.itemtype(num) == "cards") { + cards = num; + num = cards.length; + } + else if (get.itemtype(num) == "card") { + cards = [num]; + num = 1; + } + if (init !== false) { + if (cards) { + game.addVideo("drawCard", this, get.cardsInfo(cards)); + } + else { + game.addVideo("draw", this, num); + } + } + if (cards) { + cards = cards.slice(0); + node = cards.shift().copy("thrown", "drawingcard"); + } + else { + node = ui.create.div(".card.thrown.drawingcard"); + } + node.fixed = true; + node.hide(); + + var dx, dy; + if (game.chess) { + var rect = this.getBoundingClientRect(); + + if (rect.left <= 80) { + dx = -10; + if (rect.top <= 80) { + dy = -10; + } + else if (rect.top + rect.height + 80 >= ui.chessContainer.offsetHeight) { + dy = 10; + } + else { + dy = 0; + } + } + else if (rect.left + rect.width + 80 >= ui.chessContainer.offsetWidth) { + dx = 10; + if (rect.top <= 80) { + dy = -10; + } + else if (rect.top + rect.height + 80 >= ui.chessContainer.offsetHeight) { + dy = 10; + } + else { + dy = 0; + } + } + else if (rect.top <= 80) { + dx = 0; + dy = -10; + } + else if (rect.top + rect.height + 80 >= ui.chessContainer.offsetHeight) { + dx = 0; + dy = 10; + } + else { + dx = rect.left + this.offsetWidth / 2 - ui.arena.offsetWidth / 2; + dy = rect.top + this.offsetHeight / 2 - ui.arena.offsetHeight / 2; + } + + var coeff = 240 / Math.sqrt(dx * dx + dy * dy); + dx *= coeff; + dy *= coeff; + + node.style.left = (this.getLeft() + this.offsetWidth / 2 - 52 - dx) + "px"; + node.style.top = (this.getTop() + this.offsetHeight / 2 - 52 - dy) + "px"; + this.parentNode.appendChild(node); + } + else { + this.parentNode.appendChild(node); + node.style.left = "calc(50% - 52px)"; + node.style.top = "calc(50% - 52px)"; + + dx = this.getLeft() + this.offsetWidth / 2 - 52 - node.offsetLeft; + dy = this.getTop() + this.offsetHeight / 2 - 52 - node.offsetTop; + + if (get.is.mobileMe(this)) { + dx += get.cardOffset(); + if (ui.arena.classList.contains("oblongcard")) { + dy -= 16; + } + } + } + node.style.transitionDuration = "0.8s"; + ui.refresh(node); + if (typeof num == "number" && init !== false) { + config = { + total: num, + current: 1 + } + } + if (config && config.total > 1) { + var total = config.total, current = config.current; + var dxtotal; + if (total <= 5) { + dxtotal = Math.min(80, (total - 1) * 20); + dx += -dxtotal + 2 * dxtotal * (current - 1) / (total - 1) + } + else { + var total2 = Math.floor(total / 2); + if (current <= total2) { + total = total2; + dy -= 20; + } + else { + current -= total2; + total -= total2; + dy += 20; + } + dxtotal = Math.min(80, (total - 1) * 20); + dx += -dxtotal + 2 * dxtotal * (current - 1) / (total - 1) + } + config.current++; + } + if (node.style.transform && node.style.transform != "none" && node.style.transform.indexOf("translate") == -1) { + node.style.transform += " translate(" + dx + "px," + dy + "px)"; + } + else { + node.style.transform = "translate(" + dx + "px," + dy + "px)"; + } + node.show(); + + node.listenTransition(function () { + node.style.transitionDuration = "0.5s"; + ui.refresh(node); + node.delete(); + }); + var that = this; + if (num && num > 1) { + if (config && config.total > 1) { + setTimeout(function () { + if (cards) { + that.$draw(cards, false, config) + } + else { + that.$draw(num - 1, false, config) + } + }, 50) + } + else { + setTimeout(function () { + if (cards) { + that.$draw(cards, false, config) + } + else { + that.$draw(num - 1, false, config) + } + }, 200); + } + } + } + $compareMultiple(card1, targets, cards) { + game.broadcast(function (player, card1, targets, cards) { + player.$compareMultiple(card1, targets, cards); + }, this, card1, targets, cards); + game.addVideo("compareMultiple", this, [get.cardInfo(card1), get.targetsInfo(targets), get.cardsInfo(cards)]); + var player = this; + var node1 = player.$throwxy2(card1, + "calc(50% - 52px)", "calc(50% + 10px)", "perspective(600px) rotateY(180deg)", true + ); + if (lib.config.cardback_style != "default") { + node1.style.transitionProperty = "none"; + ui.refresh(node1); + node1.classList.add("infohidden"); + ui.refresh(node1); + node1.style.transitionProperty = ""; + } + else { + node1.classList.add("infohidden"); + } + + node1.style.transform = "perspective(600px) rotateY(180deg) translateX(0)"; + var onEnd01 = function () { + //node1.removeEventListener("webkitTransitionEnd",onEnd01); + setTimeout(function () { + node1.style.transition = "all ease-in 0.3s"; + node1.style.transform = "perspective(600px) rotateY(270deg) translateX(52px)"; + var onEnd = function () { + node1.classList.remove("infohidden"); + node1.style.transition = "all 0s"; + ui.refresh(node1); + node1.style.transform = "perspective(600px) rotateY(-90deg) translateX(52px)"; + ui.refresh(node1); + node1.style.transition = ""; + ui.refresh(node1); + node1.style.transform = ""; + //node1.removeEventListener("webkitTransitionEnd",onEnd); + } + node1.listenTransition(onEnd); + }, 300); + }; + node1.listenTransition(onEnd01); + + setTimeout(function () { + var left0 = -targets.length * 52 - (targets.length - 1) * 8; + for (var i = 0; i < targets.length; i++) { + (function (target, card2, i) { + var left = left0 + i * 120; + var node2; + if (left < 0) { + node2 = target.$throwxy2(card2, + "calc(50% - " + (-left) + "px)", "calc(50% - 114px)", "perspective(600px) rotateY(180deg)", true + ); + } + else { + node2 = target.$throwxy2(card2, + "calc(50% + " + left + "px)", "calc(50% - 114px)", "perspective(600px) rotateY(180deg)", true + ); + } + if (lib.config.cardback_style != "default") { + node2.style.transitionProperty = "none"; + ui.refresh(node2); + node2.classList.add("infohidden"); + ui.refresh(node2); + node2.style.transitionProperty = ""; + } + else { + node2.classList.add("infohidden"); + } + node2.style.transform = "perspective(600px) rotateY(180deg) translateX(0)"; + var onEnd02 = function () { + //node2.removeEventListener("webkitTransitionEnd",onEnd02); + setTimeout(function () { + node2.style.transition = "all ease-in 0.3s"; + node2.style.transform = "perspective(600px) rotateY(270deg) translateX(52px)"; + var onEnd = function () { + node2.classList.remove("infohidden"); + node2.style.transition = "all 0s"; + ui.refresh(node2); + node2.style.transform = "perspective(600px) rotateY(-90deg) translateX(52px)"; + ui.refresh(node2); + node2.style.transition = ""; + ui.refresh(node2); + node2.style.transform = ""; + //node2.removeEventListener("webkitTransitionEnd",onEnd); + } + node2.listenTransition(onEnd); + }, 200); + }; + node2.listenTransition(onEnd02); + }(targets[i], cards[i], i)) + } + }, 200); + } + $compare(card1, target, card2) { + game.broadcast(function (player, target, card1, card2) { + player.$compare(card1, target, card2); + }, this, target, card1, card2); + game.addVideo("compare", this, [get.cardInfo(card1), target.dataset.position, get.cardInfo(card2)]); + var player = this; + var node1 = player.$throwxy2(card1, + "calc(50% - 114px)", "calc(50% - 52px)", "perspective(600px) rotateY(180deg)", true + ); + if (lib.config.cardback_style != "default") { + node1.style.transitionProperty = "none"; + ui.refresh(node1); + node1.classList.add("infohidden"); + ui.refresh(node1); + node1.style.transitionProperty = ""; + } + else { + node1.classList.add("infohidden"); + } + + node1.style.transform = "perspective(600px) rotateY(180deg) translateX(0)"; + var onEnd01 = function () { + //node1.removeEventListener("webkitTransitionEnd",onEnd01); + setTimeout(function () { + node1.style.transition = "all ease-in 0.3s"; + node1.style.transform = "perspective(600px) rotateY(270deg) translateX(52px)"; + var onEnd = function () { + node1.classList.remove("infohidden"); + node1.style.transition = "all 0s"; + ui.refresh(node1); + node1.style.transform = "perspective(600px) rotateY(-90deg) translateX(52px)"; + ui.refresh(node1); + node1.style.transition = ""; + ui.refresh(node1); + node1.style.transform = ""; + //node1.removeEventListener("webkitTransitionEnd",onEnd); + } + node1.listenTransition(onEnd); + }, 300); + }; + node1.listenTransition(onEnd01); + setTimeout(function () { + var node2 = target.$throwxy2(card2, + "calc(50% + 10px)", "calc(50% - 52px)", "perspective(600px) rotateY(180deg)", true + ); + if (lib.config.cardback_style != "default") { + node2.style.transitionProperty = "none"; + ui.refresh(node2); + node2.classList.add("infohidden"); + ui.refresh(node2); + node2.style.transitionProperty = ""; + } + else { + node2.classList.add("infohidden"); + } + node2.style.transform = "perspective(600px) rotateY(180deg) translateX(0)"; + var onEnd02 = function () { + //node2.removeEventListener("webkitTransitionEnd",onEnd02); + setTimeout(function () { + node2.style.transition = "all ease-in 0.3s"; + node2.style.transform = "perspective(600px) rotateY(270deg) translateX(52px)"; + var onEnd = function () { + node2.classList.remove("infohidden"); + node2.style.transition = "all 0s"; + ui.refresh(node2); + node2.style.transform = "perspective(600px) rotateY(-90deg) translateX(52px)"; + ui.refresh(node2); + node2.style.transition = ""; + ui.refresh(node2); + node2.style.transform = ""; + //node2.removeEventListener("webkitTransitionEnd",onEnd); + } + node2.listenTransition(onEnd); + }, 200); + }; + node2.listenTransition(onEnd02); + }, 200); + } + $throw(card, time, init, nosource) { + if (typeof card == "number") { + var tmp = card; + card = []; + while (tmp--) { + var cardx = ui.create.card(); + cardx.classList.add("infohidden"); + cardx.classList.add("infoflip"); + card.push(cardx); + } + } + if (init !== false) { + if (init !== "nobroadcast") { + game.broadcast(function (player, card, time, init, nosource) { + player.$throw(card, time, init, nosource); + }, this, card, time, init); + } + if (get.itemtype(card) != "cards") { + if (get.itemtype(card) == "card") { + card = [card]; + } + else { + return; + } + } + game.addVideo("throw", this, [get.cardsInfo(card), time, nosource]); + } + if (game.chess) { + this.chessFocus(); + } + if (get.itemtype(card) == "cards") { + var node; + for (var i = 0; i < card.length; i++) { + node = this.$throw(card[i], time, false, nosource); + } + return node; + } + else { + var node; + if (card == undefined || card.length == 0) return; + node = this.$throwordered(card.copy("thrown"), nosource); + if (time != undefined) { + node.fixed = true; + setTimeout(function () { node.delete() }, time); + } + lib.listenEnd(node); + return node; + } + } + $throwordered() { + return this.$throwordered2.apply(this, arguments); + // if(lib.config.low_performance){ + // return this.$throwordered2.apply(this,arguments); + // } + // else{ + // return this.$throwordered1.apply(this,arguments); + // } + } + $throwordered1(node, nosource) { + node.classList.add("thrown"); + node.hide(); + node.style.transitionProperty = "left,top,opacity,transform"; + for (var i = 0; i < ui.thrown.length; i++) { + if (ui.thrown[i].parentNode != ui.arena || + ui.thrown[i].classList.contains("removing")) { + ui.thrown.splice(i--, 1); + } + } + ui.thrown.push(node); + var uithrowns = ui.thrown.slice(0); + var tops; + if (game.chess) { + switch (Math.floor((ui.thrown.length - 1) / 4)) { + case 0: + tops = ["calc(50% - 82px)"]; + break; + case 1: + tops = ["calc(50% - 139px)", "calc(50% - 25px)"]; + break; + case 2: + tops = ["calc(50% - 196px)", "calc(50% - 82px)", "calc(50% + 32px)"]; + break; + default: + tops = ["calc(50% - 253px)", "calc(50% - 139px)", + "calc(50% - 25px)", "calc(50% + 89px)"]; + } + } + else { + switch (Math.floor((ui.thrown.length - 1) / 4)) { + case 0: + tops = ["calc(50% - 52px)"]; + break; + case 1: + tops = ["calc(50% - 109px)", "calc(50% + 5px)"]; + break; + case 2: + tops = ["calc(50% - 166px)", "calc(50% - 52px)", "calc(50% + 62px)"]; + break; + default: + tops = ["calc(50% - 223px)", "calc(50% - 109px)", + "calc(50% + 5px)", "calc(50% + 119px)"]; + } + } + while (uithrowns.length) { + var throwns = uithrowns.splice(0, Math.min(uithrowns.length, 4)); + switch (throwns.length) { + case 1: + throwns[0].style.left = "calc(50% - 52px)"; + break; + case 2: + throwns[0].style.left = "calc(50% - 109px)"; + throwns[1].style.left = "calc(50% + 5px)"; + break; + case 3: + throwns[0].style.left = "calc(50% - 166px)"; + throwns[1].style.left = "calc(50% - 52px)"; + throwns[2].style.left = "calc(50% + 62px)"; + break; + case 4: + throwns[0].style.left = "calc(50% - 223px)"; + throwns[1].style.left = "calc(50% - 109px)"; + throwns[2].style.left = "calc(50% + 5px)"; + throwns[3].style.left = "calc(50% + 119px)"; + break; + } + var top; + if (tops.length) { + top = tops.shift(); + } + else { + if (game.chess) { + top = "calc(50% - 82px)"; + } + else { + top = "calc(50% - 52px)"; + } + } + for (var i = 0; i < throwns.length; i++) { + throwns[i].style.top = top; + } + } + if (nosource) { + node.style.transform = "scale(0)"; + node.classList.add("center"); + } + else { + var parseCalc = function (str) { + var per = str.slice(str.indexOf("calc(") + 5, str.indexOf("%")); + var add = str.slice(str.indexOf("%") + 1, str.indexOf("px")).replace(/\s/g, ""); + return [parseInt(per), parseInt(add)]; + } + var nx = parseCalc(node.style.left); + var ny = parseCalc(node.style.top); + nx = nx[0] * ui.arena.offsetWidth / 100 + nx[1]; + ny = ny[0] * ui.arena.offsetHeight / 100 + ny[1]; + var dx, dy; + if (game.chess) { + var rect = this.getBoundingClientRect(); + dx = rect.left + this.offsetWidth / 2 - 52 - nx; + dy = rect.top + this.offsetHeight / 2 - 52 - ny; + } + else { + dx = this.getLeft() + this.offsetWidth / 2 - 52 - nx; + dy = this.getTop() + this.offsetHeight / 2 - 52 - ny; + if (get.is.mobileMe(this)) { + dx += get.cardOffset(); + if (ui.arena.classList.contains("oblongcard")) { + dy -= 16; + } + } + } + if (node.style.transform && node.style.transform != "none" && node.style.transform.indexOf("translate") == -1) { + node.style.transform += " translate(" + dx + "px," + dy + "px)"; + } + else { + node.style.transform = "translate(" + dx + "px," + dy + "px)"; + } + } + ui.arena.appendChild(node); + ui.refresh(node); + node.style.transform = ""; + node.show(); + lib.listenEnd(node); + return node; + } + $throwordered2(node, nosource) { + node.classList.add("thrown"); + node.classList.add("center"); + node.hide(); + node.style.transitionProperty = "left,top,opacity,transform"; + + if (nosource) { + // node.style.transform="scale(0)"; + } + else { + var nx = [50, -52]; + var ny = [50, -52]; + nx = nx[0] * ui.arena.offsetWidth / 100 + nx[1]; + ny = ny[0] * ui.arena.offsetHeight / 100 + ny[1]; + var dx, dy; + if (game.chess) { + var rect = this.getBoundingClientRect(); + dx = rect.left + this.offsetWidth / 2 - 52 - nx; + dy = rect.top + this.offsetHeight / 2 - 52 - ny; + } + else { + dx = this.getLeft() + this.offsetWidth / 2 - 52 - nx; + dy = this.getTop() + this.offsetHeight / 2 - 52 - ny; + if (get.is.mobileMe(this)) { + dx += get.cardOffset(); + if (ui.arena.classList.contains("oblongcard")) { + dy -= 16; + } + } + } + if (node.style.transform && node.style.transform != "none" && node.style.transform.indexOf("translate") == -1) { + node.style.transform += " translate(" + dx + "px," + dy + "px)"; + } + else { + node.style.transform = "translate(" + dx + "px," + dy + "px)"; + } + } + ui.arena.appendChild(node); + ui.refresh(node); + + for (var i = 0; i < ui.thrown.length; i++) { + if (ui.thrown[i].parentNode != ui.arena || + ui.thrown[i].classList.contains("removing")) { + ui.thrown.splice(i--, 1); + } + } + ui.thrown.push(node); + var uithrowns = ui.thrown.slice(0); + var tops; + switch (Math.floor((ui.thrown.length - 1) / 4)) { + case 0: + tops = [0]; + break; + case 1: + tops = [-57, 57]; + break; + case 2: + tops = [-114, 0, 114]; + break; + default: + tops = [-171, -57, 57, 171]; + } + while (uithrowns.length) { + var throwns = uithrowns.splice(0, Math.min(uithrowns.length, 4)); + switch (throwns.length) { + case 1: + throwns[0]._transthrown = "translate(0px,"; + break; + case 2: + throwns[0]._transthrown = "translate(-57px,"; + throwns[1]._transthrown = "translate(57px,"; + break; + case 3: + throwns[0]._transthrown = "translate(-114px,"; + throwns[1]._transthrown = "translate(0,"; + throwns[2]._transthrown = "translate(114px,"; + break; + case 4: + throwns[0]._transthrown = "translate(-171px,"; + throwns[1]._transthrown = "translate(-57px,"; + throwns[2]._transthrown = "translate(57px,"; + throwns[3]._transthrown = "translate(171px,"; + break; + } + var top; + if (tops.length) { + top = tops.shift(); + } + else { + top = 0; + } + if (game.chess) { + top -= 30; + } + for (var i = 0; i < throwns.length; i++) { + throwns[i].style.transform = throwns[i]._transthrown + top + "px)"; + delete throwns[i]._transthrown; + } + } + + node.show(); + lib.listenEnd(node); + return node; + } + $throwxy(card, left, top) { + var node = card.copy("thrown", "thrownhighlight"); + node.dataset.position = this.dataset.position; + node.hide(); + node.style.transitionProperty = "left,top,opacity"; + + ui.arena.appendChild(node); + ui.refresh(node); + node.show(); + node.style.left = left; + node.style.top = top; + lib.listenEnd(node); + return node; + } + $throwxy2(card, left, top, trans, flipx, flipy) { + if (game.chess) { + return this.$throwxy.apply(this, arguments); + } + var node = card.copy("thrown", "thrownhighlight"); + node.style.left = left; + node.style.top = top; + node.hide(); + // node.style.transitionProperty="left,top,opacity,transform"; + + var parseCalc = function (str) { + var per = str.slice(str.indexOf("calc(") + 5, str.indexOf("%")); + var add = str.slice(str.indexOf("%") + 1, str.indexOf("px")).replace(/\s/g, ""); + return [parseInt(per), parseInt(add)]; + } + var nx = parseCalc(node.style.left); + var ny = parseCalc(node.style.top); + nx = nx[0] * ui.arena.offsetWidth / 100 + nx[1]; + ny = ny[0] * ui.arena.offsetHeight / 100 + ny[1]; + var dx = this.getLeft() + this.offsetWidth / 2 - 52 - nx; + var dy = this.getTop() + this.offsetHeight / 2 - 52 - ny; + if (flipx) dx = -dx; + if (flipy) dy = -dy; + if (trans) { + node.style.transform = trans + " translate(" + dx + "px," + dy + "px)"; + } + else { + node.style.transform = "translate(" + dx + "px," + dy + "px)"; + } + + ui.arena.appendChild(node); + ui.refresh(node); + node.show(); + // node.style.transform=trans||""; + lib.listenEnd(node); + return node; + } + throwDice(num) { + if (typeof num != "number") { + num = get.rand(6) + 1; + _status.event.num = num; + } + if (!game.online) { + game.pause(); + } + game.broadcastAll(function (num) { + var diceContainer = ui.create.div(".fullsize.dice-container", ui.window); + ui.window.classList.add("dicepaused"); + var dice = ui.create.div(".dice"); + var side; + + side = ui.create.div(".side.front", dice); + ui.create.div(".dot.center", side); + ui.create.div(".side.front.inner", dice); + + side = ui.create.div(".side.top", dice); + ui.create.div(".dot.dtop.dleft", side); + ui.create.div(".dot.dbottom.dright", side); + ui.create.div(".side.top.inner", dice); + + side = ui.create.div(".side.right", dice); + ui.create.div(".dot.dtop.dleft", side); + ui.create.div(".dot.center", side); + ui.create.div(".dot.dbottom.dright", side); + ui.create.div(".side.right.inner", dice); + + side = ui.create.div(".side.left", dice); + ui.create.div(".dot.dtop.dleft", side); + ui.create.div(".dot.dtop.dright", side); + ui.create.div(".dot.dbottom.dleft", side); + ui.create.div(".dot.dbottom.dright", side); + ui.create.div(".side.left.inner", dice); + + side = ui.create.div(".side.bottom", dice); + ui.create.div(".dot.center", side); + ui.create.div(".dot.dtop.dleft", side); + ui.create.div(".dot.dtop.dright", side); + ui.create.div(".dot.dbottom.dleft", side); + ui.create.div(".dot.dbottom.dright", side); + ui.create.div(".side.bottom.inner", dice); + + side = ui.create.div(".side.back", dice); + ui.create.div(".dot.dtop.dleft", side); + ui.create.div(".dot.dtop.dright", side); + ui.create.div(".dot.dbottom.dleft", side); + ui.create.div(".dot.dbottom.dright", side); + ui.create.div(".dot.center dleft", side); + ui.create.div(".dot.center dright", side); + ui.create.div(".side.back.inner", dice); + + ui.create.div(".side.cover.x", dice); + ui.create.div(".side.cover.y", dice); + ui.create.div(".side.cover.z", dice); + + var map = { + 1: [75, 0, 45], + 2: [-15, 45, 0], + 3: [165, -45, 90], + 4: [345, -45, 90], + 5: [345, -45, 180], + 6: [255, 0, 135] + }; + dice.roll = function (deg) { + if (typeof deg == "number") { + dice.current[0] += deg; + deg = dice.current; + } + deg = deg.slice(0); + dice.current = deg; + this.style.transform = "rotateX(" + deg[0] + "deg) rotateY(" + deg[1] + "deg) rotateZ(" + deg[2] + "deg)"; + }; + dice.roll(map[num]); + diceContainer.appendChild(dice); + ui.refresh(dice); + dice.roll(1025); + + dice.addEventListener("webkitTransitionEnd", function () { + if (!dice.over) { + dice.style.transition = "transform 0.8s ease"; + dice.roll(-20); + dice.over = true; + } + else if (!dice.resumed) { + setTimeout(function () { + diceContainer.delete(); + ui.window.classList.remove("dicepaused"); + }, 300); + if (!game.online) { + setTimeout(game.resume, 800); + } + dice.resumed = true; + } + }); + }, num); + } + $giveAuto(card, player) { + if (Array.isArray(card) && card.length == 0) return; + var args = Array.from(arguments); + if (_status.connectMode || (!this.isUnderControl(true) && !player.isUnderControl(true))) { + if (Array.isArray(card)) { + card = card.length; + } + else { + card = 1; + } + args[0] = card; + } + return this.$give.apply(this, args); + } + $give(card, player, log, init) { + if (init !== false) { + game.broadcast(function (source, card, player, init) { + source.$give(card, player, false, init); + }, this, card, player, init); + if (typeof card == "number" && card >= 0) { + game.addVideo("give", this, [card, player.dataset.position]); + } + else { + if (get.itemtype(card) == "card") { + card = [card]; + } + if (get.itemtype(card) == "cards") { + game.addVideo("giveCard", this, [get.cardsInfo(card), player.dataset.position]); + } + } + } + if (get.itemtype(card) == "cards") { + if (log != false && !_status.video) { + game.log(player, "从", this, "获得了", card); + } + if (this.$givemod) { + this.$givemod(card, player); + } + else { + for (var i = 0; i < card.length; i++) { + this.$give(card[i], player, false, false); + } + } + } + else if (typeof card == "number" && card >= 0) { + if (log != false && !_status.video) { + game.log(player, "从", this, "获得了" + get.cnNumber(card) + "张牌"); + } + if (this.$givemod) { + this.$givemod(card, player); + } + else { + while (card--) this.$give("", player, false, false); + } + } + else { + if (log != false && !_status.video) { + if (get.itemtype(card) == "card" && log != false) { + game.log(player, "从", this, "获得了", card); + } + else { + game.log(player, "从", this, "获得了一张牌"); + } + } + if (this.$givemod) { + this.$givemod(card, player); + } + else { + var node; + if (get.itemtype(card) == "card") { + node = card.copy("card", "thrown", false); + } + else { + node = ui.create.div(".card.thrown"); + } + // node.dataset.position=this.dataset.position; + node.fixed = true; + this.$throwordered(node); + // lib.listenEnd(node); + // node.hide(); + // node.style.transitionProperty="left,top,opacity"; + // + // node.style.transform="rotate("+(Math.random()*16-8)+"deg)"; + // + // ui.arena.appendChild(node); + // ui.refresh(node); + // node.show(); + // node.style.left="calc(50% - 52px "+((Math.random()-0.5<0)?"+":"-")+" "+Math.random()*100+"px)"; + // node.style.top="calc(50% - 52px "+((Math.random()-0.5<0)?"+":"-")+" "+Math.random()*80+"px)"; + + node.listenTransition(function () { + var dx = player.getLeft() + player.offsetWidth / 2 - 52 - node.offsetLeft; + var dy = player.getTop() + player.offsetHeight / 2 - 52 - node.offsetTop; + if (node.style.transform && node.style.transform != "none" && node.style.transform.indexOf("translate") == -1) { + node.style.transform += " translate(" + dx + "px," + dy + "px)"; + } + else { + node.style.transform = "translate(" + dx + "px," + dy + "px)"; + } + + node.delete(); + }); + // setTimeout(function(){ + // // node.removeAttribute("style"); + // // node.dataset.position=player.dataset.position; + // var dx=player.offsetLeft+player.offsetWidth/2-52-node.offsetLeft; + // var dy=player.offsetTop+player.offsetHeight/2-52-node.offsetTop; + // if(node.style.transform&&node.style.transform!="none"&&node.style.transform.indexOf("translate")==-1){ + // node.style.transform+=" translate("+dx+"px,"+dy+"px)"; + // } + // else{ + // node.style.transform="translate("+dx+"px,"+dy+"px)"; + // } + // + // node.delete(); + // },700); + } + } + } + $equip(card) { + game.broadcast(function (player, card) { + player.$equip(card); + }, this, card); + card.fix(); + card.style.transform = ""; + card.classList.remove("drawinghidden"); + delete card._transform; + var player = this; + var equipNum = get.equipNum(card); + var equipped = false; + for (var i = 0; i < player.node.equips.childNodes.length; i++) { + if (get.equipNum(player.node.equips.childNodes[i]) >= equipNum) { + player.node.equips.insertBefore(card, player.node.equips.childNodes[i]); + equipped = true; + break; + } + } + if (!equipped) { + player.node.equips.appendChild(card); + if (_status.discarded) { + _status.discarded.remove(card); + } + } + var info = get.info(card); + if (info.skills) { + for (var i = 0; i < info.skills.length; i++) { + player.addSkillTrigger(info.skills[i]); + } + } + return player; + } + $gain(card, log, init) { + if (init !== false) { + game.broadcast(function (player, card, init) { + player.$gain(card, false, init); + }, this, card, init); + if (typeof card == "number" && card >= 0) { + game.addVideo("gain", this, card); + } + else { + if (get.itemtype(card) == "card") { + card = [card]; + } + if (get.itemtype(card) == "cards") { + game.addVideo("gainCard", this, get.cardsInfo(card)); + } + else { + game.addVideo("gain", this, 1); + } + } + } + if (get.itemtype(card) == "cards") { + if (log != false && !_status.video) { + game.log(this, "获得了", card); + } + if (this.$gainmod) { + this.$gainmod(card); + } + else { + for (var i = 0; i < card.length; i++) { + this.$gain(card[i], false, false); + } + } + } + else if (typeof card == "number" && card > 1) { + if (log != false && !_status.video) { + game.log(this, "获得了" + get.cnNumber(card) + "张牌"); + } + if (this.$gainmod) { + this.$gainmod(card); + } + else { + for (var i = 0; i < card; i++) { + this.$gain(1, false, false); + } + } + } + else { + if (get.itemtype(card) == "card" && log != false && !_status.video) { + game.log(this, "获得了", card); + } + if (this.$gainmod) { + this.$gainmod(card); + } + else { + var node; + if (get.itemtype(card) == "card") { + // node=this.$throwordered(card.copy(),true); + node = card.copy("thrown", false); + } + else { + // node=this.$throwordered(ui.create.div(".card.thrown"),true); + node = ui.create.div(".card.thrown"); + node.moveTo = lib.element.Card.prototype.moveTo; + node.moveDelete = lib.element.Card.prototype.moveDelete; + } + node.fixed = true; + node.style.left = "calc(50% - 52px " + ((Math.random() - 0.5 < 0) ? "+" : "-") + " " + Math.random() * 100 + "px)"; + node.style.top = "calc(50% - 52px " + ((Math.random() - 0.5 < 0) ? "+" : "-") + " " + Math.random() * 100 + "px)"; + node.style.transform = "scale(0)"; + node.hide(); + ui.arena.appendChild(node); + ui.refresh(node); + node.show(); + node.style.transform = ""; + + lib.listenEnd(node); + var player = this; + setTimeout(function () { + node.moveDelete(player); + }, 700); + } + } + } + $gain2(cards, log) { + if (log === true) { + game.log(this, "获得了", cards); + } + game.broadcast(function (player, cards) { + player.$gain2(cards); + }, this, cards); + if (get.itemtype(cards) == "card") cards = [cards]; + else if (get.itemtype(cards) != "cards") return; + var list = [], list2 = []; + for (var i = 0; i < cards.length; i++) { + if (cards[i].clone && + (cards[i].clone.parentNode == this.parentNode || + cards[i].clone.parentNode == ui.arena) && + parseFloat(getComputedStyle(cards[i].clone).opacity) > 0.3) { + cards[i].clone.moveDelete(this); + list2.push(cards[i].clone); + } + else { + list.push(cards[i]); + } + } + if (list2.length) { + game.addVideo("gain2", this, get.cardsInfo(list2)); + } + if (list.length) { + this.$draw(list, "nobroadcast"); + return true; + } + } + $skill(name, type, color, avatar) { + if (typeof type != "string") type = "legend"; + if (!avatar) { + this.playerfocus(1500); + game.delay(2); + } + else { + game.addVideo("playerfocus2"); + game.broadcastAll(function () { + ui.arena.classList.add("playerfocus"); + setTimeout(function () { + ui.arena.classList.remove("playerfocus"); + }, 1800) + }); + game.delay(3); + } + var that = this; + setTimeout(function () { + game.broadcastAll(function (that, type, name, color, avatar) { + if (lib.config.animation && !lib.config.low_performance) { + if (game.chess) { + that["$" + type + "2"](1200); + } + else { + that["$" + type](1200); + } + } + if (name) { + that.$fullscreenpop(name, color, avatar); + } + }, that, type, name, color, avatar); + }, avatar ? 0 : 300); + } + $fire() { + game.addVideo("flame", this, "fire"); + var left, top; + if (game.chess) { + var rect = this.getBoundingClientRect(); + left = rect.left; + top = rect.top; + } + else { + left = this.getLeft(); + top = this.getTop(); + } + game.animate.flame(left + this.offsetWidth / 2, + top + this.offsetHeight - 20, 700, "fire"); + } + $thunder() { + game.addVideo("flame", this, "thunder"); + var left, top; + if (game.chess) { + var rect = this.getBoundingClientRect(); + left = rect.left; + top = rect.top; + } + else { + left = this.getLeft(); + top = this.getTop(); + } + game.animate.flame(left + this.offsetWidth / 2, + top + this.offsetHeight - 30, 700, "thunder"); + } + $rare2() { + game.addVideo("flame", this, "rare2"); + var rect = this.getBoundingClientRect(); + var left = rect.left; + var top = rect.top + 15; + game.animate.flame(left + this.offsetWidth / 2, + top + this.offsetHeight - 30, 700, "rare"); + } + $epic2() { + game.addVideo("flame", this, "epic2"); + var rect = this.getBoundingClientRect(); + var left = rect.left; + var top = rect.top + 15; + game.animate.flame(left + this.offsetWidth / 2, + top + this.offsetHeight - 30, 700, "epic"); + } + $legend2() { + game.addVideo("flame", this, "legend2"); + var rect = this.getBoundingClientRect(); + var left = rect.left; + var top = rect.top + 15; + game.animate.flame(left + this.offsetWidth / 2, + top + this.offsetHeight - 30, 700, "legend"); + } + $rare(time) { + time = time || 700; + game.addVideo("flame", this, "rare"); + var left, top; + if (game.chess) { + left = this.getLeft() - ui.arena.offsetLeft; + top = this.getTop() - ui.arena.offsetTop; + } + else { + left = this.getLeft(); + top = this.getTop(); + } + if (this.classList.contains("minskin")) { + top += 15; + } + game.animate.flame(left + this.offsetWidth / 2, + top + this.offsetHeight - 30, time, "rare"); + } + $epic(time) { + time = time || 700; + game.addVideo("flame", this, "epic"); + var left, top; + if (game.chess) { + left = this.getLeft() - ui.arena.offsetLeft; + top = this.getTop() - ui.arena.offsetTop; + } + else { + left = this.getLeft(); + top = this.getTop(); + } + if (this.classList.contains("minskin")) { + top += 15; + } + game.animate.flame(left + this.offsetWidth / 2, + top + this.offsetHeight - 30, time, "epic"); + } + $legend(time) { + time = time || 700; + game.addVideo("flame", this, "legend"); + var left, top; + if (game.chess) { + left = this.getLeft() - ui.arena.offsetLeft; + top = this.getTop() - ui.arena.offsetTop; + } + else { + left = this.getLeft(); + top = this.getTop(); + } + if (this.classList.contains("minskin")) { + top += 15; + } + game.animate.flame(left + this.offsetWidth / 2, + top + this.offsetHeight - 30, time, "legend"); + } + $coin() { + game.broadcast(function (player) { + if (!lib.config.low_performance) { + player.$coin(); + } + }, this); + game.addVideo("flame", this, "coin"); + var left = this.getLeft() - ui.arena.offsetLeft; + var top = this.getTop() - ui.arena.offsetTop; + if (this.classList.contains("minskin")) { + top += 15; + } + top -= 25; + game.animate.flame(left + this.offsetWidth / 2, + top + this.offsetHeight - 30, 700, "coin"); + } + $dust() { + game.broadcast(function (player) { + if (!lib.config.low_performance) { + player.$dust(); + } + }, this); + game.addVideo("flame", this, "dust"); + var left = this.getLeft() - ui.arena.offsetLeft; + var top = this.getTop() - ui.arena.offsetTop; + if (this.classList.contains("minskin")) { + top += 15; + } + top -= 25; + game.animate.flame(left + this.offsetWidth / 2, + top + this.offsetHeight - 30, 700, "dust"); + } + $recover() { + game.addVideo("flame", this, "recover"); + var left, top; + if (game.chess) { + var rect = this.getBoundingClientRect(); + left = rect.left; + top = rect.top; + } + else { + left = this.getLeft(); + top = this.getTop(); + } + game.animate.flame(left + this.offsetWidth / 2, + top + this.offsetHeight - 30, 700, "recover"); + } + $fullscreenpop(str, nature, avatar, broadcast) { + if (broadcast !== false) game.broadcast(function (player, str, nature, avatar) { + player.$fullscreenpop(str, nature, avatar); + }, this, str, nature, avatar); + game.addVideo("fullscreenpop", this, [str, nature, avatar]); + var node = ui.create.div(".damage"); + if (avatar && this.node) { + if (avatar == "vice") { + if (lib.character[this.name2]) { + avatar = this.node.avatar2; + } + } + else { + if (lib.character[this.name]) { + avatar = this.node.avatar; + } + } + if (!get.is.div(avatar)) { + avatar = false; + } + } + else { + avatar = false; + } + if (avatar) { + node.classList.add("fullscreenavatar"); + ui.create.div("", ui.create.div(node)); + // ui.create.div("",str.split("").join("
"),ui.create.div(".text.textbg",node)); + ui.create.div("", "
" + str.split("").join("

") + "
", ui.create.div(".text", node)); + node.firstChild.firstChild.style.backgroundImage = avatar.style.backgroundImage; + node.dataset.nature = nature || "unknown"; + var num = 0; + var nodes = node.lastChild.firstChild.querySelectorAll("div"); + var interval = setInterval(function () { + if (num < nodes.length) { + nodes[num].classList.add("flashtext"); + num++; + } + else { + clearInterval(interval); + } + }, 100); + } + else { + avatar = false; + node.innerHTML = str; + node.dataset.nature = nature || "soil"; + } + if (avatar) { + var rect1 = ui.window.getBoundingClientRect(); + var rect2 = this.getBoundingClientRect(); + var dx = Math.round(2 * rect2.left + rect2.width - rect1.width); + var dy = Math.round(2 * rect2.top + rect2.height - rect1.height); + node.style.transform = "scale(0.5) translate(" + dx + "px," + dy + "px)"; + } + ui.window.appendChild(node); + ui.refresh(node); + if (avatar) { + node.style.transform = "scale(1)"; + node.style.opacity = 1; + } + else { + node.classList.add("damageadded"); + } + setTimeout(function () { + node.delete(); + node.style.transform = "scale(1.5)" + }, avatar ? 1600 : 1000); + } + $damagepop(num, nature, font, nobroadcast) { + if (typeof num == "number" || typeof num == "string") { + game.addVideo("damagepop", this, [num, nature, font]); + if (nobroadcast !== false) game.broadcast(function (player, num, nature, font) { + player.$damagepop(num, nature, font); + }, this, num, nature, font); + var node = ui.create.div(".damage"); + if (font) { + node.classList.add("normal-font"); + } + if (typeof num == "number" && num > 0) { + if (num == Infinity) num = "+∞" + else num = "+" + num; + } + else if (num == -Infinity) num = "-∞"; + node.innerHTML = num; + this.damagepopups.push(node); + node.dataset.nature = nature || "soil"; + if (this.damagepopups.length == 1) { + this.$damagepop(); + } + } + else if (this.damagepopups.length) { + var node = this.damagepopups[0]; + this.appendChild(node); + ui.refresh(node); + node.classList.add("damageadded"); + node.listenTransition(function () { + setTimeout(function () { + node.delete(); + }, 200); + }); + // setTimeout(function(){ + // node.delete(); + // },500); + var that = this; + setTimeout(function () { + that.damagepopups.shift(); + that.$damagepop(); + }, 500); + } + } + $damage(source) { + if (get.itemtype(source) == "player") { + game.addVideo("damage", this, source.dataset.position); + } + else { + game.addVideo("damage", this); + } + game.broadcast(function (player, source) { + player.$damage(source); + }, this, source); + if (source && source != this && lib.config.damage_shake) { + var left, top; + if (source.getTop() == this.getTop()) { + left = 20; + top = 0; + } + else { + var ratio = (source.getLeft() - this.getLeft()) / (source.getTop() - this.getTop()); + left = Math.abs(20 * ratio / Math.sqrt(1 + ratio * ratio)); + top = Math.abs(20 / Math.sqrt(1 + ratio * ratio)); + } + if (source.getLeft() - this.getLeft() > 0) left = -left; + if (source.getTop() - this.getTop() > 0) top = -top; + if (get.is.mobileMe(this)) { + if (this.classList.contains("linked")) { + this.node.avatar.style.transform = "translate(" + left + "px," + top + "px) rotate(-90deg)"; + this.node.avatar2.style.transform = "translate(" + left + "px," + top + "px) rotate(-90deg)"; + } + else { + this.node.avatar.style.transform = "translate(" + left + "px," + top + "px)"; + this.node.avatar2.style.transform = "translate(" + left + "px," + top + "px)"; + } + } + else if (this.classList.contains("linked") && get.is.newLayout()) { + this.style.transform = "translate(" + left + "px," + top + "px) rotate(-90deg)"; + } + else if (this._chesstransform) { + this.style.transform = "translate(" + (left + this._chesstransform[0]) + "px," + (top + this._chesstransform[1]) + "px)"; + } + else { + this.style.transform = "translate(" + left + "px," + top + "px)"; + } + } + else { + var zoom1 = 0.9, zoom2 = 0.95; + if (arguments[1] == "phase") { + zoom1 = 1.05; + zoom2 = 1.05; + } + if (get.is.mobileMe(this)) { + if (this.classList.contains("linked")) { + this.node.avatar.style.transform = "scale(" + zoom1 + ") rotate(-90deg)"; + this.node.avatar2.style.transform = "scale(" + zoom1 + ") rotate(-90deg)"; + } + else { + this.node.avatar.style.transform = "scale(" + zoom1 + ")"; + this.node.avatar2.style.transform = "scale(" + zoom1 + ")"; + } + } + else if (this.classList.contains("linked") && get.is.newLayout()) { + this.style.transform = "scale(" + zoom2 + ") rotate(-90deg)"; + } + else if (game.chess && this._chesstransform) { + this.style.transform = "translate(" + this._chesstransform[0] + "px," + this._chesstransform[1] + "px) scale(" + zoom2 + ")"; + } + else { + this.style.transform = "scale(" + zoom2 + ")"; + } + } + this.queue(); + } + $die() { + game.addVideo("die", this); + game.broadcast(function (player) { + player.$die(); + }, this); + if (lib.config.die_move != "off") { + this.$dieflip(lib.config.die_move); + } + if (this.$dieAfter) { + this.$dieAfter(); + } + } + $dieflip(type) { + var top0 = ui.window.offsetHeight / 2; + var left0 = ui.window.offsetWidth / 2; + var ratio = (left0 - this.getLeft()) / (top0 - this.getTop()); + var left = Math.abs(50 * ratio / Math.sqrt(1 + ratio * ratio)); + var top = Math.abs(50 / Math.sqrt(1 + ratio * ratio)); + if (left0 - this.getLeft() > 0) left = -left; + if (top0 - this.getTop() > 0) top = -top; + if (get.is.mobileMe(this)) { + left = -Math.random() * 5 - 10; + top = Math.random() * 5 + 10; + } + if (this._chesstransform) { + left += this._chesstransform[0]; + top += this._chesstransform[1]; + } + var transform = "translate(" + left + "px," + top + "px) " + + "rotate(" + (Math.random() * 20 - 10) + "deg) "; + if (type == "flip") { + if (game.layout == "long" || game.layout == "long2") { + transform += "rotateY(180deg)"; + } + else { + transform += ((Math.random() - 0.5 < 0) ? "rotateX(180deg)" : "rotateY(180deg)"); + } + } + if (get.is.mobileMe(this)) { + this.node.avatar.style.transform = transform; + this.node.avatar2.style.transform = transform; + this.style.transform = ""; + } + else { + this.node.avatar.style.transform = ""; + this.node.avatar2.style.transform = ""; + this.style.transform = transform; + } + this.queue(false); + } + $phaseJudge(card) { + game.addVideo("phaseJudge", this, get.cardInfo(card)); + var player = this; + var clone = player.$throw(card); + if (lib.config.low_performance && card && card.clone) { + var waitingForTransition = get.time(); + _status.waitingForTransition = waitingForTransition; + card.clone.listenTransition(function () { + if (_status.waitingForTransition == waitingForTransition && _status.paused) { + game.resume(); + } + }); + game.pause(); + } + else { + game.delay(); + } + } +} diff --git a/noname/library/element/v-card.js b/noname/library/element/v-card.js index db1e43907..e202c02b8 100644 --- a/noname/library/element/v-card.js +++ b/noname/library/element/v-card.js @@ -1 +1,107 @@ -export class VCard { } +export class VCard { + /** + * @param {any} [suitOrCard] + * @param {number | Card[]} [numberOrCards] + * @param {string} [name] + * @param {string} [nature] + */ + constructor(suitOrCard, numberOrCards, name, nature) { + if (Array.isArray(suitOrCard)) { + /** + * @type {string} + */ + this.suit = suitOrCard[0]; + /** + * @type {number} + */ + this.number = suitOrCard[1]; + /** + * @type {string} + */ + this.name = suitOrCard[2]; + /** + * @type {string} + */ + this.nature = suitOrCard[3]; + } + else if (get.itemtype(suitOrCard) == "card") { + this.name = get.name(suitOrCard); + this.suit = get.suit(suitOrCard); + this.color = get.color(suitOrCard); + this.number = get.number(suitOrCard); + this.nature = get.nature(suitOrCard); + this.isCard = true; + this.cardid = suitOrCard.cardid; + this.wunature = suitOrCard.wunature; + /** + * @type {Record} + */ + this.storage = get.copy(suitOrCard.storage); + if (Array.isArray(numberOrCards)) this.cards = numberOrCards.slice(); + else this.cards = [suitOrCard]; + const info = get.info(this, false); + if (info) { + const autoViewAs = info.autoViewAs; + if (typeof autoViewAs == "string") this.name = autoViewAs; + } + } + else if (suitOrCard && typeof suitOrCard != "string") { + Object.keys(suitOrCard).forEach(key => { + const propertyDescriptor = Object.getOwnPropertyDescriptor(suitOrCard, key), value = propertyDescriptor.value; + if (Array.isArray(value)) this[key] = value.slice(); + else Object.defineProperty(this, key, propertyDescriptor); + }); + if (Array.isArray(numberOrCards)) { + const noCards = !this.cards; + /** + * @type {Card[]} + */ + this.cards = numberOrCards.slice(); + if (noCards) { + if (!lib.suits.includes(this.suit)) this.suit = get.suit(this); + if (!Object.keys(lib.color).includes(this.color)) this.color = get.color(this); + if (typeof this.number != "number") this.number = get.number(this); + if (!this.nature) this.nature = get.nature(this); + } + } + const info = get.info(this, false); + if (info) { + const autoViewAs = info.autoViewAs; + if (typeof autoViewAs == "string") this.name = autoViewAs; + } + } + if (typeof suitOrCard == "string") this.suit = suitOrCard; + if (typeof numberOrCards == "number") this.number = numberOrCards; + if (typeof name == "string") this.name = name; + if (typeof nature == "string") this.nature = nature; + if (!this.storage) this.storage = {}; + if (!this.cards) this.cards = []; + } + sameSuitAs(card) { + return get.suit(this) == get.suit(card); + } + differentSuitFrom(card) { + return get.suit(this) != get.suit(card); + } + sameNumberAs(card) { + return get.number(this) == get.number(card); + } + differentNumberFrom(card) { + return get.number(this) != get.number(card); + } + sameNameAs(card) { + return get.name(this) == get.name(card); + } + differentNameFrom(card) { + return get.name(this) != get.name(card); + } + /** + * @param {Player} player + */ + hasNature(nature, player) { + const natures = get.natureList(this, player); + if (!nature) return natures.length > 0; + if (nature == "linked") return natures.some(n => lib.linked.includes(n)); + return get.is.sameNature(natures, nature); + } +} diff --git a/noname/library/element/ws.js b/noname/library/element/ws.js new file mode 100644 index 000000000..880e55d27 --- /dev/null +++ b/noname/library/element/ws.js @@ -0,0 +1,62 @@ +export class WS { + static onopen() { + if (_status.connectCallback) { + _status.connectCallback(true); + delete _status.connectCallback; + } + } + + static onmessage(messageevent) { + if (messageevent.data == "heartbeat") { + this.send("heartbeat"); + return; + } + var message; + try { + message = JSON.parse(messageevent.data); + if (!Array.isArray(message) || + typeof lib.message.client[message[0]] !== "function") { + throw ("err"); + } + for (var i = 1; i < message.length; i++) { + message[i] = get.parsedResult(message[i]); + } + } + catch (e) { + console.log(e); + console.log("invalid message: " + messageevent.data); + return; + } + lib.message.client[message.shift()].apply(null, message); + } + + static onerror(e) { + if (this._nocallback) return; + if (_status.connectCallback) { + _status.connectCallback(false); + delete _status.connectCallback; + } + else { + alert("连接失败"); + } + } + + static onclose() { + if (this._nocallback) return; + if (_status.connectCallback) { + _status.connectCallback(false); + delete _status.connectCallback; + } + if (game.online || game.onlineroom) { + if ((game.servermode || game.onlinehall) && _status.over) { + void 0; + } + else { + localStorage.setItem(lib.configprefix + "directstart", true); + game.reload(); + } + } + game.online = false; + game.ws = null; + } +} \ No newline at end of file diff --git a/noname/library/filter.js b/noname/library/filter.js new file mode 100644 index 000000000..5b9e7b781 --- /dev/null +++ b/noname/library/filter.js @@ -0,0 +1,453 @@ +export class Filter { + constructor() { + throw new TypeError(`${new.target.name} is not a constructor`); + } + static all() { + return true; + } + static none() { + return false; + } + + /** + * Check if the card does not count toward the player’s hand limit + * + * 检测此牌是否不计入此角色的手牌上限 + */ + static ignoredHandcard(card, player) { + return game.checkMod(card, player, false, "ignoredHandcard", player); + } + + /** + * Check if the card is giftable + * 检测此牌是否可赠予 + */ + static cardGiftable(card, player, target, strict) { + const mod = game.checkMod(card, player, target, "unchanged", "cardGiftable", player); + if (!mod || strict && (mod == "unchanged" && (get.position(card) != "h" || !get.cardtag(card, "gifts")) || player == target)) return false; + return get.type(card, false) != "equip" || target.canEquip(card, true); + } + + /** + * Check if the card is recastable + * 检查此牌是否可重铸 + */ + static cardRecastable(card, player, source, strict) { + if (typeof player == "undefined") player = get.owner(card); + const mod = game.checkMod(card, player, source, "unchanged", "cardRecastable", player); + if (!mod) return false; + if (strict && mod == "unchanged") { + if (get.position(card) != "h") return false; + const info = get.info(card), recastable = info.recastable || info.chongzhu; + return Boolean(typeof recastable == "function" ? recastable(_status.event, player) : recastable); + } + return true; + } + // 装备栏相关 + static canBeReplaced(card, player) { + var mod = game.checkMod(card, player, "unchanged", "canBeReplaced", player); + if (mod != "unchanged") return mod; + return true; + } + // 装备栏 END + static buttonIncluded(button) { + return !(_status.event.excludeButton && _status.event.excludeButton.contains(button)); + } + static filterButton(button) { + return true; + } + static cardSavable(card, player, target) { + if (get.itemtype(card) == "card") { + var mod2 = game.checkMod(card, player, "unchanged", "cardEnabled2", player); + if (mod2 != "unchanged") return mod2; + } + var mod = game.checkMod(card, player, target, "unchanged", "cardSavable", player); + if (mod != "unchanged") return mod; + var savable = get.info(card).savable; + if (typeof savable == "function") savable = savable(card, player, target); + return savable; + } + static filterTrigger(event, player, name, skill) { + if (player._hookTrigger && player._hookTrigger.some(i => { + const info = lib.skill[i].hookTrigger; + return info && info.block && info.block(event, player, name, skill); + })) return false; + const fullskills = game.expandSkills(player.getSkills(false).concat(lib.skill.global)); + const info = get.info(skill); + if (!info) return console.log("缺少info的技能:", skill); + if (!fullskills.includes(skill)) { + if (get.mode() != "guozhan") return false; + if (info && info.noHidden) return false; + } + if (!info.trigger) return false; + if (!info.forceDie && player.isDead()) return false; + if (!info.forceOut && player.isOut()) return false; + if (!Object.keys(info.trigger).some(i => { + if (i != "global" && player != event[i]) return false; + if (Array.isArray(info.trigger[i])) return info.trigger[i].includes(name); + return info.trigger[i] == name; + })) return false; + if (info.filter && !info.filter(event, player, name)) return false; + if (event._notrigger.includes(player) && !lib.skill.global.includes(skill)) return false; + if (typeof info.usable == "number" && player.hasSkill("counttrigger") && + player.storage.counttrigger && player.storage.counttrigger[skill] >= info.usable) { + return false; + } + if (info.round && (info.round - (game.roundNumber - player.storage[skill + "_roundcount"]) > 0)) return false; + if (player.storage[`temp_ban_${skill}`] === true) return false; + return true; + } + static characterDisabled(i, libCharacter) { + if (!lib.character[i] || lib.character[i][4] && lib.character[i][4].contains("forbidai")) return true; + if (lib.character[i][4] && lib.character[i][4].contains("unseen")) return true; + if (lib.config.forbidai.contains(i)) return true; + if (lib.characterFilter[i] && !lib.characterFilter[i](get.mode())) return true; + if (_status.connectMode) { + if (lib.configOL.banned.contains(i) || lib.connectBanned.contains(i)) return true; + var double_character = false; + if (lib.configOL.mode == "guozhan") { + double_character = true; + } + else if (lib.configOL.double_character && (lib.configOL.mode == "identity" || lib.configOL.mode == "stone")) { + double_character = true; + } + else if (lib.configOL.double_character_jiange && (lib.configOL.mode == "versus" && _status.mode == "jiange")) { + double_character = true; + } + if (double_character && lib.config.forbiddouble.contains(i)) { + return true; + } + } + else { + if (lib.config.banned.contains(i)) return true; + var double_character = false; + if (get.mode() == "guozhan") { + double_character = true; + } + else if (get.config("double_character") && (lib.config.mode == "identity" || lib.config.mode == "stone")) { + double_character = true; + } + else if (get.config("double_character_jiange") && (lib.config.mode == "versus" && _status.mode == "jiange")) { + double_character = true; + } + if (double_character && lib.config.forbiddouble.contains(i)) { + return true; + } + } + } + static characterDisabled2(i) { + var info = lib.character[i]; + if (!info) return true; + if (info[4]) { + if (info[4].contains("boss")) return true; + if (info[4].contains("hiddenboss")) return true; + if (info[4].contains("minskin")) return true; + if (info[4].contains("unseen")) return true; + if (info[4].contains("forbidai") && (!_status.event.isMine || !_status.event.isMine())) return true; + if (lib.characterFilter[i] && !lib.characterFilter[i](get.mode())) return true; + } + return false; + } + static skillDisabled(skill) { + if (!lib.translate[skill] || !lib.translate[skill + "_info"]) return true; + var info = lib.skill[skill]; + if (info && !info.unique && !info.temp && !info.sub && !info.fixed && !info.vanish) { + return false; + } + return true; + } + static cardEnabled(card, player, event) { + if (player == undefined) player = _status.event.player; + if (!player) return false; + if (get.itemtype(card) == "card") { + var mod2 = game.checkMod(card, player, event, "unchanged", "cardEnabled2", player); + if (mod2 != "unchanged") return mod2; + } + card = get.autoViewAs(card); + if (event === "forceEnable") { + var mod = game.checkMod(card, player, event, "unchanged", "cardEnabled", player); + if (mod != "unchanged") return mod; + return true; + } + else { + var filter = get.info(card).enable; + if (!filter) return; + var mod = game.checkMod(card, player, event, "unchanged", "cardEnabled", player); + if (mod != "unchanged") return mod; + if (typeof filter == "boolean") return filter; + if (typeof filter == "function") return filter(card, player, event); + } + } + static cardRespondable(card, player, event) { + event = event || _status.event; + if (event.name != "chooseToRespond") return true; + var source = event.getParent().player; + if (source && source != player) { + if (source.hasSkillTag("norespond", false, [card, player, event], true)) { + return false; + } + } + if (player == undefined) player = _status.event.player; + if (get.itemtype(card) == "card") { + var mod2 = game.checkMod(card, player, event, "unchanged", "cardEnabled2", player); + if (mod2 != "unchanged") return mod2; + } + var mod = game.checkMod(card, player, "unchanged", "cardRespondable", player); + if (mod != "unchanged") return mod; + return true; + } + static cardUsable2(card, player, event) { + card = get.autoViewAs(card); + var info = get.info(card); + if (info.updateUsable == "phaseUse") { + event = event || _status.event; + if (event.type == "chooseToUse_button") event = event.getParent(); + if (player != _status.event.player) return true; + if (event.getParent().name != "phaseUse") return true; + if (event.getParent().player != player) return true; + } + var num = info.usable; + if (typeof num == "function") num = num(card, player); + num = game.checkMod(card, player, num, "cardUsable", player); + if (typeof num != "number") return true; + else return (player.countUsed(card) < num); + } + static cardUsable(card, player, event) { + card = get.autoViewAs(card); + var info = get.info(card); + event = event || _status.event; + if (event.type == "chooseToUse_button") event = event.getParent(); + if (player != _status.event.player) return true; + if (info.updateUsable == "phaseUse") { + if (event.getParent().name != "phaseUse") return true; + if (event.getParent().player != player) return true; + } + event.addCount_extra = true; + var num = info.usable; + if (typeof num == "function") num = num(card, player); + num = game.checkMod(card, player, num, "cardUsable", player); + if (typeof num != "number") { + return (typeof num == "boolean") ? num : true; + } + if (player.countUsed(card) < num) return true; + if (game.hasPlayer(function (current) { + return game.checkMod(card, player, current, false, "cardUsableTarget", player); + })) { + return true; + } + return false; + } + static cardDiscardable(card, player, event) { + event = event || _status.event; + if (typeof event != "string") event = event.getParent().name; + var mod = game.checkMod(card, player, event, "unchanged", "cardDiscardable", player); + if (mod != "unchanged") return mod; + return true; + } + static canBeDiscarded(card, player, target, event) { + event = event || _status.event; + if (typeof event != "string") event = event.getParent().name; + var mod = game.checkMod(card, player, target, event, "unchanged", "canBeDiscarded", target); + if (mod != "unchanged") return mod; + return true; + } + static canBeGained(card, player, target, event) { + event = event || _status.event; + if (typeof event != "string") event = event.getParent().name; + var mod = game.checkMod(card, player, target, event, "unchanged", "canBeGained", target); + if (mod != "unchanged") return mod; + return true; + } + static cardAiIncluded(card) { + if (_status.event.isMine()) return true; + return (_status.event._aiexclude.contains(card) == false); + } + static filterCard(card, player, event) { + var info = get.info(card); + //if(info.toself&&!lib.filter.targetEnabled(card,player,player)) return false; + if (player == undefined) player = _status.event.player; + if (!lib.filter.cardEnabled(card, player, event) || !lib.filter.cardUsable(card, player, event)) return false; + if (info.notarget) return true; + var range; + var select = get.copy(info.selectTarget); + if (select == undefined) { + if (info.filterTarget == undefined) return true; + range = [1, 1]; + } + else if (typeof select == "number") range = [select, select]; + else if (get.itemtype(select) == "select") range = select; + else if (typeof select == "function") range = select(card, player); + game.checkMod(card, player, range, "selectTarget", player); + if (!range || range[1] != -1) return true; + var filterTarget = (event && event.filterTarget) ? event.filterTarget : lib.filter.filterTarget; + return game.hasPlayer(function (current) { + return filterTarget(card, player, current); + }); + } + static targetEnabledx(card, player, target) { + if (!card) return false; + if (!target || !target.isIn()) return false; + var event = _status.event; + if (event._backup && event._backup.filterCard == lib.filter.filterCard && (!lib.filter.cardEnabled(card, player, event) || !lib.filter.cardUsable(card, player, event))) return false; + if (event.addCount_extra) { + if (!lib.filter.cardUsable2(card, player) && !game.checkMod(card, player, target, false, "cardUsableTarget", player)) return false; + } + var info = get.info(card); + if (info.singleCard && info.filterAddedTarget && ui.selected.targets.length) return Boolean(info.filterAddedTarget(card, player, target, ui.selected.targets[ui.selected.targets.length - 1])); + return lib.filter.targetEnabled.apply(this, arguments); + } + static targetEnabled(card, player, target) { + if (!card) return false; + if (!target || !target.isIn()) return false; + var info = get.info(card); + var filter = info.filterTarget; + if (!info.singleCard || ui.selected.targets.length == 0) { + var mod = game.checkMod(card, player, target, "unchanged", "playerEnabled", player); + if (mod != "unchanged") return mod; + var mod = game.checkMod(card, player, target, "unchanged", "targetEnabled", target); + if (mod != "unchanged") return mod; + } + if (typeof filter == "boolean") return filter; + if (typeof filter == "function") return Boolean(filter(card, player, target)); + } + static targetEnabled2(card, player, target) { + if (!card) return false; + if (!target || !target.isIn()) return false; + if (lib.filter.targetEnabled(card, player, target)) return true; + + if (game.checkMod(card, player, target, "unchanged", "playerEnabled", player) == false) return false; + if (game.checkMod(card, player, target, "unchanged", "targetEnabled", target) == false) return false; + + var filter = get.info(card).modTarget; + if (typeof filter == "boolean") return filter; + if (typeof filter == "function") return Boolean(filter(card, player, target)); + return false; + } + static targetEnabled3(card, player, target) { + if (!card) return false; + if (!target || !target.isIn()) return false; + var info = get.info(card); + + if (info.filterTarget == true) return true; + if (typeof info.filterTarget == "function" && info.filterTarget(card, player, target)) return true; + + if (info.modTarget == true) return true; + if (typeof info.modTarget == "function" && info.modTarget(card, player, target)) return true; + return false; + } + static targetInRange(card, player, target) { + var info = get.info(card); + var range = info.range; + var outrange = info.outrange; + if (range == undefined && outrange == undefined) return true; + + var mod = game.checkMod(card, player, target, "unchanged", "targetInRange", player); + var extra = 0; + if (mod != "unchanged") { + if (typeof mod == "boolean") return mod; + if (typeof mod == "number") extra = mod; + } + if (typeof info.range == "function") return info.range(card, player, target); + + if (player.hasSkill("undist") || target.hasSkill("undist")) return false; + for (var i in range) { + if (i == "attack") { + var range2 = player.getAttackRange(); + if (range2 <= 0) return false; + var distance = get.distance(player, target) + extra; + if (range[i] <= distance - range2) return false; + } + else { + var distance = get.distance(player, target, i) + extra; + if (range[i] < distance) return false; + } + } + for (var i in outrange) { + if (i == "attack") { + var range2 = player.getAttackRange(); + if (range2 <= 0) return false; + var distance = get.distance(player, target) + extra; + if (outrange[i] > distance - range2 + 1) return false; + } + else { + var distance = get.distance(player, target, i) + extra; + if (outrange[i] > distance) return false; + } + } + return true; + } + static filterTarget(card, player, target) { + return (lib.filter.targetEnabledx(card, player, target) && + lib.filter.targetInRange(card, player, target)); + } + static filterTarget2(card, player, target) { + return (lib.filter.targetEnabled2(card, player, target) && + lib.filter.targetInRange(card, player, target)); + } + static notMe(card, player, target) { + return player != target; + } + static isMe(card, player, target) { + return player == target; + } + static attackFrom(card, player, target) { + return get.distance(player, target, "attack") <= 1; + } + static globalFrom(card, player, target) { + return get.distance(player, target) <= 1; + } + static selectCard() { + return [1, 1]; + } + static selectTarget(card, player) { + if (!card) card = get.card(); + if (!player) player = get.player(); + if (card == undefined) return; + var range, info = get.info(card); + var select = get.copy(info.selectTarget); + if (select == undefined) { + if (info.filterTarget == undefined) return [0, 0]; + range = [1, 1]; + } + else if (typeof select == "number") range = [select, select]; + else if (get.itemtype(select) == "select") range = select; + else if (typeof select == "function") range = select(card, player); + game.checkMod(card, player, range, "selectTarget", player); + if (info.singleCard && info.filterAddedTarget) return [range[0] * 2, range[1] * 2]; + return range; + } + static judge(card, player, target) { + return target.canAddJudge(card); + } + static autoRespondSha() { + return !this.player.hasSha(true); + } + static autoRespondShan() { + return !this.player.hasShan(); + } + static wuxieSwap(event) { + if (event.type == "wuxie") { + if (ui.wuxie && ui.wuxie.classList.contains("glow")) { + return true; + } + if (ui.tempnowuxie && ui.tempnowuxie.classList.contains("glow") && event.state > 0) { + var triggerevent = event.getTrigger(); + if (triggerevent) { + if (ui.tempnowuxie._origin == triggerevent.parent.id) { + return true; + } + } + else if (ui.tempnowuxie._origin == _status.event.id2) { + return true; + } + } + if (lib.config.wuxie_self) { + var tw = event.info_map; + if (tw.player && tw.player.isUnderControl(true) && !tw.player.hasSkillTag("noautowuxie") && + (!tw.targets || tw.targets.length <= 1) && !tw.noai) { + return true; + } + } + } + } +} diff --git a/noname/library/group-nature.js b/noname/library/group-nature.js new file mode 100644 index 000000000..837fd19c9 --- /dev/null +++ b/noname/library/group-nature.js @@ -0,0 +1,11 @@ +export const groupNature = { + shen: "shen", + wei: "water", + shu: "soil", + wu: "wood", + qun: "qun", + western: "thunder", + key: "key", + jin: "thunder", + ye: "thunder" +}; diff --git a/noname/library/help.js b/noname/library/help.js new file mode 100644 index 000000000..9c3a8ac38 --- /dev/null +++ b/noname/library/help.js @@ -0,0 +1,32 @@ +export const HELP = { + 关于游戏: `
关于无名杀
  • 无名杀官方发布地址仅有GitHub仓库!
    点击前往Github仓库
  • 无名杀基于GPLv3开源协议。
    点击查看GPLv3协议
  • 其他所有的所谓“无名杀”社群(包括但不限于绝大多数“官方”QQ群、QQ频道等)均为玩家自发组织,与无名杀官方无关!`, + 游戏操作: "
    • 长按/鼠标悬停/右键单击显示信息。
    • 触屏模式中,双指点击切换暂停;下划显示菜单,上划切换托管。
    • 键盘快捷键
      " + + "
      A切换托管
      W切换不询问无懈
      空格暂停
    • 编辑牌堆
      在卡牌包中修改牌堆后,将自动创建一个临时牌堆,在所有模式中共用,当保存当前牌堆后,临时牌堆被清除。每个模式可设置不同的已保存牌堆,设置的牌堆优先级大于临时牌堆。
    ", + 游戏命令: `
    变量名
    • 场上角色
      game.players
    • 阵亡角色
      game.dead` + + "
    • 玩家
      game.me
    • 玩家的上/下家
      game.me.previous/next" + + "
    • 玩家的上/下家(含阵亡)
      game.me.previousSeat/
      nextSeat" + + "
    • 牌堆
      ui.cardPile
    • 弃牌堆
      ui.discardPile
    " + + `
    角色属性
    • 体力值
      player.hp` + + `
    • 体力上限
      player.maxHp
    • 身份
      player.identity
    • 手牌
      player.getCards("h")
    • 装备牌
      player.getCards("e")
    • 判定牌
      player.getCards("j")` + + "
    • 是否存活/横置/翻面
      player.isAlive()/
      isLinked()/
      isTurnedOver()
    " + + `
    角色操作
    • 受到伤害
      player.damage(source,
      num)` + + "
    • 回复体力
      player.recover(num)
    • 摸牌
      player.draw(num)
    • 获得牌
      player.gain(cards)
    • 弃牌
      player.discard(cards)" + + "
    • 使用卡牌
      player.useCard(card,
      targets)
    • 死亡
      player.die()
    • 复活
      player.revive(hp)
    " + + `
    游戏操作
    • 在命令框中输出结果
      game.print(str)
    • 清除命令框中的内容
      cls
    • 上一条/下一条输入的内容
      up/down
    • 游戏结束
      game.over(bool)` + + "
    • 角色资料
      lib.character
    • 卡牌资料
      lib.card
    ", + 游戏名词: "
    • 智囊:无名杀默认为过河拆桥/无懈可击/无中生有/洞烛先机。牌堆中没有的智囊牌会被过滤。可在卡牌设置中自行增减。若没有可用的智囊,则改为随机选取的三种锦囊牌的牌名。" + + "
    • 仁库:部分武将使用的游戏外共通区域。至多包含六张牌。当有新牌注入后,若牌数超过上限,则将最早进入仁库的溢出牌置入弃牌堆。" + + "
    • 护甲:和体力类似,每点护甲可抵挡1点伤害,但不影响手牌上限。" + + "
    • 随从:通过技能获得,拥有独立的技能、手牌区和装备区(共享判定区),出场时替代主武将的位置;随从死亡时自动切换回主武将。" + + "
    • 发现:从三张随机亮出的牌中选择一张,若无特殊说明,则获得此牌。" + + "
    • 蓄能技:发动时可以增大黄色的数字。若如此做,红色数字于技能的结算过程中改为原来的两倍。" + + "
    • 施法:若技能的拥有者未拥有等待执行的同名“施法”效果,则其可以发动“施法”技能。其须选择声明一个数字X(X∈[1, 3]),在此之后的第X个回合结束时,其执行“施法”效果,且效果中的数字X视为与技能发动者声明的X相同。" + + "
    • 共同拼点:一种特殊的拼点结算。发起者与被指定的拼点目标同时亮出拼点牌,进行一次决算:其中拼点牌点数唯一最大的角色赢,其他角色均没赢;若没有点数唯一最大的拼点牌,则所有角色拼点均没赢。" + + "
    • 强令:若一名角色拥有带有“强令”的技能,则该技能的发动时机为“出牌阶段开始时”。若技能拥有者发动该技能,其须发布“强令”给一名其他角色,并在对应技能的时间节点加以判断目标角色是否成功完成该强令所要求的任务条件。成功或失败则会根据技能效果执行不同结算流程。" + + "
    • 摧坚:若一名角色拥有带有“摧坚”的技能,则该技能的发动时机为“当你使用伤害牌指定第一个目标后”。你可以对其中一个目标发动“摧坚”技能,然后执行后续效果。其中,后续效果里的X等于该目标的非charlotte技能的数量。" + + "
    • 妄行:一种特殊的选项。若一名角色拥有带有“妄行”的技能,则该技能触发时,你须选择声明一个数字X(X∈{1,2,3,4}),技能后续中的X即为你选择的数字。选择完毕后,你获得如下效果:回合结束时,你选择一项:1.弃置X张牌;2.减1点体力上限。" + + "
    • 搏击:若一名角色拥有带有“搏击”的技能,则当该搏击技能触发时,若本次技能的目标角色在你攻击范围内,且你在其攻击范围内,则你执行技能主体效果时,同时额外执行“搏击”后的额外效果。" + + "
    • 游击:若一名角色拥有带有“游击”的技能,则当该游击技能执行至“游击”处时,若本次技能的目标角色在你的攻击范围内,且你不在其攻击范围内,则你可以执行“游击”后的额外效果。" + + "
    • 激昂:一名角色发动“昂扬技”标签技能后,此技能失效,直至从此刻至满足此技能“激昂”条件后。" + + "" +}; diff --git a/noname/library/initialization.js b/noname/library/initialization.js index 9f52d9904..05fa9c824 100644 --- a/noname/library/initialization.js +++ b/noname/library/initialization.js @@ -1 +1,3362 @@ -export class Initialization { } +import { Promises } from "./initialization/promises.js"; + +export class Initialization { + static promises = Promises; + + constructor() { + throw new TypeError(`${new.target.name} is not a constructor`); + } + + static init() { + if (typeof __dirname === "string" && __dirname.length) { + var dirsplit = __dirname.split("/"); + for (var i = 0; i < dirsplit.length; i++) { + if (dirsplit[i]) { + var c = dirsplit[i][0]; + lib.configprefix += /[A-Z]|[a-z]/.test(c) ? c : "_"; + } + } + lib.configprefix += "_"; + } + window.resetGameTimeout = setTimeout(lib.init.reset, parseInt(localStorage.getItem(lib.configprefix + "loadtime")) || 10000); + if (window.cordovaLoadTimeout) { + clearTimeout(window.cordovaLoadTimeout); + delete window.cordovaLoadTimeout; + } + var links = document.head.querySelectorAll("link"); + for (var i = 0; i < links.length; i++) { + if (links[i].href.includes("app/color.css")) { + links[i].remove(); + break; + } + } + var index = window.location.href.indexOf("index.html?server="); + if (index != -1) { + window.isNonameServer = window.location.href.slice(index + 18); + window.nodb = true; + } + else { + index = localStorage.getItem(lib.configprefix + "asserver"); + if (index) { + window.isNonameServer = index; + window.isNonameServerIp = lib.hallURL; + } + } + + var htmlbg = localStorage.getItem(lib.configprefix + "background"); + if (htmlbg) { + if (htmlbg[0] == "[") { + try { + htmlbg = JSON.parse(htmlbg); + htmlbg = htmlbg[get.rand(htmlbg.length)]; + if (htmlbg.startsWith("custom_")) { + throw ("err"); + } + _status.htmlbg = htmlbg; + } + catch (e) { + htmlbg = null; + } + } + if (htmlbg) { + document.documentElement.style.backgroundImage = `url("${lib.assetURL}image/background/${htmlbg}.jpg")`; + document.documentElement.style.backgroundSize = "cover"; + document.documentElement.style.backgroundPosition = "50% 50%"; + } + } + + lib.get = get; + lib.ui = ui; + lib.ai = ai; + lib.game = game; + _status.event = lib.element.GameEvent.initialGameEvent(); + + HTMLDivElement.prototype.animate = function (name, time) { + var that; + if (get.is.mobileMe(this) && name == "target") { + that = ui.mebg; + } + else { + that = this; + } + that.classList.add(name); + setTimeout(function () { + that.classList.remove(name); + }, time || 1000); + return this; + }; + HTMLDivElement.prototype.hide = function () { + this.classList.add("hidden"); + return this; + }; + HTMLDivElement.prototype.unfocus = function () { + if (lib.config.transparent_dialog) this.classList.add("transparent"); + return this; + }; + HTMLDivElement.prototype.refocus = function () { + this.classList.remove("transparent"); + return this; + }; + HTMLDivElement.prototype.show = function () { + this.classList.remove("hidden"); + return this; + }; + HTMLDivElement.prototype.delete = function (time, callback) { + if (this.timeout) { + clearTimeout(this.timeout); + delete this.timeout; + } + if (!this._listeningEnd || this._transitionEnded) { + if (typeof time != "number") time = 500; + this.classList.add("removing"); + var that = this; + this.timeout = setTimeout(function () { + that.remove(); + that.classList.remove("removing"); + if (typeof callback == "function") { + callback(); + } + }, time); + } + else { + this._onEndDelete = true; + } + return this; + }; + HTMLDivElement.prototype.goto = function (position, time) { + if (this.timeout) { + clearTimeout(this.timeout); + delete this.timeout; + } + + if (typeof time != "number") time = 500; + this.classList.add("removing"); + + var that = this; + this.timeout = setTimeout(function () { + if (!that._selfDestroyed) { + position.appendChild(that); + } + that.classList.remove("removing"); + delete that.destiny; + }, time); + this.destiny = position; + return this; + }; + HTMLDivElement.prototype.fix = function () { + clearTimeout(this.timeout); + delete this.timeout; + delete this.destiny; + this.classList.remove("removing"); + return this; + }; + Object.defineProperty(HTMLDivElement.prototype, "setBackground", { + configurable: true, + enumerable: false, + writable: true, + value: function (name, type, ext, subfolder) { + if (!name) return; + let src; + if (ext == "noskin") ext = ".jpg"; + ext = ext || ".jpg"; + subfolder = subfolder || "default"; + if (type) { + let dbimage = null, extimage = null, modeimage = null, nameinfo, gzbool = false; + const mode = get.mode(); + if (type == "character") { + if (lib.characterPack[`mode_${mode}`] && lib.characterPack[`mode_${mode}`][name]) { + if (mode == "guozhan") { + nameinfo = lib.character[name]; + if (name.startsWith("gz_shibing")) name = name.slice(3, 11); + else { + if (lib.config.mode_config.guozhan.guozhanSkin && lib.character[name] && lib.character[name][4].contains("gzskin")) gzbool = true; + name = name.slice(3); + } + } + else modeimage = mode; + } + else if (name.includes("::")) { + name = name.split("::"); + modeimage = name[0]; + name = name[1]; + } + else { + nameinfo = get.character(name); + } + } + if (!modeimage && nameinfo && nameinfo[4]) for (const value of nameinfo[4]) { + if (value.startsWith("ext:")) { + extimage = value; + break; + } + else if (value.startsWith("db:")) { + dbimage = value; + break; + } + else if (value.startsWith("mode:")) { + modeimage = value.slice(5); + break; + } + else if (value.startsWith("character:")) { + name = value.slice(10); + break; + } + } + if (extimage) src = extimage.replace(/^ext:/, "extension/"); + else if (dbimage) { + this.setBackgroundDB(dbimage.slice(3)); + return this; + } + else if (modeimage) src = `image/mode/${modeimage}/character/${name}${ext}`; + else if (type == "character" && lib.config.skin[name] && arguments[2] != "noskin") src = `image/skin/${name}/${lib.config.skin[name]}${ext}`; + else if (type == "character") { + src = `image/character/${gzbool ? "gz_" : ""}${name}${ext}`; + } + else src = `image/${type}/${subfolder}/${name}${ext}`; + } + else src = `image/${name}${ext}`; + this.setBackgroundImage(src); + this.style.backgroundPositionX = "center"; + this.style.backgroundSize = "cover"; + if (type == "character") { + new Promise((_, reject) => { + const image = new Image(); + image.src = `${lib.assetURL}${src}`; + image.onerror = reject; + }).catch(() => new Promise((_, reject) => { + const nameinfo = get.character(name); + if (!nameinfo) reject("noinfo"); + const sex = nameinfo[0]; + src = `image/character/default_silhouette_${sex}${ext}`; + const image = new Image(); + image.src = `${lib.assetURL}${src}`; + image.onload = () => this.setBackgroundImage(src); + image.onerror = () => reject(`sex:${sex}`); + })).catch(reason => { + let sex; + if (reason == "noinfo") sex = "male"; + else sex = reason.slice(4); + src = `image/character/default_silhouette_${sex == "female" ? "female" : "male"}${ext}`; + const image = new Image(); + image.src = `${lib.assetURL}${src}`; + image.onload = () => this.setBackgroundImage(src); + }); + } + return this; + } + }); + HTMLDivElement.prototype.setBackgroundDB = function (img) { + return game.getDB("image", img).then(src => { + this.style.backgroundImage = `url("${src}")`; + this.style.backgroundSize = "cover"; + return this; + }); + }; + HTMLDivElement.prototype.setBackgroundImage = function (img) { + this.style.backgroundImage = `url("${lib.assetURL}${img}")`; + return this; + }, + HTMLDivElement.prototype.listen = function (func) { + if (lib.config.touchscreen) { + this.addEventListener("touchend", function (e) { + if (!_status.dragged) { + func.call(this, e); + } + }); + var fallback = function (e) { + if (!_status.touchconfirmed) { + func.call(this, e); + } + else { + this.removeEventListener("click", fallback); + } + } + this.addEventListener("click", fallback); + } + else { + this.addEventListener("click", func); + } + return this; + }; + HTMLDivElement.prototype.listenTransition = function (func, time) { + let done = false; + const callback = () => { + if (!done) { + done = true; + func.call(this); + } + clearTimeout(timer); + this.removeEventListener("webkitTransitionEnd", callback); + }; + const timer = setTimeout(callback, time || 1000); + this.addEventListener("webkitTransitionEnd", callback); + return timer; + }; + HTMLDivElement.prototype.setPosition = function () { + var position; + if (arguments.length == 4) { + position = []; + for (var i = 0; i < arguments.length; i++) position.push(arguments[i]); + } + else if (arguments.length == 1 && Array.isArray(arguments[0]) && arguments[0].length == 4) { + position = arguments[0]; + } + else { + return this; + } + var top = "calc(" + position[0] + "% "; + if (position[1] > 0) top += "+ " + position[1] + "px)"; + else top += "- " + Math.abs(position[1]) + "px)"; + var left = "calc(" + position[2] + "% "; + if (position[3] > 0) left += "+ " + position[3] + "px)"; + else left += "- " + Math.abs(position[3]) + "px)"; + this.style.top = top; + this.style.left = left; + return this; + }; + HTMLDivElement.prototype.css = function (style) { + for (var i in style) { + if (i == "innerHTML") { + this.innerHTML = style[i]; + } + else { + this.style[i] = style[i]; + } + } + return this; + }; + HTMLTableElement.prototype.get = function (row, col) { + if (row < this.childNodes.length) { + return this.childNodes[row].childNodes[col]; + } + }; + /*处理lib.nature的兼容性问题*/ + const mapHasFunc = function (item) { + return this.has(item) + }; + Object.defineProperty(Map.prototype, "contains", { + configurable: true, + enumerable: false, + writable: true, + value: mapHasFunc + }); + Object.defineProperty(Map.prototype, "includes", { + configurable: true, + enumerable: false, + writable: true, + value: mapHasFunc + }); + const mapAddFunc = function (item) { + this.set(item, 0); + return this; + } + Object.defineProperty(Map.prototype, "add", { + configurable: true, + enumerable: false, + writable: true, + value: mapAddFunc + }); + Object.defineProperty(Map.prototype, "push", { + configurable: true, + enumerable: false, + writable: true, + value: mapAddFunc + }); + Object.defineProperty(Map.prototype, "addArray", { + configurable: true, + enumerable: false, + writable: true, + value: function (arr) { + for (var i = 0; i < arr.length; i++) { + this.add(arr[i]); + } + return this; + } + }); + Object.defineProperty(Map.prototype, "remove", { + configurable: true, + enumerable: false, + writable: true, + value: function (item) { + this.delete(item); + return this; + } + }); + /*Map prototype end*/ + Object.defineProperty(Array.prototype, "filterInD", { + configurable: true, + enumerable: false, + writable: true, + value: function (pos) { + if (typeof pos != "string") pos = "o"; + return this.filter(card => pos.includes(get.position(card, true))); + } + }); + Object.defineProperty(Array.prototype, "someInD", { + configurable: true, + enumerable: false, + writable: true, + value: function (pos) { + if (typeof pos != "string") pos = "o"; + return this.some(card => pos.includes(get.position(card, true))); + } + }); + Object.defineProperty(Array.prototype, "everyInD", { + configurable: true, + enumerable: false, + writable: true, + value: function (pos) { + if (typeof pos != "string") pos = "o"; + return this.every(card => pos.includes(get.position(card, true))); + } + }); + /** + *@legacy Use {@link Array#includes} instead. + */ + Object.defineProperty(Array.prototype, "contains", { + configurable: true, + enumerable: false, + writable: true, + value: Array.prototype.includes + }); + Object.defineProperty(Array.prototype, "containsSome", { + configurable: true, + enumerable: false, + writable: true, + value: function () { + return Array.from(arguments).some(i => this.includes(i)); + } + }); + Object.defineProperty(Array.prototype, "containsAll", { + configurable: true, + enumerable: false, + writable: true, + value: function () { + return Array.from(arguments).every(i => this.includes(i)); + } + }); + + Object.defineProperty(Array.prototype, "add", { + configurable: true, + enumerable: false, + writable: true, + value: function () { + for (const arg of arguments) { + if (this.contains(arg)) continue; + this.push(arg); + } + return this; + } + }); + Object.defineProperty(Array.prototype, "addArray", { + configurable: true, + enumerable: false, + writable: true, + value: function () { + for (const arr of arguments) { + for (const item of arr) this.add(item); + } + return this; + } + }); + Object.defineProperty(Array.prototype, "remove", { + configurable: true, + enumerable: false, + writable: true, + value: function () { + for (const item of arguments) { + let pos = -1; + if (typeof item == "number" && isNaN(item)) { + pos = this.findIndex(v => isNaN(v)) + } else { + pos = this.indexOf(item); + } + if (pos == -1) continue; + this.splice(pos, 1); + } + return this; + } + }); + Object.defineProperty(Array.prototype, "removeArray", { + configurable: true, + enumerable: false, + writable: true, + value: function () { + for (const i of Array.from(arguments)) this.remove(...i); + return this; + } + }); + Object.defineProperty(Array.prototype, "unique", { + configurable: true, + enumerable: false, + writable: true, + value: function () { + let uniqueArray = [...new Set(this)]; + this.length = uniqueArray.length; + for (let i = 0; i < uniqueArray.length; i++) this[i] = uniqueArray[i]; + return this; + } + }); + Object.defineProperty(Array.prototype, "toUniqued", { + configurable: true, + enumerable: false, + writable: true, + value: function () { + return [...new Set(this)]; + } + }); + Object.defineProperty(Array.prototype, "randomGet", { + configurable: true, + enumerable: false, + writable: true, + value: function () { + let arr = this.slice(0); + arr.removeArray(Array.from(arguments)); + return arr[Math.floor(Math.random() * arr.length)]; + } + }); + Object.defineProperty(Array.prototype, "randomGets", { + configurable: true, + enumerable: false, + writable: true, + value: function (num) { + if (num > this.length) num = this.length; + let arr = this.slice(0); + let list = []; + for (let i = 0; i < num; i++) { + list.push(arr.splice(Math.floor(Math.random() * arr.length), 1)[0]); + } + return list; + } + }); + Object.defineProperty(Array.prototype, "randomRemove", { + configurable: true, + enumerable: false, + writable: true, + value: function (num) { + if (typeof num == "number") { + let list = []; + for (let i = 0; i < num; i++) { + if (!this.length) break; + list.push(this.randomRemove()); + } + return list; + } + return this.splice(Math.floor(Math.random() * this.length), 1)[0]; + } + }); + Object.defineProperty(Array.prototype, "randomSort", { + configurable: true, + enumerable: false, + writable: true, + value: function () { + let list = []; + while (this.length) { + list.push(this.randomRemove()); + } + for (let i = 0; i < list.length; i++) { + this.push(list[i]); + } + return this; + } + }); + Object.defineProperty(Array.prototype, "sortBySeat", { + configurable: true, + enumerable: false, + writable: true, + value: function (target) { + lib.tempSortSeat = target; + this.sort(lib.sort.seat); + delete lib.tempSortSeat; + return this; + } + }); + /** + *@description 从数组中寻找某个特征最大的,且通过筛选的第一个元素 + */ + Object.defineProperty(Array.prototype, "maxBy", { + configurable: true, + enumerable: false, + writable: true, + value: function (sortBy, filter) { + let list = this.filter(filter || (() => true)); + if (sortBy && typeof sortBy == "function") list.sort((a, b) => sortBy(a) - sortBy(b)); + else list.sort(); + return list[list.length - 1]; + } + }); + Object.defineProperty(Array.prototype, "minBy", { + configurable: true, + enumerable: false, + writable: true, + value: function (sortBy, filter) { + let list = this.filter(filter || (() => true)); + if (sortBy && typeof sortBy == "function") list.sort((a, b) => sortBy(a) - sortBy(b)); + else list.sort(); + return list[0]; + } + }); + window.onkeydown = function (e) { + if (!ui.menuContainer || !ui.menuContainer.classList.contains("hidden")) { + if (e.keyCode == 116 || ((e.ctrlKey || e.metaKey) && e.keyCode == 82)) { + if (e.shiftKey) { + if (confirm("是否重置游戏?")) { + var noname_inited = localStorage.getItem("noname_inited"); + var onlineKey = localStorage.getItem(lib.configprefix + "key"); + localStorage.clear(); + if (noname_inited) { + localStorage.setItem("noname_inited", noname_inited); + } + if (onlineKey) { + localStorage.setItem(lib.configprefix + "key", onlineKey); + } + if (indexedDB) indexedDB.deleteDatabase(lib.configprefix + "data"); + game.reload(); + return; + } + } + else { + game.reload(); + } + } + else if (e.keyCode == 83 && (e.ctrlKey || e.metaKey)) { + if (window.saveNonameInput) { + window.saveNonameInput(); + } + e.preventDefault(); + e.stopPropagation(); + return false; + } + else if (e.keyCode == 74 && (e.ctrlKey || e.metaKey) && lib.node) { + lib.node.debug(); + } + } + else { + game.closePopped(); + var dialogs = document.querySelectorAll("#window>.dialog.popped:not(.static)"); + for (var i = 0; i < dialogs.length; i++) { + dialogs[i].delete(); + } + if (e.keyCode == 32) { + var node = ui.window.querySelector("pausedbg"); + if (node) { + node.click(); + } + else { + ui.click.pause(); + } + } + else if (e.keyCode == 65) { + if (ui.auto) ui.auto.click(); + } + else if (e.keyCode == 87) { + if (ui.wuxie && ui.wuxie.style.display != "none") { + ui.wuxie.classList.toggle("glow") + } + else if (ui.tempnowuxie) { + ui.tempnowuxie.classList.toggle("glow") + } + } + else if (e.keyCode == 116 || ((e.ctrlKey || e.metaKey) && e.keyCode == 82)) { + if (e.shiftKey) { + if (confirm("是否重置游戏?")) { + var noname_inited = localStorage.getItem("noname_inited"); + var onlineKey = localStorage.getItem(lib.configprefix + "key"); + localStorage.clear(); + if (noname_inited) { + localStorage.setItem("noname_inited", noname_inited); + } + if (onlineKey) { + localStorage.setItem(lib.configprefix + "key", onlineKey); + } + if (indexedDB) indexedDB.deleteDatabase(lib.configprefix + "data"); + game.reload(); + return; + } + } + else { + game.reload(); + } + } + else if (e.keyCode == 83 && (e.ctrlKey || e.metaKey)) { + e.preventDefault(); + e.stopPropagation(); + return false; + } + else if (e.keyCode == 74 && (e.ctrlKey || e.metaKey) && lib.node) { + lib.node.debug(); + } + // else if(e.keyCode==27){ + // if(!ui.arena.classList.contains("paused")) ui.click.config(); + // } + } + }; + window.onload = function () { + if (lib.device) { + var script = document.createElement("script"); + script.src = "cordova.js"; + document.body.appendChild(script); + document.addEventListener("deviceready", function () { + if (lib.init.cordovaReady) { + lib.init.cordovaReady(); + delete lib.init.cordovaReady; + } + }); + } + if (_status.packLoaded) { + delete _status.packLoaded; + lib.init.onload(); + } + else { + _status.windowLoaded = true; + } + }; + + window.onerror = function (msg, src, line, column, err) { + const winPath = window.__dirname ? ("file:///" + (__dirname.replace(new RegExp("\\\\", "g"), "/") + "/")) : ""; + let str = `错误文件: ${typeof src == "string" ? decodeURI(src).replace(lib.assetURL, "").replace(winPath, "") : "未知文件"}`; + str += `\n错误信息: ${msg}`; + const tip = lib.getErrorTip(msg); + if (tip) str += `\n错误提示: ${tip}`; + str += `\n行号: ${line}`; + str += `\n列号: ${column}`; + const version = lib.version || ""; + const reg = /[^\d.]/; + const match = version.match(reg) != null; + str += "\n" + `${match ? "游戏" : "无名杀"}版本: ${version || "未知版本"}`; + if (match) str += "\n⚠️您使用的游戏代码不是源于libccy/noname无名杀官方仓库,请自行寻找您所使用的游戏版本开发者反馈!"; + if (_status && _status.event) { + let evt = _status.event; + str += `\nevent.name: ${evt.name}\nevent.step: ${evt.step}`; + if (evt.parent) str += `\nevent.parent.name: ${evt.parent.name}\nevent.parent.step: ${evt.parent.step}`; + if (evt.parent && evt.parent.parent) str += `\nevent.parent.parent.name: ${evt.parent.parent.name}\nevent.parent.parent.step: ${evt.parent.parent.step}`; + if (evt.player || evt.target || evt.source || evt.skill || evt.card) { + str += "\n-------------" + } + if (evt.player) { + if (lib.translate[evt.player.name]) str += `\nplayer: ${lib.translate[evt.player.name]}[${evt.player.name}]`; + else str += "\nplayer: " + evt.player.name; + let distance = get.distance(_status.roundStart, evt.player, "absolute"); + if (distance != Infinity) { + str += `\n座位号: ${distance + 1}`; + } + } + if (evt.target) { + if (lib.translate[evt.target.name]) str += `\ntarget: ${lib.translate[evt.target.name]}[${evt.target.name}]`; + else str += "\ntarget: " + evt.target.name; + } + if (evt.source) { + if (lib.translate[evt.source.name]) str += `\nsource: ${lib.translate[evt.source.name]}[${evt.source.name}]`; + else str += "\nsource: " + evt.source.name; + } + if (evt.skill) { + if (lib.translate[evt.skill]) str += `\nskill: ${lib.translate[evt.skill]}[${evt.skill}]`; + else str += "\nskill: " + evt.skill; + } + if (evt.card) { + if (lib.translate[evt.card.name]) str += `\ncard: ${lib.translate[evt.card.name]}[${evt.card.name}]`; + else str += "\ncard: " + evt.card.name; + } + } + str += "\n-------------"; + if (typeof line == "number" && (typeof game.readFile == "function" || location.origin != "file://")) { + const createShowCode = function (lines) { + let showCode = ""; + if (lines.length >= 10) { + if (line > 4) { + for (let i = line - 5; i < line + 6 && i < lines.length; i++) { + showCode += `${i + 1}| ${line == i + 1 ? "⚠️" : ""}${lines[i]}\n`; + } + } else { + for (let i = 0; i < line + 6 && i < lines.length; i++) { + showCode += `${i + 1}| ${line == i + 1 ? "⚠️" : ""}${lines[i]}\n`; + } + } + } else { + showCode = lines.map((_line, i) => `${i + 1}| ${line == i + 1 ? "⚠️" : ""}${_line}\n`).toString(); + } + return showCode; + } + //协议名须和html一致(网页端防跨域),且文件是js + if (typeof src == "string" && src.startsWith(location.protocol) && src.endsWith(".js")) { + //获取代码 + const codes = lib.init.reqSync("local:" + decodeURI(src).replace(lib.assetURL, "").replace(winPath, "")); + const lines = codes.split("\n"); + str += "\n" + createShowCode(lines); + str += "\n-------------"; + } + //解析parsex里的content fun内容(通常是技能content) + else if (err && err.stack && err.stack.split("\n")[1].trim().startsWith("at Object.eval [as content]")) { + const codes = _status.event.content; + if (typeof codes == "function") { + const lines = codes.toString().split("\n"); + str += "\n" + createShowCode(lines); + str += "\n-------------"; + } + } + } + if (err && err.stack) str += "\n" + decodeURI(err.stack).replace(new RegExp(lib.assetURL, "g"), "").replace(new RegExp(winPath, "g"), ""); + alert(str); + window.ea = Array.from(arguments); + window.em = msg; + window.el = line; + window.ec = column; + window.eo = err; + game.print(str); + if (!lib.config.errstop) { + _status.withError = true; + game.loop(); + } + }; + + if (window.noname_update) { + lib.version = window.noname_update.version; + lib.changeLog = window.noname_update.changeLog; + if (window.noname_update.players) { + lib.changeLog.push("players://" + JSON.stringify(window.noname_update.players)); + } + if (window.noname_update.cards) { + lib.changeLog.push("cards://" + JSON.stringify(window.noname_update.cards)); + } + delete window.noname_update; + } + var noname_inited = localStorage.getItem("noname_inited"); + if (noname_inited && noname_inited !== "nodejs") { + var ua = userAgent; + if (ua.includes("android")) { + lib.device = "android"; + } + else if (ua.includes("iphone") || ua.includes("ipad") || ua.includes("macintosh")) { + lib.device = "ios"; + } + } + + if (lib.assetURL.includes("com.widget.noname.qingyao") || lib.assetURL.includes("online.nonamekill.android")) { + alert("您正在一个不受信任的闭源客户端上运行《无名杀》。建议您更换为其他开源的无名杀客户端,避免给您带来不必要的损失。"); + } + + var config3 = null; + var proceed = function (config2) { + if (config3 === null) { + config3 = config2; + return; + } + if (config2.mode) lib.config.mode = config2.mode; + if (lib.config.mode_config[lib.config.mode] == undefined) lib.config.mode_config[lib.config.mode] = {}; + for (var i in lib.config.mode_config.global) { + if (lib.config.mode_config[lib.config.mode][i] == undefined) { + lib.config.mode_config[lib.config.mode][i] = lib.config.mode_config.global[i]; + } + } + if (lib.config.characters) { + lib.config.defaultcharacters = lib.config.characters.slice(0); + } + if (lib.config.cards) { + lib.config.defaultcards = lib.config.cards.slice(0); + } + for (var i in config2) { + if (i.includes("_mode_config")) { + var thismode = i.substr(i.indexOf("_mode_config") + 13); + if (!lib.config.mode_config[thismode]) { + lib.config.mode_config[thismode] = {}; + } + lib.config.mode_config[thismode][i.substr(0, i.indexOf("_mode_config"))] = config2[i]; + } + else { + lib.config[i] = config2[i]; + } + } + for (var i in lib.config.translate) { + lib.translate[i] = lib.config.translate[i]; + } + + lib.config.all.characters = []; + lib.config.all.cards = []; + lib.config.all.plays = []; + lib.config.all.mode = []; + + if (lib.config.debug) { + lib.init.js(lib.assetURL + "game", "asset", function () { + lib.skin = window.noname_skin_list; + delete window.noname_skin_list; + delete window.noname_asset_list; + }); + } + + if (window.isNonameServer) { + lib.config.mode = "connect"; + } + var pack = window.noname_package; + delete window.noname_package; + for (i in pack.character) { + if (lib.config.all.sgscharacters.contains(i) || lib.config.hiddenCharacterPack.indexOf(i) == -1) { + lib.config.all.characters.push(i); + lib.translate[i + "_character_config"] = pack.character[i]; + } + } + for (i in pack.card) { + if (lib.config.all.sgscards.contains(i) || lib.config.hiddenCardPack.indexOf(i) == -1) { + lib.config.all.cards.push(i); + lib.translate[i + "_card_config"] = pack.card[i]; + } + } + for (i in pack.play) { + lib.config.all.plays.push(i); + lib.translate[i + "_play_config"] = pack.play[i]; + } + for (i in pack.submode) { + for (var j in pack.submode[i]) { + lib.translate[i + "|" + j] = pack.submode[i][j]; + } + } + + if (!lib.config.gameRecord) { + lib.config.gameRecord = {}; + } + for (i in pack.mode) { + if (lib.config.hiddenModePack.indexOf(i) == -1) { + lib.config.all.mode.push(i); + lib.translate[i] = pack.mode[i]; + if (!lib.config.gameRecord[i]) { + lib.config.gameRecord[i] = { data: {} }; + } + } + } + if (lib.config.all.mode.length == 0) { + lib.config.all.mode.push("identity"); + lib.translate.identity = "身份"; + if (!lib.config.gameRecord.identity) { + lib.config.gameRecord.identity = { data: {} }; + } + } + if (pack.background) { + for (i in pack.background) { + if (lib.config.hiddenBackgroundPack.contains(i)) continue; + lib.configMenu.appearence.config.image_background.item[i] = pack.background[i]; + } + for (var i = 0; i < lib.config.customBackgroundPack.length; i++) { + var link = lib.config.customBackgroundPack[i]; + lib.configMenu.appearence.config.image_background.item[link] = link.slice(link.indexOf("_") + 1); + } + lib.configMenu.appearence.config.image_background.item.default = "默认"; + } + if (pack.music) { + if (lib.device || typeof window.require == "function") { + lib.configMenu.audio.config.background_music.item.music_custom = "自定义音乐"; + } + lib.config.all.background_music = ["music_default"]; + for (i in pack.music) { + lib.config.all.background_music.push(i); + lib.configMenu.audio.config.background_music.item[i] = pack.music[i]; + } + if (lib.config.customBackgroundMusic) { + for (i in lib.config.customBackgroundMusic) { + lib.config.all.background_music.push(i); + lib.configMenu.audio.config.background_music.item[i] = lib.config.customBackgroundMusic[i]; + } + } + lib.configMenu.audio.config.background_music.item.music_random = "随机播放"; + lib.configMenu.audio.config.background_music.item.music_off = "关闭"; + } + if (pack.theme) { + for (i in pack.theme) { + lib.configMenu.appearence.config.theme.item[i] = pack.theme[i]; + } + } + if (lib.config.extension_sources) { + for (i in lib.config.extension_sources) { + lib.configMenu.general.config.extension_source.item[i] = i; + } + } + + if (pack.font) { + ui.css.fontsheet = lib.init.sheet(); + const appearenceConfig = lib.configMenu.appearence.config, fontSheet = ui.css.fontsheet.sheet, suitsFont = lib.config.suits_font; + Object.keys(pack.font).forEach(value => { + const font = pack.font[value]; + appearenceConfig.name_font.item[value] = font; + appearenceConfig.identity_font.item[value] = font; + appearenceConfig.cardtext_font.item[value] = font; + appearenceConfig.global_font.item[value] = font; + fontSheet.insertRule(`@font-face {font-family: "${value}"; src: local("${font}"), url("${lib.assetURL}font/${value}.woff2");}`, 0); + if (suitsFont) fontSheet.insertRule(`@font-face {font-family: "${value}"; src: local("${font}"), url("${lib.assetURL}font/suits.woff2");}`, 0); + }); + if (suitsFont) fontSheet.insertRule(`@font-face {font-family: "Suits"; src: url("${lib.assetURL}font/suits.woff2");}`, 0); + fontSheet.insertRule(`@font-face {font-family: "NonameSuits"; src: url("${lib.assetURL}font/suits.woff2");}`, 0); + fontSheet.insertRule(`@font-face {font-family: "MotoyaLMaru"; src: url("${lib.assetURL}font/motoyamaru.woff2");}`, 0) + appearenceConfig.cardtext_font.item.default = "默认"; + appearenceConfig.global_font.item.default = "默认"; + } + + var ua = userAgent; + if ("ontouchstart" in document) { + if (!lib.config.totouched) { + game.saveConfig("totouched", true); + if (lib.device) { + game.saveConfig("low_performance", true); + game.saveConfig("confirm_exit", true); + game.saveConfig("touchscreen", true); + game.saveConfig("fold_mode", false); + if (ua.indexOf("ipad") == -1) { + game.saveConfig("phonelayout", true); + } + else if (lib.device == "ios") { + game.saveConfig("show_statusbar_ios", "overlay"); + } + } + else if (confirm("是否切换到触屏模式?(触屏模式可提高触屏设备的响应速度,但无法使用鼠标)")) { + game.saveConfig("touchscreen", true); + if (ua.includes("iphone") || ua.includes("android")) { + game.saveConfig("phonelayout", true); + } + game.reload(); + } + } + } + else if (lib.config.touchscreen) { + game.saveConfig("touchscreen", false); + } + if (!lib.config.toscrolled && ua.includes("macintosh")) { + game.saveConfig("toscrolled", true); + game.saveConfig("mousewheel", false); + } + + var show_splash = lib.config.show_splash; + if (show_splash == "off") { + show_splash = false; + } + else if (show_splash == "init") { + if (localStorage.getItem("show_splash_off")) { + show_splash = false; + } + } + localStorage.removeItem("show_splash_off"); + var extensionlist = []; + if (!localStorage.getItem(lib.configprefix + "disable_extension")) { + if (lib.config.extensions && lib.config.extensions.length) { + window.resetExtension = function () { + for (var i = 0; i < lib.config.extensions.length; i++) { + game.saveConfig("extension_" + lib.config.extensions[i] + "_enable", false); + } + localStorage.setItem(lib.configprefix + "disable_extension", true); + } + } + for (var i = 0; i < lib.config.plays.length; i++) { + if (lib.config.all.plays.includes(lib.config.plays[i])) { + extensionlist.push(lib.config.plays[i]); + } + } + var alerted = false; + for (var i = 0; i < lib.config.extensions.length; i++) { + if (window.bannedExtensions.contains(lib.config.extensions[i])) { + //if(!alerted) alert("读取某些扩展时出现问题。"); + alerted = true; + continue; + } + var extcontent = localStorage.getItem(lib.configprefix + "extension_" + lib.config.extensions[i]); + if (extcontent) { + //var backup_onload=lib.init.onload; + _status.evaluatingExtension = true; + try { + eval(extcontent); + } + catch (e) { + console.log(e); + } + //lib.init.onload=backup_onload; + _status.evaluatingExtension = false; + } + else if (lib.config.mode != "connect" || (!localStorage.getItem(lib.configprefix + "directstart") && show_splash)) { + extensionlist.push(lib.config.extensions[i]); + } + } + } + else { + if (lib.config.mode != "connect" || (!localStorage.getItem(lib.configprefix + "directstart") && show_splash)) { + var alerted = false; + for (var i = 0; i < lib.config.extensions.length; i++) { + if (window.bannedExtensions.contains(lib.config.extensions[i])) { + //if(!alerted) alert("读取某些扩展时出现问题。"); + alerted = true; + continue; + } + game.import("extension", { name: lib.config.extensions[i] }); + } + } + } + const loadPack = () => { + const isArray = Array.isArray; + if (isArray(lib.onprepare) && lib.onprepare.length) { + _status.onprepare = Object.freeze(lib.onprepare.map(fn => { + if (typeof fn != "function") return; + return (gnc.is.generatorFunc(fn) ? gnc.of(fn) : fn)(); + })); + } + let toLoad = lib.config.all.cards.length + lib.config.all.characters.length + 1; + if (_status.javaScriptExtensions) toLoad += _status.javaScriptExtensions.reduce((constructingToLoad, javaScriptExtension) => { + const lengths = Object.values(javaScriptExtension).reduce((constructingLengths, value) => { + if (isArray(value)) constructingLengths.push(value.length); + return constructingLengths; + }, []); + if (!lengths.length) return constructingToLoad + 1; + return constructingToLoad + Math.min(...lengths); + }, 0); + const packLoaded = gnc.of(function* () { + toLoad--; + if (toLoad) return; + if (_status.importing) { + let promises = lib.creation.array; + for (const type in _status.importing) { + promises.addArray(_status.importing[type]) + } + yield Promise.allSettled(promises); + delete _status.importing; + } + if (_status.windowLoaded) { + delete _status.windowLoaded; + lib.init.onload(); + } + else _status.packLoaded = true; + }); + if (localStorage.getItem(`${lib.configprefix}playback`)) { + toLoad++; + lib.init.js(`${lib.assetURL}mode`, lib.config.mode, packLoaded, packLoaded); + } + else if ((localStorage.getItem(`${lib.configprefix}directstart`) || !show_splash) && lib.config.all.mode.includes(lib.config.mode)) { + toLoad++; + lib.init.js(`${lib.assetURL}mode`, lib.config.mode, packLoaded, packLoaded); + } + lib.init.js(`${lib.assetURL}card`, lib.config.all.cards, packLoaded, packLoaded); + lib.init.js(`${lib.assetURL}character`, lib.config.all.characters, packLoaded, packLoaded); + lib.init.js(`${lib.assetURL}character`, "rank", packLoaded, packLoaded); + if (!_status.javaScriptExtensions) return; + const loadJavaScriptExtension = (javaScriptExtension, pathArray, fileArray, onLoadArray, onErrorArray, index) => { + if (!pathArray && !fileArray && !onLoadArray && !onErrorArray) { + lib.init.js(javaScriptExtension.path, javaScriptExtension.file, () => { + if (typeof javaScriptExtension.onload == "function") javaScriptExtension.onload(); + packLoaded(); + }, () => { + if (typeof javaScriptExtension.onerror == "function") javaScriptExtension.onerror(); + packLoaded(); + }); + return; + } + if (typeof index != "number") index = 0; + if (pathArray && index >= javaScriptExtension.path.length) return; + if (fileArray && index >= javaScriptExtension.file.length) return; + if (onLoadArray && index >= javaScriptExtension.onload.length) return; + if (onErrorArray && index >= javaScriptExtension.onerror.length) return; + const path = pathArray ? javaScriptExtension.path[index] : javaScriptExtension.path; + const file = fileArray ? javaScriptExtension.file[index] : javaScriptExtension.file; + const onLoad = onLoadArray ? javaScriptExtension.onload[index] : javaScriptExtension.onload; + const onError = onErrorArray ? javaScriptExtension.onerror[index] : javaScriptExtension.onerror; + const javaScriptExtensionOnLoad = () => { + if (typeof onLoad == "function") onLoad(); + loadJavaScriptExtension(javaScriptExtension, pathArray, fileArray, onLoadArray, onErrorArray, index + 1); + packLoaded(); + }, jsExtOnError = () => { + if (typeof onError == "function") onError(); + loadJavaScriptExtension(javaScriptExtension, pathArray, fileArray, onLoadArray, onErrorArray, index + 1); + packLoaded(); + }; + lib.init.js(path, file, javaScriptExtensionOnLoad, jsExtOnError); + }; + _status.javaScriptExtensions.forEach(javaScriptExtension => { + const pathArray = isArray(javaScriptExtension.path); + const fileArray = isArray(javaScriptExtension.file); + const onLoadArray = isArray(javaScriptExtension.onLoad); + const onErrorArray = isArray(javaScriptExtension.onError); + loadJavaScriptExtension(javaScriptExtension, pathArray, fileArray, onLoadArray, onErrorArray); + }); + }; + + var layout = lib.config.layout; + if (layout == "default" || lib.layoutfixed.indexOf(lib.config.mode) !== -1) { + layout = "mobile"; + } + if (layout == "phone") { + layout = "mobile"; + game.saveConfig("layout", "mobile"); + game.saveConfig("phonelayout", true); + } + game.layout = layout; + if (lib.config.image_background_random) { + if (_status.htmlbg) { + game.saveConfig("image_background", _status.htmlbg); + } + else { + var list = []; + for (var i in lib.configMenu.appearence.config.image_background.item) { + if (i == "default") continue; + list.push(i); + } + game.saveConfig("image_background", list.randomGet(lib.config.image_background)); + } + lib.init.background(); + } + delete _status.htmlbg; + + window.game = game; + // node:path library alternative + if (typeof module != "object" || typeof module.exports != "object") lib.init.js(`${lib.assetURL}game`, "path", () => { + lib.path = window._noname_path; + delete window._noname_path; + }, e => { + console.log(e); + }); + var styleToLoad = 6; + var styleLoaded = gnc.of(function* () { + --styleToLoad; + if (styleToLoad == 0) { + if (extensionlist.length && (lib.config.mode != "connect" || show_splash)) { + _status.extensionLoading = []; + let extToLoad = extensionlist.length; + const extLoaded = gnc.of(function* () { + --extToLoad; + if (extToLoad == 0) { + yield Promise.allSettled(_status.extensionLoading); + _status.extensionLoaded.filter(Boolean).forEach(name => { + lib.announce.publish("Noname.Init.Extension.onLoad", name); + lib.announce.publish(`Noname.Init.Extension.${name}.onLoad`, void 0); + }); + delete _status.extensionLoading; + loadPack(); + } + }); + //读取扩展 + var alerted = false; + for (var i = 0; i < extensionlist.length; i++) { + if (window.bannedExtensions.contains(extensionlist[i])) { + alerted = true; + --extToLoad; + if (extToLoad == 0) { + yield Promise.allSettled(_status.extensionLoading); + delete _status.extensionLoading; + loadPack(); + } + continue; + } + lib.init.js(lib.assetURL + "extension/" + extensionlist[i], "extension", extLoaded, (function (i) { + return gnc.of(function* () { + game.removeExtension(i); + --extToLoad; + if (extToLoad == 0) { + yield Promise.allSettled(_status.extensionLoading); + delete _status.extensionLoading; + loadPack(); + } + }); + }(extensionlist[i]))); + } + } + else { + loadPack(); + } + } + }); + if (lib.config.layout == "default") { + lib.config.layout = "mobile"; + } + ui.css.layout = lib.init.css(lib.assetURL + "layout/" + layout, "layout", styleLoaded); + if (get.is.phoneLayout()) { + ui.css.phone = lib.init.css(lib.assetURL + "layout/default", "phone", styleLoaded); + } + else { + ui.css.phone = lib.init.css(); + styleToLoad--; + } + ui.css.theme = lib.init.css(lib.assetURL + "theme/" + lib.config.theme, "style", styleLoaded); + ui.css.card_style = lib.init.css(lib.assetURL + "theme/style/card", lib.config.card_style, styleLoaded); + ui.css.cardback_style = lib.init.css(lib.assetURL + "theme/style/cardback", lib.config.cardback_style, styleLoaded); + ui.css.hp_style = lib.init.css(lib.assetURL + "theme/style/hp", lib.config.hp_style, styleLoaded); + + if (lib.config.player_style && lib.config.player_style != "default" && lib.config.player_style != "custom") { + var str = ""; + switch (lib.config.player_style) { + case "wood": str = `url("${lib.assetURL}theme/woodden/wood.jpg")`; break; + case "music": str = "linear-gradient(#4b4b4b, #464646)"; break; + case "simple": str = "linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4))"; break; + } + ui.css.player_stylesheet = lib.init.sheet("#window .player{background-image:" + str + "}"); + } + if (lib.config.border_style && lib.config.border_style != "default" && lib.config.border_style != "custom" && lib.config.border_style != "auto") { + ui.css.border_stylesheet = lib.init.sheet(); + var bstyle = lib.config.border_style; + if (bstyle.startsWith("dragon_")) { + bstyle = bstyle.slice(7); + } + ui.css.border_stylesheet.sheet.insertRule(`#window .player>.framebg,#window #arena.long.mobile:not(.fewplayer) .player[data-position="0"]>.framebg{display:block;background-image:url("${lib.assetURL}theme/style/player/${bstyle}1.png")}`, 0); + ui.css.border_stylesheet.sheet.insertRule(`#window #arena.long:not(.fewplayer) .player>.framebg, #arena.oldlayout .player>.framebg{background-image:url("${lib.assetURL}theme/style/player/${bstyle}3.png")}`, 0); + ui.css.border_stylesheet.sheet.insertRule(".player>.count{z-index: 3 !important;border-radius: 2px !important;text-align: center !important;}", 0); + } + if (lib.config.control_style && lib.config.control_style != "default" && lib.config.control_style != "custom") { + var str = ""; + switch (lib.config.control_style) { + case "wood": str = `url("${lib.assetURL}theme/woodden/wood.jpg")`; break; + case "music": str = "linear-gradient(#4b4b4b, #464646);color:white;text-shadow:black 0 0 2px"; break; + case "simple": str = "linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4));color:white;text-shadow:black 0 0 2px"; break; + } + if (lib.config.control_style == "wood") { + ui.css.control_stylesheet = lib.init.sheet("#window .control,#window .menubutton,#window #system>div>div,#window #system>div>.pressdown2{background-image:" + str + "}"); + } + else { + ui.css.control_stylesheet = lib.init.sheet("#window .control,.menubutton:not(.active):not(.highlight):not(.red):not(.blue),#window #system>div>div{background-image:" + str + "}"); + } + } + if (lib.config.menu_style && lib.config.menu_style != "default" && lib.config.menu_style != "custom") { + var str = ""; + switch (lib.config.menu_style) { + case "wood": str = `url("${lib.assetURL}theme/woodden/wood2.png")`; break; + case "music": str = "linear-gradient(#4b4b4b, #464646);color:white;text-shadow:black 0 0 2px"; break; + case "simple": str = "linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4));color:white;text-shadow:black 0 0 2px"; break; + } + ui.css.menu_stylesheet = lib.init.sheet("html #window>.dialog.popped,html .menu,html .menubg{background-image:" + str + "}"); + } + + lib.config.duration = 500; + + if (!lib.config.touchscreen) { + document.addEventListener("mousewheel", ui.click.windowmousewheel, { passive: true }); + document.addEventListener("mousemove", ui.click.windowmousemove); + document.addEventListener("mousedown", ui.click.windowmousedown); + document.addEventListener("mouseup", ui.click.windowmouseup); + document.addEventListener("contextmenu", ui.click.right); + } + else { + document.addEventListener("touchstart", ui.click.touchconfirm); + document.addEventListener("touchstart", ui.click.windowtouchstart); + document.addEventListener("touchend", ui.click.windowtouchend); + document.addEventListener("touchmove", ui.click.windowtouchmove); + } + }; + var proceed2 = () => { + if (config3) { + proceed(config3); + } + else { + config3 = true; + } + }; + + ui.css = { + menu: lib.init.css(lib.assetURL + "layout/default", "menu", function () { + ui.css.default = lib.init.css(lib.assetURL + "layout/default", "layout"); + proceed2(); + }) + }; + + if (lib.device) { + lib.init.cordovaReady = function () { + if (lib.device == "android") { + document.addEventListener("pause", function () { + if (!_status.paused2 && (typeof _status.event.isMine == "function" && !_status.event.isMine())) { + ui.click.pause(); + } + if (ui.backgroundMusic) { + ui.backgroundMusic.pause(); + } + }); + document.addEventListener("resume", () => { + if (ui.backgroundMusic) ui.backgroundMusic.play(); + }); + document.addEventListener("backbutton", function () { + if (ui.arena && ui.arena.classList.contains("menupaused")) { + if (window.saveNonameInput) { + window.saveNonameInput(); + } + else { + ui.click.configMenu(); + } + } + else if (lib.config.confirm_exit) { + navigator.notification.confirm( + "是否退出游戏?", + function (index) { + switch (index) { + case 2: game.reload(); break; + case 3: navigator.app.exitApp(); break; + } + }, + "确认退出", + ["取消", "重新开始", "退出"] + ); + } + else { + navigator.app.exitApp(); + } + }); + 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); + } + }, lib.other.ignore); + }); + } + } + game.download = function (url, folder, onsuccess, onerror, dev, onprogress) { + if (!url.startsWith("http")) { + url = get.url(dev) + url; + } + var fileTransfer = new FileTransfer(); + folder = lib.assetURL + folder; + if (onprogress) { + fileTransfer.onprogress = function (progressEvent) { + onprogress(progressEvent.loaded, progressEvent.total); + }; + } + lib.config.brokenFile.add(folder); + game.saveConfigValue("brokenFile"); + fileTransfer.download(encodeURI(url), encodeURI(folder), function () { + lib.config.brokenFile.remove(folder); + game.saveConfigValue("brokenFile"); + if (onsuccess) { + onsuccess(); + } + }, onerror); + }; + game.readFile = function (filename, callback, onerror) { + window.resolveLocalFileSystemURL(lib.assetURL, function (entry) { + entry.getFile(filename, {}, function (fileEntry) { + fileEntry.file(function (fileToLoad) { + var fileReader = new FileReader(); + fileReader.onload = function (e) { + callback(e.target.result); + }; + fileReader.readAsArrayBuffer(fileToLoad, "UTF-8"); + }, onerror); + }, onerror); + }, onerror); + }; + game.readFileAsText = function (filename, callback, onerror) { + window.resolveLocalFileSystemURL(lib.assetURL, function (entry) { + entry.getFile(filename, {}, function (fileEntry) { + fileEntry.file(function (fileToLoad) { + var fileReader = new FileReader(); + fileReader.onload = function (e) { + callback(e.target.result); + }; + fileReader.readAsText(fileToLoad, "UTF-8"); + }, onerror); + }, onerror); + }, onerror); + }; + game.writeFile = function (data, path, name, callback) { + game.ensureDirectory(path, function () { + if (Object.prototype.toString.call(data) == "[object File]") { + var fileReader = new FileReader(); + fileReader.onload = function (e) { + game.writeFile(e.target.result, path, name, callback); + }; + fileReader.readAsArrayBuffer(data, "UTF-8"); + } + else { + window.resolveLocalFileSystemURL(lib.assetURL + path, function (entry) { + entry.getFile(name, { create: true }, function (fileEntry) { + fileEntry.createWriter(function (fileWriter) { + fileWriter.onwriteend = callback; + fileWriter.write(data); + }, callback); + }, callback); + }, callback); + } + }); + }; + game.removeFile = function (dir, callback) { + window.resolveLocalFileSystemURL(lib.assetURL, function (entry) { + entry.getFile(dir, {}, function (fileEntry) { + fileEntry.remove(); + if (callback) callback(); + }, callback || function () { }); + }, callback || function () { }); + }; + game.getFileList = (dir, success, failure) => { + var files = [], folders = []; + window.resolveLocalFileSystemURL(lib.assetURL + dir, entry => { + var dirReader = entry.createReader(); + var entries = []; + var readEntries = () => { + dirReader.readEntries(results => { + if (!results.length) { + entries.sort(); + for (var i = 0; i < entries.length; i++) { + if (entries[i].isDirectory) { + folders.push(entries[i].name); + } + else { + files.push(entries[i].name); + } + } + success(folders, files); + } + else { + entries = entries.concat(Array.from(results)); + readEntries(); + } + }, failure); + }; + readEntries(); + }, failure); + }; + game.ensureDirectory = (list, callback, file) => { + const directoryList = typeof list == "string" ? [list] : list.slice().reverse(), num = file ? 1 : 0, access = (entry, directory, createDirectory) => { + if (directory.length <= num) { + createDirectory(); + return; + } + const str = directory.pop(); + return new Promise((resolve, reject) => entry.getDirectory(str, { + create: false + }, resolve, reject)).catch(() => new Promise(resolve => entry.getDirectory(str, { + create: true + }, resolve))).then(directoryEntry => access(directoryEntry, directory, createDirectory)); + }; + return new Promise((resolve, reject) => window.resolveLocalFileSystemURL(lib.assetURL, rootEntry => { + const createDirectory = () => { + if (directoryList.length) access(rootEntry, directoryList.pop().split("/").reverse(), createDirectory); + if (typeof callback == "function") callback(); + resolve(); + }; + createDirectory(); + }, reject)); + }; + if (ui.updateUpdate) { + ui.updateUpdate(); + } + var showbar = function () { + if (window.StatusBar) { + if (lib.device == "android") { + if (lib.config.show_statusbar_android) { + window.StatusBar.overlaysWebView(false); + window.StatusBar.backgroundColorByName("black"); + window.StatusBar.show(); + } + } + else if (lib.device == "ios") { + if (lib.config.show_statusbar_ios != "off" && lib.config.show_statusbar_ios != "auto") { + if (lib.config.show_statusbar_ios == "default") { + window.StatusBar.overlaysWebView(false); + } + else { + window.StatusBar.overlaysWebView(true); + } + window.StatusBar.backgroundColorByName("black"); + window.StatusBar.show(); + } + } + } + } + if (lib.arenaReady) { + lib.arenaReady.push(showbar); + } + else { + showbar(); + } + }; + } + else if (typeof window.require == "function") { + lib.node = { + fs: require("fs"), + path: require("path"), + debug: function () { + require("electron").remote.getCurrentWindow().toggleDevTools(); + } + }; + lib.path = lib.node.path; + game.download = function (url, folder, onsuccess, onerror, dev, onprogress) { + if (!url.startsWith("http")) { + url = get.url(dev) + url; + } + game.ensureDirectory(folder, function () { + try { + var file = lib.node.fs.createWriteStream(__dirname + "/" + folder); + } + catch (e) { + onerror(); + } + lib.config.brokenFile.add(folder); + game.saveConfigValue("brokenFile"); + if (!lib.node.http) lib.node.http = require("http"); + if (!lib.node.https) lib.node.https = require("https"); + var opts = require("url").parse(encodeURI(url)); + opts.headers = { "User-Agent": "AppleWebkit" }; + (url.startsWith("https") ? lib.node.https : lib.node.http).get(opts, function (response) { + var stream = response.pipe(file); + stream.on("finish", function () { + lib.config.brokenFile.remove(folder); + game.saveConfigValue("brokenFile"); + if (onsuccess) { + onsuccess(); + } + }); + stream.on("error", onerror); + if (onprogress) { + var streamInterval = setInterval(function () { + if (stream.closed) { + clearInterval(streamInterval); + } + else { + onprogress(stream.bytesWritten); + } + }, 200); + } + }); + }, true); + }; + game.readFile = function (filename, callback, onerror) { + lib.node.fs.readFile(__dirname + "/" + filename, function (err, data) { + if (err) { + onerror(err); + } + else { + callback(data); + } + }); + }; + game.readFileAsText = function (filename, callback, onerror) { + lib.node.fs.readFile(__dirname + "/" + filename, "utf-8", function (err, data) { + if (err) { + onerror(err); + } + else { + callback(data); + } + }); + }; + game.writeFile = function (data, path, name, callback) { + game.ensureDirectory(path, function () { + if (Object.prototype.toString.call(data) == "[object File]") { + var fileReader = new FileReader(); + fileReader.onload = function (e) { + game.writeFile(e.target.result, path, name, callback); + }; + fileReader.readAsArrayBuffer(data, "UTF-8"); + } + else { + get.zip(function (zip) { + zip.file("i", data); + lib.node.fs.writeFile(__dirname + "/" + path + "/" + name, zip.files.i.asNodeBuffer(), null, callback); + }); + } + }); + }; + game.removeFile = function (filename, callback) { + lib.node.fs.unlink(__dirname + "/" + filename, callback || function () { }); + }; + game.getFileList = (dir, success, failure) => { + var files = [], folders = []; + dir = __dirname + "/" + dir; + if (typeof failure == "undefined") { + failure = err => { + throw err; + }; + } + else if (failure == null) { + failure = () => { }; + } + try { + lib.node.fs.readdir(dir, (err, filelist) => { + if (err) { + failure(err); + return; + } + for (var i = 0; i < filelist.length; i++) { + if (filelist[i][0] != "." && filelist[i][0] != "_") { + if (lib.node.fs.statSync(dir + "/" + filelist[i]).isDirectory()) { + folders.push(filelist[i]); + } + else { + files.push(filelist[i]); + } + } + } + success(folders, files); + }); + } + catch (e) { + failure(e); + } + }; + game.ensureDirectory = (list, callback, file) => { + const directoryList = typeof list == "string" ? [list] : list.slice().reverse(), number = file ? 1 : 0, access = (path, directory, createDirectory) => { + if (directory.length <= number) { + createDirectory(); + return; + } + path += `/${directory.pop()}`; + const fullPath = `${__dirname}${path}`; + return new Promise((resolve, reject) => lib.node.fs.access(fullPath, errnoException => { + if (errnoException) reject(); + else resolve(); + })).catch(() => new Promise((resolve, reject) => lib.node.fs.mkdir(fullPath, errnoException => { + if (errnoException) reject(errnoException); + else resolve(); + }))).then(() => access(path, directory, createDirectory), console.log); + }; + return new Promise(resolve => { + const createDirectory = () => { + if (directoryList.length) access("", directoryList.pop().split("/").reverse(), createDirectory); + else { + if (typeof callback == "function") callback(); + resolve(); + } + }; + createDirectory(); + }); + }; + if (ui.updateUpdate) { + ui.updateUpdate(); + } + } + else { + //为其他自定义平台提供文件读写函数赋值的一种方式。 + //但这种方式只能修改game的文件读写函数。 + if (window.initReadWriteFunction) { + const g = {}; + const ReadWriteFunctionName = ["download", "readFile", "readFileAsText", "writeFile", "removeFile", "getFileList", "ensureDirectory", "createDir"]; + ReadWriteFunctionName.forEach(prop => { + Object.defineProperty(g, prop, { + configurable: true, + get() { return undefined; }, + set(newValue) { + if (typeof newValue == "function") { + delete g[prop]; + g[prop] = game[prop] = newValue; + } + } + }) + }); + window.initReadWriteFunction(g); + } + window.onbeforeunload = function () { + if (lib.config.confirm_exit && !_status.reloading) { + return "是否离开游戏?" + } + else { + return null; + } + }; + } + + lib.config = window.config; + lib.configOL = {}; + delete window.config; + let config2; + if (localStorage.getItem(`${lib.configprefix}nodb`)) window.nodb = true; + if (window.indexedDB && !window.nodb) new Promise((resolve, reject) => { + const idbOpenDBRequest = window.indexedDB.open(`${lib.configprefix}data`, 4); + idbOpenDBRequest.onerror = reject; + idbOpenDBRequest.onsuccess = resolve; + idbOpenDBRequest.onupgradeneeded = idbVersionChangeEvent => { + const idbDatabase = idbVersionChangeEvent.target.result; + if (!idbDatabase.objectStoreNames.contains("video")) idbDatabase.createObjectStore("video", { + keyPath: "time" + }); + if (!idbDatabase.objectStoreNames.contains("image")) idbDatabase.createObjectStore("image"); + if (!idbDatabase.objectStoreNames.contains("audio")) idbDatabase.createObjectStore("audio"); + if (!idbDatabase.objectStoreNames.contains("config")) idbDatabase.createObjectStore("config"); + if (!idbDatabase.objectStoreNames.contains("data")) idbDatabase.createObjectStore("data"); + }; + }).then(event => { + lib.db = event.target.result; + return game.getDB("config"); + }).then(object => { + if (!object.storageImported) { + try { + config2 = JSON.parse(localStorage.getItem(`${lib.configprefix}config`)); + if (!config2 || typeof config2 != "object") throw "err"; + } + catch (err) { + config2 = {}; + } + Object.keys(config2).forEach(key => game.saveConfig(key, config2[key])); + Object.keys(lib.mode).forEach(key => { + try { + config2 = JSON.parse(localStorage.getItem(`${lib.configprefix}${key}`)); + if (!config2 || typeof config2 != "object" || get.is.empty(config2)) throw "err"; + } + catch (err) { + config2 = false; + } + localStorage.removeItem(`${lib.configprefix}${key}`); + if (config2) game.putDB("data", key, config2); + }); + game.saveConfig("storageImported", true); + lib.init.background(); + localStorage.removeItem(`${lib.configprefix}config`); + } + else config2 = object; + proceed(config2); + }); + else { + try { + config2 = JSON.parse(localStorage.getItem(lib.configprefix + "config")); + if (!config2 || typeof config2 != "object") throw "err" + } + catch (err) { + config2 = {}; + localStorage.setItem(lib.configprefix + "config", JSON.stringify({})); + } + proceed(config2); + } + } + + static reset() { + if (window.inSplash) return; + if (window.resetExtension) { + if (confirm("游戏似乎未正常载入,有可能因为部分扩展未正常载入,或者因为部分扩展未载入完毕。\n是否禁用扩展并重新打开?")) { + window.resetExtension(); + window.location.reload(); + } + } + else { + if (lib.device) { + if (navigator.notification) { + navigator.notification.confirm( + "游戏似乎未正常载入,是否重置游戏?", + function (index) { + if (index == 2) { + localStorage.removeItem("noname_inited"); + window.location.reload(); + } + else if (index == 3) { + var noname_inited = localStorage.getItem("noname_inited"); + var onlineKey = localStorage.getItem(lib.configprefix + "key"); + localStorage.clear(); + if (noname_inited) { + localStorage.setItem("noname_inited", noname_inited); + } + if (onlineKey) { + localStorage.setItem(lib.configprefix + "key", onlineKey); + } + if (indexedDB) indexedDB.deleteDatabase(lib.configprefix + "data"); + setTimeout(function () { + window.location.reload(); + }, 200); + } + }, + "确认退出", + ["取消", "重新下载", "重置设置"] + ); + } + else { + if (confirm("游戏似乎未正常载入,是否重置游戏?")) { + localStorage.removeItem("noname_inited"); + window.location.reload(); + } + } + } + else { + if (confirm("游戏似乎未正常载入,是否重置游戏?")) { + var onlineKey = localStorage.getItem(lib.configprefix + "key"); + localStorage.clear(); + if (onlineKey) { + localStorage.setItem(lib.configprefix + "key", onlineKey); + } + if (indexedDB) indexedDB.deleteDatabase(lib.configprefix + "data"); + setTimeout(function () { + window.location.reload(); + }, 200); + } + } + } + } + + static onload = gnc.of(function* () { + const libOnload = lib.onload; + delete lib.onload; + while (Array.isArray(libOnload) && libOnload.length) { + const fun = libOnload.shift(); + if (typeof fun != "function") continue; + yield (gnc.is.generatorFunc(fun) ? gnc.of(fun) : fun)(); + } + ui.updated(); + game.documentZoom = game.deviceZoom; + if (game.documentZoom != 1) { + ui.updatez(); + } + ui.background = ui.create.div(".background"); + ui.background.style.backgroundSize = "cover"; + ui.background.style.backgroundPosition = "50% 50%"; + if (lib.config.image_background && lib.config.image_background != "default" && !lib.config.image_background.startsWith("custom_")) { + ui.background.setBackgroundImage("image/background/" + lib.config.image_background + ".jpg"); + if (lib.config.image_background_blur) { + ui.background.style.filter = "blur(8px)"; + ui.background.style.webkitFilter = "blur(8px)"; + ui.background.style.transform = "scale(1.05)"; + } + } + document.documentElement.style.backgroundImage = ""; + document.documentElement.style.backgroundSize = ""; + document.documentElement.style.backgroundPosition = ""; + document.body.insertBefore(ui.background, document.body.firstChild); + document.body.onresize = ui.updatexr; + if (lib.config.touchscreen) { + document.body.addEventListener("touchstart", function (e) { + this.startX = e.touches[0].clientX / game.documentZoom; + this.startY = e.touches[0].clientY / game.documentZoom; + _status.dragged = false; + }); + document.body.addEventListener("touchmove", function (e) { + if (_status.dragged) return; + if (Math.abs(e.touches[0].clientX / game.documentZoom - this.startX) > 10 || + Math.abs(e.touches[0].clientY / game.documentZoom - this.startY) > 10) { + _status.dragged = true; + } + }); + } + + if (lib.config.image_background.startsWith("custom_")) { + ui.background.style.backgroundImage = "none"; + game.getDB("image", lib.config.image_background, function (fileToLoad) { + if (!fileToLoad) return; + var fileReader = new FileReader(); + fileReader.onload = function (fileLoadedEvent) { + var data = fileLoadedEvent.target.result; + ui.background.style.backgroundImage = "url(" + data + ")"; + if (lib.config.image_background_blur) { + ui.background.style.filter = "blur(8px)"; + ui.background.style.webkitFilter = "blur(8px)"; + ui.background.style.transform = "scale(1.05)"; + } + }; + fileReader.readAsDataURL(fileToLoad, "UTF-8"); + }); + } + if (lib.config.card_style == "custom") { + game.getDB("image", "card_style", function (fileToLoad) { + if (!fileToLoad) return; + var fileReader = new FileReader(); + fileReader.onload = function (fileLoadedEvent) { + if (ui.css.card_stylesheet) { + ui.css.card_stylesheet.remove(); + } + ui.css.card_stylesheet = lib.init.sheet(".card:not(*:empty){background-image:url(" + fileLoadedEvent.target.result + ")}"); + }; + fileReader.readAsDataURL(fileToLoad, "UTF-8"); + }); + } + if (lib.config.cardback_style == "custom") { + game.getDB("image", "cardback_style", function (fileToLoad) { + if (!fileToLoad) return; + var fileReader = new FileReader(); + fileReader.onload = function (fileLoadedEvent) { + if (ui.css.cardback_stylesheet) { + ui.css.cardback_stylesheet.remove(); + } + ui.css.cardback_stylesheet = lib.init.sheet(".card:empty,.card.infohidden{background-image:url(" + fileLoadedEvent.target.result + ")}"); + }; + fileReader.readAsDataURL(fileToLoad, "UTF-8"); + }); + game.getDB("image", "cardback_style2", function (fileToLoad) { + if (!fileToLoad) return; + var fileReader = new FileReader(); + fileReader.onload = function (fileLoadedEvent) { + if (ui.css.cardback_stylesheet2) { + ui.css.cardback_stylesheet2.remove(); + } + ui.css.cardback_stylesheet2 = lib.init.sheet(".card.infohidden:not(.infoflip){background-image:url(" + fileLoadedEvent.target.result + ")}"); + }; + fileReader.readAsDataURL(fileToLoad, "UTF-8"); + }); + } + if (lib.config.hp_style == "custom") { + game.getDB("image", "hp_style1", function (fileToLoad) { + if (!fileToLoad) return; + var fileReader = new FileReader(); + fileReader.onload = function (fileLoadedEvent) { + if (ui.css.hp_stylesheet1) { + ui.css.hp_stylesheet1.remove(); + } + ui.css.hp_stylesheet1 = lib.init.sheet(`.hp:not(.text):not(.actcount)[data-condition="high"]>div:not(.lost){background-image:url(${fileLoadedEvent.target.result})}`); + }; + fileReader.readAsDataURL(fileToLoad, "UTF-8"); + }); + game.getDB("image", "hp_style2", function (fileToLoad) { + if (!fileToLoad) return; + var fileReader = new FileReader(); + fileReader.onload = function (fileLoadedEvent) { + if (ui.css.hp_stylesheet2) { + ui.css.hp_stylesheet2.remove(); + } + ui.css.hp_stylesheet2 = lib.init.sheet(`.hp:not(.text):not(.actcount)[data-condition="mid"]>div:not(.lost){background-image:url(${fileLoadedEvent.target.result})}`); + }; + fileReader.readAsDataURL(fileToLoad, "UTF-8"); + }); + game.getDB("image", "hp_style3", function (fileToLoad) { + if (!fileToLoad) return; + var fileReader = new FileReader(); + fileReader.onload = function (fileLoadedEvent) { + if (ui.css.hp_stylesheet3) { + ui.css.hp_stylesheet3.remove(); + } + ui.css.hp_stylesheet3 = lib.init.sheet(`.hp:not(.text):not(.actcount)[data-condition="low"]>div:not(.lost){background-image:url(${fileLoadedEvent.target.result})}`); + }; + fileReader.readAsDataURL(fileToLoad, "UTF-8"); + }); + game.getDB("image", "hp_style4", function (fileToLoad) { + if (!fileToLoad) return; + var fileReader = new FileReader(); + fileReader.onload = function (fileLoadedEvent) { + if (ui.css.hp_stylesheet4) { + ui.css.hp_stylesheet4.remove(); + } + ui.css.hp_stylesheet4 = lib.init.sheet(".hp:not(.text):not(.actcount)>.lost{background-image:url(" + fileLoadedEvent.target.result + ")}"); + }; + fileReader.readAsDataURL(fileToLoad, "UTF-8"); + }); + } + if (lib.config.player_style == "custom") { + ui.css.player_stylesheet = lib.init.sheet("#window .player{background-image:none;background-size:100% 100%;}"); + game.getDB("image", "player_style", function (fileToLoad) { + if (!fileToLoad) return; + var fileReader = new FileReader(); + fileReader.onload = function (fileLoadedEvent) { + if (ui.css.player_stylesheet) { + ui.css.player_stylesheet.remove(); + } + ui.css.player_stylesheet = lib.init.sheet(`#window .player{background-image:url("${fileLoadedEvent.target.result}");background-size:100% 100%;}`); + }; + fileReader.readAsDataURL(fileToLoad, "UTF-8"); + }); + } + if (lib.config.border_style == "custom") { + game.getDB("image", "border_style", function (fileToLoad) { + if (!fileToLoad) return; + var fileReader = new FileReader(); + fileReader.onload = function (fileLoadedEvent) { + if (ui.css.border_stylesheet) { + ui.css.border_stylesheet.remove(); + } + ui.css.border_stylesheet = lib.init.sheet(); + ui.css.border_stylesheet.sheet.insertRule(`#window .player>.framebg{display:block;background-image:url("${fileLoadedEvent.target.result}")}`, 0); + ui.css.border_stylesheet.sheet.insertRule(".player>.count{z-index: 3 !important;border-radius: 2px !important;text-align: center !important;}", 0); + }; + fileReader.readAsDataURL(fileToLoad, "UTF-8"); + }); + } + if (lib.config.control_style == "custom") { + game.getDB("image", "control_style", function (fileToLoad) { + if (!fileToLoad) return; + var fileReader = new FileReader(); + fileReader.onload = function (fileLoadedEvent) { + if (ui.css.control_stylesheet) { + ui.css.control_stylesheet.remove(); + } + ui.css.control_stylesheet = lib.init.sheet(`#window .control,.menubutton:not(.active):not(.highlight):not(.red):not(.blue),#window #system>div>div{background-image:url("${fileLoadedEvent.target.result}")}`); + }; + fileReader.readAsDataURL(fileToLoad, "UTF-8"); + }); + } + if (lib.config.menu_style == "custom") { + game.getDB("image", "menu_style", function (fileToLoad) { + if (!fileToLoad) return; + var fileReader = new FileReader(); + fileReader.onload = function (fileLoadedEvent) { + if (ui.css.menu_stylesheet) { + ui.css.menu_stylesheet.remove(); + } + ui.css.menu_stylesheet = lib.init.sheet(`html #window>.dialog.popped,html .menu,html .menubg{background-image:url("${fileLoadedEvent.target.result}");background-size:cover}`); + }; + fileReader.readAsDataURL(fileToLoad, "UTF-8"); + }); + } + + var proceed2 = gnc.of(function* () { + var mode = lib.imported.mode; + var card = lib.imported.card; + var character = lib.imported.character; + var play = lib.imported.play; + delete window.game; + var i, j, k; + for (i in mode[lib.config.mode].element) { + if (!lib.element[i]) lib.element[i] = []; + for (j in mode[lib.config.mode].element[i]) { + if (j == "init") { + if (!lib.element[i].inits) lib.element[i].inits = []; + lib.element[i].inits.push(mode[lib.config.mode].element[i][j]); + } + else { + lib.element[i][j] = mode[lib.config.mode].element[i][j]; + } + } + } + for (i in mode[lib.config.mode].ai) { + if (typeof mode[lib.config.mode].ai[i] == "object") { + if (ai[i] == undefined) ai[i] = {}; + for (j in mode[lib.config.mode].ai[i]) { + ai[i][j] = mode[lib.config.mode].ai[i][j]; + } + } + else { + ai[i] = mode[lib.config.mode].ai[i]; + } + } + for (i in mode[lib.config.mode].ui) { + if (typeof mode[lib.config.mode].ui[i] == "object") { + if (ui[i] == undefined) ui[i] = {}; + for (j in mode[lib.config.mode].ui[i]) { + ui[i][j] = mode[lib.config.mode].ui[i][j]; + } + } + else { + ui[i] = mode[lib.config.mode].ui[i]; + } + } + for (i in mode[lib.config.mode].game) { + game[i] = mode[lib.config.mode].game[i]; + } + for (i in mode[lib.config.mode].get) { + get[i] = mode[lib.config.mode].get[i]; + } + lib.init.start = mode[lib.config.mode].start; + lib.init.startBefore = mode[lib.config.mode].startBefore; + if (game.onwash) { + lib.onwash.push(game.onwash); + delete game.onwash; + } + if (game.onover) { + lib.onover.push(game.onover); + delete game.onover; + } + lib.config.banned = lib.config[lib.config.mode + "_banned"] || []; + lib.config.bannedcards = lib.config[lib.config.mode + "_bannedcards"] || []; + + lib.rank = window.noname_character_rank; + delete window.noname_character_rank; + for (i in mode[lib.config.mode]) { + if (i == "element") continue; + if (i == "game") continue; + if (i == "ai") continue; + if (i == "ui") continue; + if (i == "get") continue; + if (i == "config") continue; + if (i == "onreinit") continue; + if (i == "start") continue; + if (i == "startBefore") continue; + if (lib[i] == undefined) lib[i] = (Array.isArray(mode[lib.config.mode][i])) ? [] : {}; + for (j in mode[lib.config.mode][i]) { + lib[i][j] = mode[lib.config.mode][i][j]; + } + } + if (typeof mode[lib.config.mode].init == "function") { + mode[lib.config.mode].init(); + } + + var connectCharacterPack = []; + var connectCardPack = []; + for (i in character) { + if (character[i].character) { + const characterPack = lib.characterPack[i]; + if (characterPack) Object.assign(characterPack, character[i].character); + else lib.characterPack[i] = character[i].character; + } + for (j in character[i]) { + if (j == "mode" || j == "forbid") continue; + if (j == "connect") { + connectCharacterPack.push(i); + continue; + } + if (j == "character" && !lib.config.characters.contains(i) && lib.config.mode != "connect") { + if (lib.config.mode == "chess" && get.config("chess_mode") == "leader" && get.config("chess_leader_allcharacter")) { + for (k in character[i][j]) { + lib.hiddenCharacters.push(k); + } + } + else if (lib.config.mode != "boss" || i != "boss") { + continue; + } + } + if (Array.isArray(lib[j]) && Array.isArray(character[i][j])) { + lib[j].addArray(character[i][j]); + continue; + } + for (k in character[i][j]) { + if (j == "character") { + if (!character[i][j][k][4]) { + character[i][j][k][4] = []; + } + if (character[i][j][k][4].contains("boss") || + character[i][j][k][4].contains("hiddenboss")) { + lib.config.forbidai.add(k); + } + if (lib.config.forbidai_user && lib.config.forbidai_user.contains(k)) { + lib.config.forbidai.add(k); + } + for (var l = 0; l < character[i][j][k][3].length; l++) { + lib.skilllist.add(character[i][j][k][3][l]); + } + } + if (j == "skill" && k[0] == "_" && (lib.config.mode != "connect" ? (!lib.config.characters.contains(i)) : (!character[i].connect))) { + continue; + } + if (j == "translate" && k == i) { + lib[j][k + "_character_config"] = character[i][j][k]; + } + else { + if (lib[j][k] == undefined) { + if (j == "skill" && !character[i][j][k].forceLoad && lib.config.mode == "connect" && !character[i].connect) { + lib[j][k] = { + nopop: character[i][j][k].nopop, + derivation: character[i][j][k].derivation + }; + } + else { + Object.defineProperty(lib[j], k, Object.getOwnPropertyDescriptor(character[i][j], k)); + } + if (j == "card" && lib[j][k].derivation) { + if (!lib.cardPack.mode_derivation) { + lib.cardPack.mode_derivation = [k]; + } + else { + lib.cardPack.mode_derivation.push(k); + } + } + } + else if (Array.isArray(lib[j][k]) && Array.isArray(character[i][j][k])) { + lib[j][k].addArray(character[i][j][k]); + } + else { + console.log( + `dublicate ${j} in character ${i}:\n${k}:\nlib.${j}.${k}`, + lib[j][k], + `\ncharacter.${i}.${j}.${k}`, + character[i][j][k] + ); + } + } + } + } + } + var connect_avatar_list = []; + for (var i in lib.character) { + connect_avatar_list.push(i); + } + connect_avatar_list.sort(lib.sort.capt); + for (var i = 0; i < connect_avatar_list.length; i++) { + var ia = connect_avatar_list[i]; + lib.mode.connect.config.connect_avatar.item[ia] = lib.translate[ia]; + } + if (lib.config.mode != "connect") { + var pilecfg = lib.config.customcardpile[get.config("cardpilename") || "当前牌堆"]; + if (pilecfg) { + lib.config.bannedpile = get.copy(pilecfg[0] || {}); + lib.config.addedpile = get.copy(pilecfg[1] || {}); + } + else { + lib.config.bannedpile = {}; + lib.config.addedpile = {}; + } + } + else { + lib.cardPackList = {}; + } + for (i in card) { + const cardPack = lib.cardPack[i] ? lib.cardPack[i] : lib.cardPack[i] = []; + if (card[i].card) { + for (var j in card[i].card) { + if (!card[i].card[j].hidden && card[i].translate[j + "_info"]) { + cardPack.push(j); + } + } + } + for (j in card[i]) { + if (j == "mode" || j == "forbid") continue; + if (j == "connect") { + connectCardPack.push(i); + continue; + } + if (j == "list") { + if (lib.config.mode == "connect") { + const cardPackList = lib.cardPackList[i]; + if (cardPackList) cardPackList.addArray(card[i][j]); + else lib.cardPackList[i] = card[i][j]; + } + else { + if (lib.config.cards.contains(i)) { + var pile; + if (typeof card[i][j] == "function") { + pile = card[i][j](); + } + else { + pile = card[i][j]; + } + const cardPile = lib.cardPile[i]; + if (cardPile) cardPile.addArray(pile); + else lib.cardPile[i] = pile.slice(0); + if (lib.config.bannedpile[i]) { + for (var k = 0; k < lib.config.bannedpile[i].length; k++) { + pile[lib.config.bannedpile[i][k]] = null; + } + } + for (var k = 0; k < pile.length; k++) { + if (!pile[k]) { + pile.splice(k--, 1); + } + } + if (lib.config.addedpile[i]) { + for (var k = 0; k < lib.config.addedpile[i].length; k++) { + pile.push(lib.config.addedpile[i][k]); + } + } + lib.card.list.addArray(pile); + } + } + } + else { + for (k in card[i][j]) { + if (j == "skill" && k[0] == "_" && !card[i][j][k].forceLoad && (lib.config.mode != "connect" ? (!lib.config.cards.contains(i)) : (!card[i].connect))) { + continue; + } + if (j == "translate" && k == i) { + lib[j][k + "_card_config"] = card[i][j][k]; + } + else { + if (lib[j][k] == undefined) { + if (j == "skill" && !card[i][j][k].forceLoad && lib.config.mode == "connect" && !card[i].connect) { + lib[j][k] = { + nopop: card[i][j][k].nopop, + derivation: card[i][j][k].derivation + }; + } + else { + Object.defineProperty(lib[j], k, Object.getOwnPropertyDescriptor(card[i][j], k)); + } + } + else { + console.log( + `dublicate ${j} in card ${i}:\n${k}:\nlib.${j}.${k}`, + lib[j][k], + `\ncard.${i}.${j}.${k}`, + card[i][j][k] + ); + } + if (j == "card" && lib[j][k].derivation) { + if (!lib.cardPack.mode_derivation) { + lib.cardPack.mode_derivation = [k]; + } + else { + lib.cardPack.mode_derivation.push(k); + } + } + } + } + } + } + } + if (lib.cardPack.mode_derivation) { + for (var i = 0; i < lib.cardPack.mode_derivation.length; i++) { + if (typeof lib.card[lib.cardPack.mode_derivation[i]].derivation == "string" && !lib.character[lib.card[lib.cardPack.mode_derivation[i]].derivation]) { + lib.cardPack.mode_derivation.splice(i--, 1); + } + else if (typeof lib.card[lib.cardPack.mode_derivation[i]].derivationpack == "string" && !lib.config.cards.contains(lib.card[lib.cardPack.mode_derivation[i]].derivationpack)) { + lib.cardPack.mode_derivation.splice(i--, 1); + } + } + if (lib.cardPack.mode_derivation.length == 0) { + delete lib.cardPack.mode_derivation; + } + } + if (lib.config.mode != "connect") { + for (i in play) { + if (lib.config.hiddenPlayPack.contains(i)) continue; + if (play[i].forbid && play[i].forbid.contains(lib.config.mode)) continue; + if (play[i].mode && play[i].mode.contains(lib.config.mode) == false) continue; + for (j in play[i].element) { + if (!lib.element[j]) lib.element[j] = []; + for (k in play[i].element[j]) { + if (k == "init") { + if (!lib.element[j].inits) lib.element[j].inits = []; + lib.element[j].inits.push(play[i].element[j][k]); + } + else { + lib.element[j][k] = play[i].element[j][k]; + } + } + } + for (j in play[i].ui) { + if (typeof play[i].ui[j] == "object") { + if (ui[j] == undefined) ui[j] = {}; + for (k in play[i].ui[j]) { + ui[j][k] = play[i].ui[j][k]; + } + } + else { + ui[j] = play[i].ui[j]; + } + } + for (j in play[i].game) { + game[j] = play[i].game[j]; + } + for (j in play[i].get) { + get[j] = play[i].get[j]; + } + for (j in play[i]) { + if (j == "mode" || j == "forbid" || j == "init" || j == "element" || + j == "game" || j == "get" || j == "ui" || j == "arenaReady") continue; + for (k in play[i][j]) { + if (j == "translate" && k == i) { + // lib[j][k+"_play_config"]=play[i][j][k]; + } + else { + if (lib[j][k] != undefined) { + console.log( + `dublicate ${j} in play ${i}:\n${k}:\nlib.${j}.${k}`, + lib[j][k], + `\nplay.${i}.${j}.${k}`, + play[i][j][k] + ); + } + lib[j][k] = play[i][j][k]; + } + } + } + if (typeof play[i].init == "function") play[i].init(); + if (typeof play[i].arenaReady == "function") lib.arenaReady.push(play[i].arenaReady); + } + } + + lib.connectCharacterPack = []; + lib.connectCardPack = []; + for (var i = 0; i < lib.config.all.characters.length; i++) { + var packname = lib.config.all.characters[i]; + if (connectCharacterPack.contains(packname)) { + lib.connectCharacterPack.push(packname) + } + } + for (var i = 0; i < lib.config.all.cards.length; i++) { + var packname = lib.config.all.cards[i]; + if (connectCardPack.contains(packname)) { + lib.connectCardPack.push(packname) + } + } + if (lib.config.mode != "connect") { + for (i = 0; i < lib.card.list.length; i++) { + if (lib.card.list[i][2] == "huosha") { + lib.card.list[i] = lib.card.list[i].slice(0); + lib.card.list[i][2] = "sha"; + lib.card.list[i][3] = "fire"; + } + else if (lib.card.list[i][2] == "leisha") { + lib.card.list[i] = lib.card.list[i].slice(0); + lib.card.list[i][2] = "sha"; + lib.card.list[i][3] = "thunder"; + } + if (!lib.card[lib.card.list[i][2]]) { + lib.card.list.splice(i, 1); i--; + } + else if (lib.card[lib.card.list[i][2]].mode && + lib.card[lib.card.list[i][2]].mode.contains(lib.config.mode) == false) { + lib.card.list.splice(i, 1); i--; + } + } + } + + if (lib.config.mode == "connect") { + _status.connectMode = true; + } + if (window.isNonameServer) { + lib.cheat.i(); + } + else if (lib.config.dev && (!_status.connectMode || lib.config.debug)) { + lib.cheat.i(); + } + lib.config.sort_card = get.sortCard(lib.config.sort); + delete lib.imported.character; + delete lib.imported.card; + delete lib.imported.mode; + delete lib.imported.play; + for (var i in lib.init) { + if (i.startsWith("setMode_")) { + delete lib.init[i]; + } + } + if (!_status.connectMode) { + for (var i = 0; i < lib.extensions.length; i++) { + try { + _status.extension = lib.extensions[i][0]; + _status.evaluatingExtension = lib.extensions[i][3]; + if (typeof lib.extensions[i][1] == "function") + yield (gnc.is.coroutine(lib.extensions[i][1]) ? gnc.of(lib.extensions[i][1]) : lib.extensions[i][1]).call(lib.extensions[i], lib.extensions[i][2], lib.extensions[i][4]); + if (lib.extensions[i][4]) { + if (lib.extensions[i][4].character) { + for (var j in lib.extensions[i][4].character.character) { + game.addCharacterPack(get.copy(lib.extensions[i][4].character)); + break; + } + } + if (lib.extensions[i][4].card) { + for (var j in lib.extensions[i][4].card.card) { + game.addCardPack(get.copy(lib.extensions[i][4].card)); + break; + } + } + if (lib.extensions[i][4].skill) { + for (var j in lib.extensions[i][4].skill.skill) { + game.addSkill(j, lib.extensions[i][4].skill.skill[j], + lib.extensions[i][4].skill.translate[j], + lib.extensions[i][4].skill.translate[j + "_info"], + lib.extensions[i][4].skill.translate[j + "_append"], + lib.extensions[i][4].skill.translate[j + "_ab"]); + } + } + } + delete _status.extension; + delete _status.evaluatingExtension; + } + catch (e) { + console.log(e); + } + } + } + delete lib.extensions; + + if (lib.init.startBefore) { + lib.init.startBefore(); + delete lib.init.startBefore; + } + ui.create.arena(); + game.createEvent("game", false).setContent(lib.init.start); + if (lib.mode[lib.config.mode] && lib.mode[lib.config.mode].fromextension) { + var startstr = mode[lib.config.mode].start.toString(); + if (startstr.indexOf("onfree") == -1) { + setTimeout(lib.init.onfree, 500); + } + } + delete lib.init.start; + if (Array.isArray(_status.onprepare) && _status.onprepare.length) { + yield Promise.allSettled(_status.onprepare); + delete _status.onprepare; + } + game.loop(); + }) + var proceed = gnc.of(function* () { + if (!lib.db) { + try { + lib.storage = JSON.parse(localStorage.getItem(lib.configprefix + lib.config.mode)); + if (typeof lib.storage != "object") throw ("err"); + if (lib.storage == null) throw ("err"); + } + catch (err) { + lib.storage = {}; + localStorage.setItem(lib.configprefix + lib.config.mode, "{}"); + } + yield proceed2(); + } + else { + game.getDB("data", lib.config.mode, function (obj) { + lib.storage = obj || {}; + proceed2(); + }); + } + }); + if (!lib.imported.mode || !lib.imported.mode[lib.config.mode]) { + window.inSplash = true; + clearTimeout(window.resetGameTimeout); + delete window.resetGameTimeout; + var clickedNode = false; + var clickNode = function () { + if (clickedNode) return; + this.classList.add("clicked"); + clickedNode = true; + lib.config.mode = this.link; + game.saveConfig("mode", this.link); + if (this.link == "connect") { + localStorage.setItem(lib.configprefix + "directstart", true); + game.reload(); + } + else { + if (game.layout != "mobile" && lib.layoutfixed.indexOf(lib.config.mode) !== -1) { + game.layout = "mobile"; + ui.css.layout.href = lib.assetURL + "layout/" + game.layout + "/layout.css"; + } + else if (game.layout == "mobile" && lib.config.layout != "mobile" && lib.layoutfixed.indexOf(lib.config.mode) === -1) { + game.layout = lib.config.layout; + if (game.layout == "default") { + ui.css.layout.href = ""; + } + else { + ui.css.layout.href = lib.assetURL + "layout/" + game.layout + "/layout.css"; + } + } + splash.delete(1000); + delete window.inSplash; + window.resetGameTimeout = setTimeout(lib.init.reset, 10000); + + this.listenTransition(function () { + lib.init.js(lib.assetURL + "mode", lib.config.mode, proceed); + }, 500); + } + } + var downNode = function () { + this.classList.add("glow"); + } + var upNode = function () { + this.classList.remove("glow"); + } + var splash = ui.create.div("#splash", document.body); + if (lib.config.touchscreen) { + splash.classList.add("touch"); + lib.setScroll(splash); + } + if (lib.config.player_border != "wide") { + splash.classList.add("slim"); + } + splash.dataset.radius_size = lib.config.radius_size; + for (var i = 0; i < lib.config.all.mode.length; i++) { + var node = ui.create.div(".hidden", splash, clickNode); + node.link = lib.config.all.mode[i]; + ui.create.div(node, ".splashtext", get.verticalStr(get.translation(lib.config.all.mode[i]))); + if (lib.config.all.stockmode.includes(lib.config.all.mode[i])) { + // 初始启动页设置 + if (lib.config.splash_style == undefined) game.saveConfig("splash_style", "style1"); + splash.dataset.splash_style = lib.config.splash_style; + // 扩展可通过window.splashurl设置素材读取路径 + if (window.splashurl == undefined) window.splashurl = "image/splash/"; + if (lib.config.splash_style == "style1" || lib.config.splash_style == "style2") { + ui.create.div(node, ".avatar").setBackgroundImage("image/splash/" + lib.config.splash_style + "/" + lib.config.all.mode[i] + ".jpg"); + } else { + ui.create.div(node, ".avatar").setBackgroundImage(splashurl + lib.config.splash_style + "/" + lib.config.all.mode[i] + ".jpg"); + } + } + else { + var avatarnode = ui.create.div(node, ".avatar"); + var avatarbg = lib.mode[lib.config.all.mode[i]].splash; + if (avatarbg.startsWith("ext:")) { + avatarnode.setBackgroundImage(avatarbg.replace(/^ext:/, "extension/")); + } + else { + avatarnode.setBackgroundDB(avatarbg); + } + } + if (!lib.config.touchscreen) { + node.addEventListener("mousedown", downNode); + node.addEventListener("mouseup", upNode); + node.addEventListener("mouseleave", upNode); + } + setTimeout((function (node) { + return function () { + node.show(); + } + }(node)), i * 100); + } + if (lib.config.mousewheel) { + splash.onmousewheel = ui.click.mousewheel; + } + } + else { + yield proceed(); + } + localStorage.removeItem(lib.configprefix + "directstart"); + delete lib.init.init; + const libOnload2 = lib.onload2; + delete lib.onload2; + while (Array.isArray(libOnload2) && libOnload2.length) { + const fun = libOnload2.shift(); + if (typeof fun != "function") continue; + yield (gnc.is.generatorFunc(fun) ? gnc.of(fun) : fun)(); + } + }) + + static startOnline() { + "step 0" + event._resultid = null; + event._result = null; + game.pause(); + "step 1" + if (result) { + if (event._resultid) { + result.id = event._resultid; + } + game.send("result", result); + } + event.goto(0); + } + + static onfree() { + if (lib.onfree) { + clearTimeout(window.resetGameTimeout); + delete window.resetGameTimeout; + if (!game.syncMenu) { + delete window.resetExtension; + localStorage.removeItem(lib.configprefix + "disable_extension"); + } + + if (game.removeFile && lib.config.brokenFile.length) { + while (lib.config.brokenFile.length) { + game.removeFile(lib.config.brokenFile.shift()); + } + game.saveConfigValue("brokenFile"); + } + + var onfree = lib.onfree; + delete lib.onfree; + var loop = function () { + if (onfree.length) { + (onfree.shift())(); + setTimeout(loop, 100); + } + }; + setTimeout(loop, 500); + if (!_status.new_tutorial) game.saveConfig("menu_loadondemand", true, lib.config.mode); + } + } + + static connection(ws) { + const client = new lib.element.Client(ws); + lib.node.clients.push(client); + if (window.isNonameServer) { + document.querySelector("#server_count").innerHTML = lib.node.clients.length; + } + ws.on("message", function (messagestr) { + var message; + try { + message = JSON.parse(messagestr); + if (!Array.isArray(message) || + typeof lib.message.server[message[0]] !== "function") { + throw ("err"); + } + for (var i = 1; i < message.length; i++) { + message[i] = get.parsedResult(message[i]); + } + } + catch (e) { + console.log(e); + console.log("invalid message: " + messagestr); + return; + } + lib.message.server[message.shift()].apply(client, message); + }); + ws.on("close", function () { + client.close(); + }); + client.send("opened"); + } + + static sheet() { + var style = document.createElement("style"); + document.head.appendChild(style); + for (var i = 0; i < arguments.length; i++) { + if (typeof arguments[i] == "string") { + style.sheet.insertRule(arguments[i], 0); + } + } + return style; + } + + static css(path, file, before) { + const style = document.createElement("link"); + style.rel = "stylesheet"; + if (path) { + if (path[path.length - 1] == "/") path = path.slice(0, path.length - 1); + if (file) path = `${path}${/^db:extension-[^:]*$/.test(path) ? ":" : "/"}${file}.css`; + (path.startsWith("db:") ? game.getDB("image", path.slice(3)).then(get.objectURL) : new Promise(resolve => resolve(path))).then(resolvedPath => { + style.href = resolvedPath; + if (typeof before == "function") { + style.addEventListener("load", before); + document.head.appendChild(style); + } + else if (before) document.head.insertBefore(style, before); + else document.head.appendChild(style); + }); + } + return style; + } + + /** + * 在扩展的precontent中调用,用于加载扩展必需的JS文件。 + * If any of the parameters is an Array, corresponding files will be loaded in order + * 如果任意参数为数组,则按顺序加载加载相应的文件 + */ + static jsForExtension(path, file, onLoad, onError) { + if (!_status.javaScriptExtensions) _status.javaScriptExtensions = []; + _status.javaScriptExtensions.push({ + path: path, + file: file, + onLoad: onLoad, + onError: onError + }); + } + + static js(path, file, onLoad, onError) { + if (path[path.length - 1] == "/") path = path.slice(0, path.length - 1); + if (path == `${lib.assetURL}mode` && lib.config.all.stockmode.indexOf(file) == -1) { + lib.genAwait(lib.init[`setMode_${file}`]()).then(onLoad); + return; + } + if (Array.isArray(file)) { + file.forEach(value => lib.init.js(path, value, onLoad, onError)); + return; + } + let scriptSource = file ? `${path}${/^db:extension-[^:]*$/.test(path) ? ":" : "/"}${file}.js` : path; + if (path.startsWith("http")) scriptSource += `?rand=${get.id()}`; + else if (lib.config.fuck_sojson && scriptSource.includes("extension") != -1 && scriptSource.startsWith(lib.assetURL)) { + const pathToRead = scriptSource.slice(lib.assetURL.length); + const alertMessage = `检测到您安装了使用免费版sojson进行加密的扩展。请谨慎使用这些扩展,避免游戏数据遭到破坏。\n扩展文件:${pathToRead}`; + if (typeof game.readFileAsText == "function") game.readFileAsText(pathToRead, result => { + if (result.includes("sojson") || result.includes("jsjiami") || result.includes("var _0x")) alert(alertMessage); + }, () => void 0); + else if (location.origin != "file://") lib.init.reqSync(pathToRead, function () { + const result = this.responseText; + if (result.includes("sojson") || result.includes("jsjiami") || result.includes("var _0x")) alert(alertMessage); + }, () => void 0); + } + const script = document.createElement("script"); + (scriptSource.startsWith("db:") ? game.getDB("image", scriptSource.slice(3)).then(get.objectURL) : new Promise(resolve => resolve(scriptSource))).then(resolvedScriptSource => { + script.src = resolvedScriptSource; + if (path.startsWith("http")) script.addEventListener("load", () => script.remove()); + document.head.appendChild(script); + if (typeof onLoad == "function") script.addEventListener("load", onLoad); + if (typeof onError == "function") script.addEventListener("error", onError); + }); + return script; + } + + /** + * 同步lib.init.js + * @returns { void } + */ + static jsSync(path, file, onLoad, onError) { + if (lib.assetURL.length == 0 && location.origin == "file://" && typeof game.readFile == "undefined") { + const e = new Error("浏览器file协议下无法使用此api,请在http/https协议下使用此api"); + if (typeof onError == "function") onError(e); + else throw e; + return; + } + if (path[path.length - 1] == "/") path = path.slice(0, path.length - 1); + if (path == `${lib.assetURL}mode` && lib.config.all.stockmode.indexOf(file) == -1) { + lib.genAwait(lib.init[`setMode_${file}`]()).then(onLoad); + return; + } + if (Array.isArray(file)) { + return file.forEach(value => lib.init.jsSync(path, value, onLoad, onError)); + } + let scriptSource; + if (!file) scriptSource = path; + else scriptSource = `${path}/${file}.js`; + if (path.startsWith("http")) scriptSource += `?rand=${get.id()}`; + const xmlHttpRequest = new XMLHttpRequest(); + let data; + xmlHttpRequest.addEventListener("load", () => { + data = xmlHttpRequest.responseText; + if (!data) { + if (typeof onError == "function") onError(new Error(`${scriptSource}加载失败!`)); + return; + } + if (lib.config.fuck_sojson && scriptSource.includes("extension") != -1 && scriptSource.startsWith(lib.assetURL)) { + const pathToRead = scriptSource.slice(lib.assetURL.length); + if (data.includes("sojson") || data.includes("jsjiami") || data.includes("var _0x")) alert(`检测到您安装了使用免费版sojson进行加密的扩展。请谨慎使用这些扩展,避免游戏数据遭到破坏。\n扩展文件:${pathToRead}`); + } + try { + window.eval(data); + if (typeof onLoad == "function") onLoad(); + } + catch (error) { + if (typeof onError == "function") onError(error); + } + }); + if (typeof onError == "function") xmlHttpRequest.addEventListener("error", onError); + xmlHttpRequest.open("GET", scriptSource, false); + xmlHttpRequest.send(); + } + + static req(str, onload, onerror, master) { + let sScriptURL; + if (str.startsWith("http")) sScriptURL = str; + else if (str.startsWith("local:")) { + if (lib.assetURL.length == 0 && location.origin == "file://" && typeof game.readFile == "undefined") { + const e = new Error("浏览器file协议下无法使用此api,请在http/https协议下使用此api"); + if (typeof onerror == "function") onerror(e); + else throw e; + return; + } + sScriptURL = lib.assetURL + str.slice(6); + } + else { + let url = get.url(master); + if (url[url.length - 1] != "/") url += "/"; + sScriptURL = url + str; + } + const oReq = new XMLHttpRequest(); + if (typeof onload == "function") oReq.addEventListener("load", onload); + if (typeof onerror == "function") oReq.addEventListener("error", onerror); + oReq.open("GET", sScriptURL); + oReq.send(); + } + + /** + * 同步lib.init.req + */ + static reqSync(str, onload, onerror, master) { + let sScriptURL; + if (str.startsWith("http")) sScriptURL = str; + else if (str.startsWith("local:")) { + if (lib.assetURL.length == 0 && location.origin == "file://" && typeof game.readFile == "undefined") { + const e = new Error("浏览器file协议下无法使用此api,请在http/https协议下使用此api"); + if (typeof onerror == "function") onerror(e); + else throw e; + return; + } + sScriptURL = lib.assetURL + str.slice(6); + } + else { + let url = get.url(master); + if (url[url.length - 1] != "/") url += "/"; + sScriptURL = url + str; + } + const oReq = new XMLHttpRequest(); + if (typeof onload == "function") oReq.addEventListener("load", onload); + if (typeof onerror == "function") oReq.addEventListener("error", onerror); + oReq.open("GET", sScriptURL, false); + oReq.send(); + if (typeof onload !== "function") return oReq.responseText; + } + + static json(url, onload, onerror) { + const oReq = new XMLHttpRequest(); + if (typeof onload == "function") oReq.addEventListener("load", () => { + let result; + try { + result = JSON.parse(oReq.responseText); + if (!result) throw ("err"); + } + catch (e) { + if (typeof onerror == "function") onerror(e); + return; + } + onload(result); + }); + if (typeof onerror == "function") oReq.addEventListener("error", onerror); + oReq.open("GET", url); + oReq.send(); + } + + /** + * 同步lib.init.json + */ + static jsonSync(url, onload, onerror) { + if (lib.assetURL.length == 0 && location.origin == "file://" && typeof game.readFile == "undefined") { + const e = new Error("浏览器file协议下无法使用此api,请在http/https协议下使用此api"); + if (typeof onerror == "function") onerror(e); + else throw e; + return; + } + const oReq = new XMLHttpRequest(); + if (typeof onload == "function") oReq.addEventListener("load", () => { + let result; + try { + result = JSON.parse(oReq.responseText); + if (!result) throw ("err"); + } + catch (e) { + if (typeof onerror == "function") onerror(e); + return; + } + onload(result); + }); + if (typeof onerror == "function") oReq.addEventListener("error", onerror); + oReq.open("GET", url, false); + oReq.send(); + } + + static cssstyles() { + if (ui.css.styles) { + ui.css.styles.remove(); + } + ui.css.styles = lib.init.sheet(); + ui.css.styles.sheet.insertRule("#arena .player>.name,#arena .button.character>.name {font-family: " + (lib.config.name_font || "xinwei") + ",xinwei}", 0); + ui.css.styles.sheet.insertRule("#arena .player>.name,.button.character>.name {font-family: " + (lib.config.name_font || "xinwei") + ",xinwei}", 0); + ui.css.styles.sheet.insertRule("#arena .player .identity>div {font-family: " + (lib.config.identity_font || "huangcao") + ",xinwei}", 0); + ui.css.styles.sheet.insertRule(".button.character.newstyle>.identity {font-family: " + (lib.config.identity_font || "huangcao") + ",xinwei}", 0); + if (lib.config.cardtext_font && lib.config.cardtext_font != "default") { + ui.css.styles.sheet.insertRule(".card div:not(.info):not(.background) {font-family: " + lib.config.cardtext_font + ";}", 0); + } + if (lib.config.global_font && lib.config.global_font != "default") { + ui.css.styles.sheet.insertRule("#window {font-family: " + lib.config.global_font + ",xinwei}", 0); + ui.css.styles.sheet.insertRule("#window #control{font-family: STHeiti,SimHei,Microsoft JhengHei,Microsoft YaHei,WenQuanYi Micro Hei,Suits,Helvetica,Arial,sans-serif}", 0); + } + switch (lib.config.glow_phase) { + case "yellow": ui.css.styles.sheet.insertRule("#arena .player:not(.selectable):not(.selected).glow_phase {box-shadow: rgba(0, 0, 0, 0.3) 0 0 0 1px, rgb(217, 152, 62) 0 0 15px, rgb(217, 152, 62) 0 0 15px !important;}", 0); break; + case "green": ui.css.styles.sheet.insertRule("#arena .player:not(.selectable):not(.selected).glow_phase {box-shadow: rgba(0, 0, 0, 0.3) 0 0 0 1px, rgba(10, 155, 67, 1) 0 0 15px, rgba(10, 155, 67, 1) 0 0 15px !important;}", 0); break; + case "purple": ui.css.styles.sheet.insertRule("#arena .player:not(.selectable):not(.selected).glow_phase {box-shadow: rgba(0, 0, 0, 0.3) 0 0 0 1px, rgb(189, 62, 170) 0 0 15px, rgb(189, 62, 170) 0 0 15px !important;}", 0); break; + } + } + + static layout(layout, nosave) { + const loadingScreen = ui.create.div(".loading-screen", document.body), loadingScreenStyle = loadingScreen.style; + loadingScreenStyle.animationDuration = "1s"; + loadingScreenStyle.animationFillMode = "forwards"; + loadingScreenStyle.animationName = "opacity-0-1"; + if (layout == "default") layout = "mobile"; + if (!nosave) game.saveConfig("layout", layout); + game.layout = layout; + ui.arena.hide(); + new Promise(resolve => setTimeout(resolve, 500)).then(() => { + if (game.layout == "default") { + ui.css.layout.href = ""; + } + else { + ui.css.layout.href = lib.assetURL + "layout/" + game.layout + "/layout.css"; + } + if (game.layout == "mobile" || game.layout == "long") { + ui.arena.classList.add("mobile"); + } + else { + ui.arena.classList.remove("mobile"); + } + if (game.layout == "mobile" || game.layout == "long" || game.layout == "long2" || game.layout == "nova") { + if (game.me && game.me.node.handcards2.childNodes.length) { + while (game.me.node.handcards2.childNodes.length) { + game.me.node.handcards1.appendChild(game.me.node.handcards2.firstChild); + } + } + } + if (game.layout == "default") { + ui.arena.classList.add("oldlayout"); + } + else { + ui.arena.classList.remove("oldlayout"); + } + if (lib.config.cardshape == "oblong" && (game.layout == "long" || game.layout == "mobile" || game.layout == "long2" || game.layout == "nova")) { + ui.arena.classList.add("oblongcard"); + ui.window.classList.add("oblongcard"); + } + else { + ui.arena.classList.remove("oblongcard"); + ui.window.classList.remove("oblongcard"); + } + //if(lib.config.textequip=="text"&&(game.layout=="long"||game.layout=="mobile")){ + if (game.layout == "long" || game.layout == "mobile") { + ui.arena.classList.add("textequip"); + } + else { + ui.arena.classList.remove("textequip"); + } + if (get.is.phoneLayout()) { + ui.css.phone.href = lib.assetURL + "layout/default/phone.css"; + ui.arena.classList.add("phone"); + } + else { + ui.css.phone.href = ""; + ui.arena.classList.remove("phone"); + } + for (var i = 0; i < game.players.length; i++) { + if (get.is.linked2(game.players[i])) { + if (game.players[i].classList.contains("linked")) { + game.players[i].classList.remove("linked"); + game.players[i].classList.add("linked2"); + } + } + else { + if (game.players[i].classList.contains("linked2")) { + game.players[i].classList.remove("linked2"); + game.players[i].classList.add("linked"); + } + } + } + if (game.layout == "long" || game.layout == "long2") { + ui.arena.classList.add("long"); + } + else { + ui.arena.classList.remove("long"); + } + if (lib.config.player_border != "wide" || game.layout == "long" || game.layout == "long2") { + ui.arena.classList.add("slim_player"); + } + else { + ui.arena.classList.remove("slim_player"); + } + if (lib.config.player_border == "normal" && lib.config.mode != "brawl" && (game.layout == "long" || game.layout == "long2")) { + ui.arena.classList.add("lslim_player"); + } + else { + ui.arena.classList.remove("lslim_player"); + } + if (lib.config.player_border == "slim") { + ui.arena.classList.add("uslim_player"); + } + else { + ui.arena.classList.remove("uslim_player"); + } + if (lib.config.player_border == "narrow") { + ui.arena.classList.add("mslim_player"); + } + else { + ui.arena.classList.remove("mslim_player"); + } + ui.updatej(); + ui.updatem(); + return new Promise(resolve => setTimeout(resolve, 100)); + }).then(() => { + ui.arena.show(); + if (game.me) game.me.update(); + return new Promise(resolve => setTimeout(resolve, 500)); + }).then(() => { + ui.updatex(); + ui.updatePlayerPositions(); + return new Promise(resolve => setTimeout(resolve, 500)); + }).then(() => { + ui.updatec(); + loadingScreenStyle.animationName = "opacity-1-0"; + loadingScreen.addEventListener("animationend", animationEvent => animationEvent.target.remove()); + }); + } + + static background() { + if (lib.config.image_background_random) { + var list = []; + for (var i in lib.configMenu.appearence.config.image_background.item) { + if (i == "default") continue; + list.push(i); + } + list.remove(lib.config.image_background); + localStorage.setItem(lib.configprefix + "background", JSON.stringify(list)); + } + else if (lib.config.image_background && lib.config.image_background != "default" && !lib.config.image_background.startsWith("custom_")) { + localStorage.setItem(lib.configprefix + "background", lib.config.image_background); + } + else if (lib.config.image_background == "default" && lib.config.theme == "simple") { + localStorage.setItem(lib.configprefix + "background", "ol_bg"); + } + else { + localStorage.removeItem(lib.configprefix + "background"); + } + } + + /** + * + * @param {*} item + * @param {Function} [scope] 作用域 + * @returns + */ + static parsex(item, scope) { + //by 诗笺、Tipx-L + /** + * @param {Function} func + */ + function Legacy(func) { + //Remove all comments + //移除所有注释 + let str = func.toString().replace(/((?:(?:^[ \t]*)?(?:\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/(?:[ \t]*\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/)))?|\/\/(?:[^\\]|\\(?:\r?\n)?)*?(?:\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/))|(?=\r?\n))))+)|("(?:\\[\s\S]|[^"\\])*"|"(?:\\[\s\S]|[^"\\])*"|(?:\r?\n|[\s\S])[^/""\\\s]*)/mg, "$2").trim(); + //获取第一个 { 后的所有字符 + str = str.slice(str.indexOf("{") + 1); + //判断代码中是否有debugger + let regex = /event\.debugger\(\)/; + let hasDebugger = false; + let insertDebugger = `yield code=>eval(code);`; + let debuggerSkip = 0; + let debuggerResult; + while ((debuggerResult = str.slice(debuggerSkip).match(regex)) != null) { + let debuggerCopy = str; + debuggerCopy = debuggerCopy.slice(0, debuggerSkip + debuggerResult.index) + insertDebugger + debuggerCopy.slice(debuggerSkip + debuggerResult.index + debuggerResult[0].length, -1); + //测试是否有错误 + try { + new GeneratorFunction(debuggerCopy); + str = debuggerCopy + "}"; + debuggerSkip += debuggerResult.index + insertDebugger.length; + hasDebugger = true; + } catch (error) { + debuggerSkip += debuggerResult.index + debuggerResult[0].length; + } + } + //func中要写步骤的话,必须要写step 0 + if (str.indexOf("step 0") == -1) { + str = "{if(event.step==1) {event.finish();return;}\n" + str; + } else { + let skip = 0; + let k = 0; + let result; + //去除99个step的限制 + while ((result = str.slice(skip).match(new RegExp(`[""]step ${k}[""]`))) != null) { + let insertStr; + if (k == 0) { + insertStr = `switch(step){case 0:`; + } else { + insertStr = `break;case ${k}:`; + } + let copy = str; + copy = copy.slice(0, skip + result.index) + insertStr + copy.slice(skip + result.index + result[0].length); + //测试是否有错误 + try { + new (hasDebugger ? GeneratorFunction : Function)(copy); + str = copy; + skip += result.index + insertStr.length; + } catch (error) { + k--; + skip += result.index + result[0].length; + } + k++; + } + str = `if(event.step==${k}){event.finish();return;}` + str; + } + if (!scope) { + return (new (hasDebugger ? GeneratorFunction : Function)("event", "step", "source", "player", "target", "targets", + "card", "cards", "skill", "forced", "num", "trigger", "result", + "_status", "lib", "game", "ui", "get", "ai", str)); + } else { + return scope(`function${hasDebugger ? "*" : ""} anonymous(event,step,source,player,target,targets, + card,cards,skill,forced,num,trigger,result, + _status,lib,game,ui,get,ai){${str}}; anonymous;`); + } + } + switch (typeof item) { + case "object": + if (Array.isArray(item)) { + let lastEvent = null; + return function* (event, step, source, player, target, targets, card, cards, skill, forced, num, trigger, result, _status, lib, game, ui, get, ai) { + if (step >= item.length) return event.finish(); + var current = item[step]; + if (typeof current != "function") throw new Error(`content ${step} of ${event.name} is not vaild: ${current}`); + var currentResult = current(event, { + event: event, + step: step, + source: source, + player: player, + target: target, + targets: targets, + card: card, + cards: cards, + skill: skill, + forced: forced, + num: num, + trigger: trigger, + result: result + }, (lastEvent && ("result" in lastEvent)) ? lastEvent.result : null); + // TODO: use `event.debugger` to replace source + if (gnc.is.generator(currentResult)) lastEvent = yield* currentResult; + else lastEvent = currentResult; + } + } + else { + if (Symbol.iterator in item) return lib.init.parsex(Array.from(item)); + if (item.toString !== Object.prototype.toString) return lib.init.parsex(item.toString()); + if ("render" in item) { + // TODO: Object Render Parse + throw new Error("NYI: Object Render Parse"); + } + // TODO: Object Other Parse + throw new Error("NYI: Object Other Parse"); + } + case "function": + if (gnc.is.generatorFunc(item)) { + let gen, lastEvent; + return function* (event, step, source, player, target, targets, card, cards, skill, forced, num, trigger, result, _status, lib, game, ui, get, ai) { + event.step = NaN; + if (!gen) gen = item(event, { + event: event, + step: step, + source: source, + player: player, + target: target, + targets: targets, + card: card, + cards: cards, + skill: skill, + forced: forced, + num: num, + trigger: trigger, + result: result + }); + var res = gen.next((lastEvent && ("result" in lastEvent)) ? lastEvent.result : null); + if (res.done) return event.finish(); + var currentResult = res.value; + // TODO: use `event.debugger` to replace source + if (typeof currentResult == "function") yield currentResult; + else { + if (Array.isArray(currentResult)) { + event.step = currentResult[1]; + currentResult = currentResult[0]; + } + lastEvent = currentResult; + } + } + } else if (item._parsed) return item; + // falls through + default: + return Legacy(item); + } + } + + static eval(func) { + if (typeof func == "function") { + return eval("(" + func.toString() + ")"); + } + else if (typeof func == "object") { + for (var i in func) { + if (Object.prototype.hasOwnProperty.call(func, i)) { + func[i] = lib.init.eval(func[i]); + } + } + } + return func; + } + + static encode(strUni) { + var strUtf = strUni.replace( + /[\u0080-\u07ff]/g, function (c) { + var cc = c.charCodeAt(0); + return String.fromCharCode(0xc0 | cc >> 6, 0x80 | cc & 0x3f); + }); + strUtf = strUtf.replace( + /[\u0800-\uffff]/g, function (c) { + var cc = c.charCodeAt(0); + return String.fromCharCode(0xe0 | cc >> 12, 0x80 | cc >> 6 & 0x3F, 0x80 | cc & 0x3f); + }); + return btoa(strUtf); + } + + static decode(str) { + var strUtf = atob(str); + var strUni = strUtf.replace( + /[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, function (c) { + var cc = ((c.charCodeAt(0) & 0x0f) << 12) | ((c.charCodeAt(1) & 0x3f) << 6) | (c.charCodeAt(2) & 0x3f); + return String.fromCharCode(cc); + }); + strUni = strUni.replace( + /[\u00c0-\u00df][\u0080-\u00bf]/g, function (c) { + var cc = (c.charCodeAt(0) & 0x1f) << 6 | c.charCodeAt(1) & 0x3f; + return String.fromCharCode(cc); + }); + return strUni; + } + + static stringify(obj) { + var str = "{" + for (var i in obj) { + str += `"${i}":` + if (Object.prototype.toString.call(obj[i]) == "[object Object]") { + str += lib.init.stringify(obj[i]); + } + else if (typeof obj[i] == "function") { + str += obj[i].toString(); + } + else { + str += JSON.stringify(obj[i]); + } + str += "," + } + str += "}"; + return str; + } + + static stringifySkill(obj) { + var str = ""; + for (var i in obj) { + str += i + ":" + if (Object.prototype.toString.call(obj[i]) == "[object Object]") { + str += "{\n" + lib.init.stringifySkill(obj[i]) + "}"; + } + else if (typeof obj[i] == "function") { + str += obj[i].toString().replace(/\t/g, ""); + } + else { + str += JSON.stringify(obj[i]); + } + str += ",\n" + } + return str; + } +} diff --git a/noname/library/initialization/promises.js b/noname/library/initialization/promises.js new file mode 100644 index 000000000..e99d29bba --- /dev/null +++ b/noname/library/initialization/promises.js @@ -0,0 +1,71 @@ +import { Initialization } from "../initialization.js"; + +/** + * 部分函数的Promise版本 + */ +export class Promises { + constructor() { + throw new TypeError(`${new.target.name} is not a constructor`); + } + + /** + * Promise版的`Initialization.js` + * + * @param {string} path - 文件路径 + * @param {string | string[]} [file] - 文件名或文件名组,忽略则直接读取`path`的内容 + * @returns {Promise} + */ + js(path, file) { + return new Promise((resolve, reject) => Initialization.js(path, file, resolve, reject)); + } + + /** + * Promise版的`Initialization.css` + * + * @param {string} path - 文件路径 + * @param {string | string[]} [file] - 文件名或文件名组,忽略则直接读取`path`的内容 + * @param {Element} [before] 新样式dom的位置 + * @returns {Promise} + */ + css(path, file, before) { + return new Promise((resolve, reject) => { + const style = Initialization.css(path, file, before); + style.addEventListener("load", () => resolve(style)); + style.addEventListener("error", reject); + }); + } + + /** + * Promise版的`Initialization.req` + * + * @param {string} str - 要读取的地址 + * @param {string} [master] + * @returns {Promise} + */ + req(str, master) { + return new Promise((resolve, reject) => Initialization.req(str, resolve, reject, master)); + } + + /** + * Promise版的`Initialization.json` + * + * @param {string} url - 要读取的地址 + * @returns {Promise} + */ + json(url) { + return new Promise((resolve, reject) => Initialization.json(url, resolve, reject)); + } + + /** + * Promise版的`Initialization.sheet` + * + * @returns {Promise} + */ + sheet() { + return new Promise((resolve, reject) => { + const style = Initialization.sheet(...arguments); + style.addEventListener("load", () => resolve(style)); + style.addEventListener("error", reject); + }); + } +} \ No newline at end of file diff --git a/noname/library/internal-status.js b/noname/library/internal-status.js new file mode 100644 index 000000000..15b2aff0b --- /dev/null +++ b/noname/library/internal-status.js @@ -0,0 +1,10 @@ +export const internalStatus = { + running: false, + canvas: false, + time: 0, + reload: 0, + delayed: 0, + frameId: 0, + videoId: 0, + globalId: 0 +}; diff --git a/noname/library/linq.js b/noname/library/linq.js new file mode 100644 index 000000000..a9f50a449 --- /dev/null +++ b/noname/library/linq.js @@ -0,0 +1,106 @@ +import { Creation } from "./creation.js"; + +export const linq = { + cselector: { + hasAttr: name => `[${name}]`, + isAttr: (name, item) => `[${name}=${item}]`, + inAttr: (name, item) => `[${name}~=${item}]`, + conAttr: (name, item) => `[${name}*=${item}]`, + onAttr: (name, item) => `[${name}|=${item}]`, + bgnAttr: (name, item) => `[${name}^=${item}]`, + endAttr: (name, item) => `[${name}^=${item}]`, + merge: function () { return Array.from(arguments).join(" "); }, + of: function () { return Array.from(arguments).join(""); }, + class: function () { return `.${Array.from(arguments).join(".")}`; }, + group: function () { return Array.from(arguments).join(","); }, + media: type => `@media ${type}` + }, + dom: { + attributes: { + style(name, value) { + return { + _type: "style", + name: name, + value: value + } + } + }, + inject(element, options) { + //处理id和class + if (options.identity) { + for (const item of options.identity) { + if (item.startsWith("#")) element.id = item.slice(1); + else element.classList.add(item); + } + } + //处理属性 + if (options.attributes) { + for (const item in options.attributes) element.setAttribute(item, options.attributes[item]); + } + //处理样式 + if (options.style) { + for (const item in options.style) element.style[item] = options.style[item]; + } + //处理内容 + if (options.content) { + element.innerHTML = options.content; + } + //处理子元素 + if (options.childs) { + for (const item of options.childs) { + element.appendChild(item); + } + } + return element; + }, + generate() { + let result = Creation.nullObject; + const args = Array.from(arguments); + for (const item of args) { + switch (typeof item) { + case "object": + switch (item.constructor) { + case Object: + case null: + if ("_type" in item) { + const type = item["_type"]; + if (!(type in result)) result[type] = Creation.nullObject; + result[type][item.name] = item.value; + } + else { + if (!("style" in result)) result.style = Creation.nullObject; + for (const name in item) { + result.style[name] = item[name]; + } + } + break; + default: + if (!("childs" in result)) result.childs = Creation.array; + result.childs.add(item); + break; + } + break; + case "string": + if (/^\.|#/.test(item)) { + if (!("identity" in result)) result.identity = Creation.array; + const identities = item.split(".").filter(Boolean); + for (const item of identities) result.identity.add(item); + } + else result.content = item; + break; + } + } + return result; + }, + attribute(name, value) { + return { + _type: "attributes", + name: name, + value: value + } + }, + div() { + return this.inject(document.createElement("div"), this.generate(...arguments)); + } + } +}; diff --git a/noname/library/message.js b/noname/library/message.js new file mode 100644 index 000000000..a99dea150 --- /dev/null +++ b/noname/library/message.js @@ -0,0 +1,1092 @@ +export const message = { + server: { + init: function (version, config, banned_info) { + if (lib.node.banned.contains(banned_info)) { + this.send("denied", "banned"); + } + else if (config.id && lib.playerOL && lib.playerOL[config.id]) { + var player = lib.playerOL[config.id]; + player.setNickname(); + player.ws = this; + player.isAuto = false; + this.id = config.id; + game.broadcast(function (player) { + player.setNickname(); + }, player); + this.send("reinit", lib.configOL, get.arenaState(), game.getState ? game.getState() : {}, game.ip, null, _status.onreconnect, _status.cardtag, _status.postReconnect); + } + else if (version != lib.versionOL) { + this.send("denied", "version"); + lib.node.clients.remove(this); + this.closed = true; + } + else if (!_status.waitingForPlayer) { + if (game.phaseNumber && lib.configOL.observe) { + lib.node.observing.push(this); + this.send("reinit", lib.configOL, get.arenaState(), game.getState ? game.getState() : {}, game.ip, game.players[0].playerid, null, _status.cardtag); + if (!ui.removeObserve) { + ui.removeObserve = ui.create.system("移除旁观", function () { + lib.configOL.observe = false; + if (game.onlineroom) { + game.send("server", "config", lib.configOL); + } + while (lib.node.observing.length) { + lib.node.observing.shift().ws.close(); + } + this.remove(); + delete ui.removeObserve; + }, true, true); + } + } + else { + this.send("denied", "gaming"); + lib.node.clients.remove(this); + this.closed = true; + } + } + else if (lib.node.clients.length - (window.isNonameServer ? 1 : 0) >= parseInt(lib.configOL.number)) { + this.send("denied", "number"); + lib.node.clients.remove(this); + this.closed = true; + } + else { + if (config) { + this.avatar = config.avatar; + this.nickname = config.nickname; + } + for (var i = 0; i < game.connectPlayers.length; i++) { + if (game.connectPlayers[i].classList.contains("unselectable2")) continue; + if (game.connectPlayers[i] != game.me && !game.connectPlayers[i].playerid) { + game.connectPlayers[i].playerid = this.id; + game.connectPlayers[i].initOL(this.nickname, this.avatar); + game.connectPlayers[i].ws = this; + break; + } + } + this.send("init", this.id, lib.configOL, game.ip, window.isNonameServer, game.roomId); + } + }, + inited: function () { + this.inited = true; + if (_status.waitingForPlayer) { + game.updateWaiting(); + } + }, + reinited: function () { + this.inited = true; + }, + result: function (result) { + if (lib.node.observing.contains(this)) return; + var player = lib.playerOL[this.id]; + if (player) { + player.unwait(result); + } + }, + tempResult: function (result) { + if (lib.node.observing.contains(this)) return; + var player = lib.playerOL[this.id]; + if (player) { + player.tempUnwait(result); + } + }, + startGame: function () { + if (this.id == game.onlinezhu) { + game.resume(); + } + }, + changeRoomConfig: function (config) { + if (this.id == game.onlinezhu) { + game.broadcastAll(function (config) { + for (var i in config) { + lib.configOL[i] = config[i]; + } + if (ui.connectStartBar) { + ui.connectStartBar.firstChild.innerHTML = get.modetrans(lib.configOL, true); + } + }, config); + if (lib.configOL.mode == "identity" && lib.configOL.identity_mode == "zhong" && game.connectPlayers) { + for (var i = 0; i < game.connectPlayers.length; i++) { + game.connectPlayers[i].classList.remove("unselectable2"); + } + lib.configOL.number = 8; + game.updateWaiting(); + } + if (game.onlineroom) { + game.send("server", "config", lib.configOL); + } + for (var i = 0; i < game.connectPlayers.length; i++) { + if (game.connectPlayers[i].playerid == this.id) { + game.connectPlayers[i].chat("房间设置已更改"); + } + } + } + }, + changeNumConfig: function (num, index, bool) { + if (this.id == game.onlinezhu) { + lib.configOL.number = num; + game.send("server", "config", lib.configOL); + if (game.connectPlayers && game.connectPlayers[index]) { + if (bool) { + game.connectPlayers[index].classList.add("unselectable2"); + } + else { + game.connectPlayers[index].classList.remove("unselectable2"); + } + game.updateWaiting(); + } + } + }, + throwEmotion: function (target, emotion, rotate) { + if (lib.node.observing.contains(this)) return; + var player = lib.playerOL[this.id]; + if (player) { + player.throwEmotion(target, emotion, rotate); + } + }, + emotion: function (id, pack, emotion) { + if (lib.node.observing.contains(this)) return; + var that = this; + if (!this.id || (!lib.playerOL[this.id] && (!game.connectPlayers || !function () { + for (var i = 0; i < game.connectPlayers.length; i++) { + if (game.connectPlayers[i].playerid == that.id) { + return true; + } + } + return false; + }()))) return; + var player; + if (lib.playerOL[id]) { + player = lib.playerOL[id]; + } + else if (game.connectPlayers) { + for (var i = 0; i < game.connectPlayers.length; i++) { + if (game.connectPlayers[i].playerid == id) { + player = game.connectPlayers[i]; break; + } + } + } + if (player) player.emotion(pack, emotion); + }, + chat: function (id, str) { + if (lib.node.observing.contains(this)) return; + var that = this; + if (!this.id || (!lib.playerOL[this.id] && (!game.connectPlayers || !function () { + for (var i = 0; i < game.connectPlayers.length; i++) { + if (game.connectPlayers[i].playerid == that.id) { + return true; + } + } + return false; + }()))) return; + var player; + if (lib.playerOL[id]) { + player = lib.playerOL[id]; + } + else if (game.connectPlayers) { + for (var i = 0; i < game.connectPlayers.length; i++) { + if (game.connectPlayers[i].playerid == id) { + player = game.connectPlayers[i]; break; + } + } + } + if (player) player.chat(str); + }, + giveup: function (player) { + if (lib.node.observing.contains(this) || !player || !player._giveUp) return; + _status.event.next.length = 0; + game.createEvent("giveup", false).set("includeOut", true).setContent(function () { + game.log(player, "投降"); + player.popup("投降"); + player.die("nosource").includeOut = true; + }).player = player; + }, + auto: function () { + if (lib.node.observing.contains(this)) return; + var player = lib.playerOL[this.id]; + if (player) { + player.isAuto = true; + player.setNickname(player.nickname + " - 托管"); + game.broadcast(function (player) { + player.setNickname(player.nickname + " - 托管"); + }, player); + } + }, + unauto: function () { + if (lib.node.observing.contains(this)) return; + var player = lib.playerOL[this.id]; + if (player) { + player.isAuto = false; + player.setNickname(player.nickname); + game.broadcast(function (player) { + player.setNickname(player.nickname); + }, player); + } + }, + exec: function (func) { + // if(typeof func=="function"){ + // var args=Array.from(arguments); + // args.shift(); + // func.apply(this,args); + // } + }, + log: function () { + var items = []; + try { + for (var i = 0; i < arguments.length; i++) { + eval("items.push(" + arguments[i] + ")"); + } + } + catch (e) { + this.send("log", ["err"]); + return; + } + this.send("log", items); + } + }, + client: { + log: function (arr) { + if (Array.isArray(arr)) { + for (var i = 0; i < arr.length; i++) { + console.log(arr[i]); + } + } + }, + opened: function () { + game.send("init", lib.versionOL, { + id: game.onlineID, + avatar: lib.config.connect_avatar, + nickname: get.connectNickname() + }, lib.config.banned_info); + if (ui.connecting && !ui.connecting.splashtimeout) { + ui.connecting.firstChild.innerHTML = "重连成功"; + } + }, + onconnection: id => lib.init.connection(lib.wsOL[id] = new lib.element.NodeWS(id)), + onmessage: function (id, message) { + if (lib.wsOL[id]) { + lib.wsOL[id].onmessage(message); + } + }, + onclose: function (id) { + if (lib.wsOL[id]) { + lib.wsOL[id].onclose(); + } + }, + selfclose: function () { + if (game.online || game.onlineroom) { + if ((game.servermode || game.onlinehall) && _status.over) { + // later + } + else { + game.saveConfig("tmp_user_roomId"); + } + } + game.ws.close(); + }, + reloadroom: function (forced) { + if (window.isNonameServer && (forced || !_status.protectingroom)) { + game.reload(); + } + }, + createroom: function (index, config, mode) { + game.online = false; + game.onlineroom = true; + game.roomId = index; + lib.node = {}; + if (config && mode && window.isNonameServer) { + if (mode == "auto") { + mode = lib.configOL.mode; + } + game.switchMode(mode, config); + } + else { + game.switchMode(lib.configOL.mode); + } + ui.create.connecting(true); + }, + enterroomfailed: function () { + alert("请稍后再试"); + _status.enteringroom = false; + ui.create.connecting(true); + }, + roomlist: function (list, events, clients, wsid) { + game.send("server", "key", [game.onlineKey, lib.version]); + game.online = true; + game.onlinehall = true; + lib.config.recentIP.remove(_status.ip); + lib.config.recentIP.unshift(_status.ip); + lib.config.recentIP.splice(5); + if (!lib.config.reconnect_info || lib.config.reconnect_info[0] != _status.ip) { + game.saveConfig("reconnect_info", [_status.ip, null]); + } + game.saveConfig("recentIP", lib.config.recentIP); + _status.connectMode = true; + + game.clearArena(); + game.clearConnect(); + ui.pause.hide(); + ui.auto.hide(); + + clearTimeout(_status.createNodeTimeout); + game.send("server", "changeAvatar", get.connectNickname(), lib.config.connect_avatar); + + var proceed = function () { + game.ip = get.trimip(_status.ip); + ui.create.connectRooms(list); + if (events) { + ui.connectEvents = ui.create.div(".forceopaque.menubutton.large.connectevents.pointerdiv", "约战", ui.window, ui.click.connectEvents); + ui.connectEventsCount = ui.create.div(".forceopaque.menubutton.icon.connectevents.highlight.hidden", "", ui.window); + ui.connectClients = ui.create.div(".forceopaque.menubutton.large.connectevents.pointerdiv.left", "在线", ui.window, ui.click.connectClients); + ui.connectClientsCount = ui.create.div(".forceopaque.menubutton.icon.connectevents.highlight.left", "1", ui.window); + ui.createRoomButton = ui.create.div(".forceopaque.menubutton.large.connectevents.pointerdiv.left2", "创建房间", ui.window, function () { + if (!_status.creatingroom) { + _status.creatingroom = true; + ui.click.connectMenu(); + } + }); + if (events.length) { + ui.connectEventsCount.innerHTML = events.filter(function (evt) { + return evt.creator == game.onlineKey || !get.is.banWords(evt.content) + }).length; + ui.connectEventsCount.show(); + } + } + game.wsid = wsid; + lib.message.client.updaterooms(list, clients); + lib.message.client.updateevents(events); + ui.exitroom = ui.create.system("退出房间", function () { + game.saveConfig("tmp_owner_roomId"); + game.saveConfig("tmp_user_roomId"); + if (ui.rooms) { + game.saveConfig("reconnect_info"); + } + else { + if (lib.config.reconnect_info) { + lib.config.reconnect_info.length = 1; + game.saveConfig("reconnect_info", lib.config.reconnect_info); + } + } + game.reload(); + }, true); + + var findRoom = function (id) { + for (var room of ui.rooms) { + if (room.key == id) return room; + } + return false; + }; + if (typeof lib.config.tmp_owner_roomId == "string") { + if (typeof game.roomId != "string" && !findRoom(lib.config.tmp_owner_roomId)) { + lib.configOL.mode = lib.config.connect_mode; + game.roomId = lib.config.tmp_owner_roomId; + } + game.saveConfig("tmp_owner_roomId"); + } + if (typeof lib.config.tmp_user_roomId == "string") { + if (typeof game.roomId != "string") { + if (findRoom(lib.config.tmp_user_roomId)) { + game.roomId = lib.config.tmp_user_roomId; + } + else { + ui.create.connecting(); + (function () { + var n = 10; + var id = lib.config.tmp_user_roomId; + var interval = setInterval(function () { + if (n > 0) { + n--; + if (findRoom(id)) { + clearInterval(interval); + game.send("server", "enter", id, get.connectNickname(), lib.config.connect_avatar); + } + } + else { + ui.create.connecting(true); + clearInterval(interval); + } + }, 500); + }()); + } + } + game.saveConfig("tmp_user_roomId"); + } + + if (window.isNonameServer) { + var cfg = "pagecfg" + window.isNonameServer; + if (lib.config[cfg]) { + lib.configOL = lib.config[cfg][0]; + game.send("server", "server", lib.config[cfg].slice(1)); + game.saveConfig(cfg); + _status.protectingroom = true; + setTimeout(function () { + _status.protectingroom = false; + if (!lib.node || !lib.node.clients || !lib.node.clients.length) { + game.reload(); + } + }, 15000); + } + else { + game.send("server", "server"); + } + } + else if (typeof game.roomId == "string") { + var room = findRoom(game.roomId); + if (game.roomIdServer && room && (room.serving || !room.version)) { + console.log(); + if (lib.config.reconnect_info) { + lib.config.reconnect_info[2] = null; + game.saveConfig("reconnect_info", lib.config.reconnect_info); + } + } + else { + ui.create.connecting(); + game.send("server", (game.roomId == game.onlineKey) ? "create" : "enter", game.roomId, get.connectNickname(), lib.config.connect_avatar); + } + } + lib.init.onfree(); + } + if (_status.event.parent) { + game.forceOver("noover", proceed); + } + else { + proceed(); + } + }, + updaterooms: function (list, clients) { + if (ui.rooms) { + var map = {}, map2 = {}; + for (var i of ui.rooms) map2[i.key] = true; + for (var i of list) { + if (!i) continue; + map[i[4]] = i; + } + ui.window.classList.add("more_room"); + for (var i = 0; i < ui.rooms.length; i++) { + if (!map[ui.rooms[i].key]) { + ui.rooms[i].remove(); + ui.rooms.splice(i--, 1); + } + else ui.rooms[i].initRoom(list[i]); + } + for (var i of list) { + if (!i) continue; + map[i[4]] = i; + if (!map2[i[4]]) { + var player = ui.roombase.add(``); + player.roomindex = i; + player.initRoom = lib.element.Player.prototype.initRoom; + player.addEventListener(lib.config.touchscreen ? "touchend" : "click", ui.click.connectroom); + player.initRoom(i); + ui.rooms.push(player); + } + } + if (!_status.requestReadClipboard && get.config("read_clipboard", "connect")) { + const read = text => { + try { + var roomId = text.split("\n")[1].match(/\d+/); + var caption = ui.rooms.find(caption => caption.key == roomId); + if (caption && (_status.read_clipboard_text || confirm(`是否通过复制的内容加入${roomId}房间?`))) { + ui.click.connectroom.call(caption); + delete _status.read_clipboard_text; + } + } catch (e) { console.log(e) } + } + //每次启动只请求一次 + _status.requestReadClipboard = true; + if (_status.read_clipboard_text) { + read(_status.read_clipboard_text); + } else { + window.focus(); + if (navigator.clipboard && lib.node) { + navigator.clipboard.readText().then(read).catch(_ => { }); + } else { + var input = ui.create.node("textarea", ui.window, { opacity: "0" }); + input.select(); + var result = document.execCommand("paste"); + input.blur(); + ui.window.removeChild(input); + if (result || input.value.length > 0) read(input.value); + else if (confirm("是否输入邀请链接以加入房间?")) { + var text = prompt("请输入邀请链接"); + if (typeof text == "string" && text.length > 0) read(text); + } + } + } + } + } + lib.message.client.updateclients(clients, true); + }, + updateclients: function (clients, bool) { + if (clients && ui.connectClients) { + ui.connectClients.info = clients; + ui.connectClientsCount.innerHTML = clients.length; + } + if (_status.connectClientsCallback) { + _status.connectClientsCallback(); + } + }, + updateevents: function (events) { + if (events && ui.connectEvents) { + ui.connectEvents.info = events; + var num = events.filter(function (evt) { + return typeof evt.creator == "string" && (evt.creator == game.onlineKey || !get.is.banWords(evt.content)) + }).length; + if (num) { + ui.connectEventsCount.innerHTML = num; + ui.connectEventsCount.show(); + } + else { + ui.connectEventsCount.hide(); + } + if (_status.connectEventsCallback) { + _status.connectEventsCallback(); + } + } + }, + eventsdenied: function (reason) { + var str = "创建约战失败"; + if (reason == "total") { + str += ",约战总数不能超过20"; + } + else if (reason == "time") { + str += ",时间已过"; + } + else if (reason == "ban") { + str += ",请注意文明发言"; + } + alert(str); + }, + init: function (id, config, ip, servermode, roomId) { + game.online = true; + game.onlineID = id; + game.ip = ip; + game.servermode = servermode; + game.roomId = roomId; + if (game.servermode) { + game.saveConfig("reconnect_info", [_status.ip, id, game.roomId]); + } + else { + game.saveConfig("reconnect_info", [_status.ip, id]); + game.saveConfig("tmp_user_roomId", roomId); + } + lib.config.recentIP.remove(_status.ip); + lib.config.recentIP.unshift(_status.ip); + lib.config.recentIP.splice(5); + game.saveConfig("recentIP", lib.config.recentIP); + _status.connectMode = true; + lib.configOL = config; + lib.playerOL = {}; + lib.cardOL = {}; + + game.clearArena(); + game.finishCards(); + ui.create.roomInfo(); + ui.create.chat(); + if (game.servermode) { + ui.create.connectPlayers(get.modetrans(config, true)); + } + else { + ui.create.connectPlayers(ip); + } + ui.pause.hide(); + ui.auto.hide(); + game.clearConnect(); + clearTimeout(_status.createNodeTimeout); + + var proceed = function () { + game.loadModeAsync(config.mode, function (mode) { + for (var i in mode.ai) { + if (typeof mode.ai[i] == "object") { + if (ai[i] == undefined) ai[i] = {}; + for (var j in mode.ai[i]) { + ai[i][j] = mode.ai[i][j]; + } + } + else { + ai[i] = mode.ai[i]; + } + } + for (var i in mode.get) { + if (typeof mode.get[i] == "object") { + if (get[i] == undefined) get[i] = {}; + for (var j in mode.get[i]) { + get[i][j] = mode.get[i][j]; + } + } + else { + get[i] = mode.get[i]; + } + } + for (var i in mode.translate) { + lib.translate[i] = mode.translate[i]; + } + if (mode.game) { + game.getIdentityList = mode.game.getIdentityList; + game.updateState = mode.game.updateState; + game.getRoomInfo = mode.game.getRoomInfo; + } + if (mode.element && mode.element.player) { + Object.defineProperties(lib.element.Player.prototype, Object.getOwnPropertyDescriptors(mode.element.player)); + } + if (mode.skill) { + for (var i in mode.skill) { + lib.skill[i] = mode.skill[i]; + } + } + if (mode.card) { + for (var i in mode.card) { + lib.card[i] = mode.card[i]; + } + } + game.finishCards(); + if (mode.characterPack) { + for (var i in mode.characterPack) { + lib.characterPack[i] = mode.characterPack[i]; + } + } + _status.event = lib.element.GameEvent.initialGameEvent(); + _status.paused = false; + game.createEvent("game", false).setContent(lib.init.startOnline); + game.loop(); + game.send("inited"); + ui.create.connecting(true); + }); + } + if (_status.event.parent) { + game.forceOver("noover", proceed); + } + else { + proceed(); + } + for (var i in lib.characterPack) { + for (var j in lib.characterPack[i]) { + lib.character[j] = lib.character[j] || lib.characterPack[i][j]; + } + } + }, + reinit: function (config, state, state2, ip, observe, onreconnect, cardtag, postReconnect) { + ui.auto.show(); + ui.pause.show(); + game.clearConnect(); + clearTimeout(_status.createNodeTimeout); + game.online = true; + game.ip = ip; + game.servermode = state.servermode; + game.roomId = state.roomId; + if (state.over) { + _status.over = true; + } + if (observe) { + game.observe = true; + game.onlineID = null; + game.roomId = null; + } + if (game.servermode && !observe) { + game.saveConfig("reconnect_info", [_status.ip, game.onlineID, game.roomId]); + } + else { + game.saveConfig("reconnect_info", [_status.ip, game.onlineID]); + if (!observe) { + game.saveConfig("tmp_user_roomId", game.roomId); + } + } + _status.connectMode = true; + lib.configOL = config; + lib.playerOL = {}; + lib.cardOL = {}; + + game.loadModeAsync(config.mode, function (mode) { + for (var i in mode.ai) { + if (typeof mode.ai[i] == "object") { + if (ai[i] == undefined) ai[i] = {}; + for (var j in mode.ai[i]) { + ai[i][j] = mode.ai[i][j]; + } + } + else { + ai[i] = mode.ai[i]; + } + } + for (var i in mode.get) { + if (typeof mode.get[i] == "object") { + if (get[i] == undefined) get[i] = {}; + for (var j in mode.get[i]) { + get[i][j] = mode.get[i][j]; + } + } + else { + get[i] = mode.get[i]; + } + } + for (var i in mode.translate) { + lib.translate[i] = mode.translate[i]; + } + if (mode.game) { + game.getIdentityList = mode.game.getIdentityList; + game.getIdentityList2 = mode.game.getIdentityList2; + game.updateState = mode.game.updateState; + game.showIdentity = mode.game.showIdentity; + } + if (mode.element && mode.element.player) { + Object.defineProperties(lib.element.Player.prototype, Object.getOwnPropertyDescriptors(mode.element.player)); + } + if (mode.skill) { + for (var i in mode.skill) { + lib.skill[i] = mode.skill[i]; + } + } + if (mode.card) { + for (var i in mode.card) { + lib.card[i] = mode.card[i]; + } + } + game.finishCards(); + if (mode.characterPack) { + for (var i in mode.characterPack) { + lib.characterPack[i] = mode.characterPack[i]; + } + } + if (mode.onreinit) { + mode.onreinit(); + } + _status.cardtag = get.parsedResult(cardtag); + game.players = []; + game.dead = []; + for (var i in lib.characterPack) { + for (var j in lib.characterPack[i]) { + lib.character[j] = lib.character[j] || lib.characterPack[i][j]; + } + } + game.clearArena(); + game.finishCards(); + if (!observe) { + ui.create.chat(); + if (ui.exitroom) { + ui.exitroom.remove(); + delete ui.exitroom; + } + } + else { + if (!ui.exitroom) { + ui.create.system("退出旁观", function () { + game.saveConfig("reconnect_info"); + game.reload(); + }, true); + } + if (!lib.configOL.observe_handcard) { + ui.arena.classList.add("observe"); + } + } + postReconnect = get.parsedResult(postReconnect); + for (var i in postReconnect) { + if (Array.isArray(postReconnect[i])) { + postReconnect[i].shift().apply(this, postReconnect[i]); + } + } + state = get.parsedResult(state); + ui.arena.setNumber(state.number); + _status.mode = state.mode; + _status.renku = state.renku; + lib.inpile = state.inpile; + lib.inpile_nature = state.inpile_nature; + var pos = state.players[observe || game.onlineID].position; + for (var i in state.players) { + var info = state.players[i]; + var player = ui.create.player(ui.arena).animate("start"); + player.dataset.position = (info.position < pos) ? info.position - pos + parseInt(state.number) : info.position - pos; + if (i == observe || i == game.onlineID) { + game.me = player; + } + if (player.setModeState) { + player.setModeState(info); + } + else { + player.init(info.name1, info.name2); + if (info.name && info.name != info.name1) player.name = info.name; + } + if (!info.unseen) player.classList.remove("unseen"); + if (!info.unseen2) player.classList.remove("unseen2"); + if (!player.isUnseen(2) && player.storage.nohp) { + delete player.storage.nohp; + player.node.hp.show(); + } + player.playerid = i; + player.nickname = info.nickname; + player.changeGroup(info.group, false, "nobroadcast"); + player.identity = info.identity; + player.identityShown = info.identityShown; + player.hp = info.hp; + player.maxHp = info.maxHp; + player.hujia = info.hujia; + player.sex = info.sex; + player.side = info.side; + player.phaseNumber = info.phaseNumber; + player.seatNum = info.seatNum; + player.disabledSlots = info.disabledSlots; + player.expandedSlots = info.expandedSlots; + player.setNickname(); + if (info.dead) { + player.classList.add("dead"); + if (lib.config.die_move) { + player.$dieflip(); + } + if (player.$dieAfter) { + player.$dieAfter(); + } + game.dead.push(player); + } + else { + game.players.push(player); + } + if (info.linked) { + player.addLink(); + } + if (info.turnedover) { + player.classList.add("turnedover"); + } + if (info.out) { + player.classList.add("out"); + } + if (info.disableJudge) { + player.$disableJudge(); + } + player.$syncDisable(); + + player.directgain(info.handcards); + lib.playerOL[i] = player; + for (var i = 0; i < info.equips.length; i++) { + player.$equip(info.equips[i]); + } + for (var i = 0; i < info.handcards.length; i++) { + info.handcards[i].addGaintag(info.gaintag[i]); + } + for (var i = 0; i < info.specials.length; i++) { + info.specials[i].classList.add("glows"); + } + if (info.expansions.length) { + var expansion_gaintag = []; + player.$addToExpansion(info.expansions); + for (var i = 0; i < info.expansions.length; i++) { + info.expansions[i].addGaintag(info.expansion_gaintag[i]); + expansion_gaintag.addArray(info.expansion_gaintag[i]); + } + for (var i of expansion_gaintag) player.markSkill[i]; + } + for (var i = 0; i < info.judges.length; i++) { + if (info.views[i] && info.views[i] != info.judges[i]) { + info.judges[i].classList.add("fakejudge"); + info.judges[i].viewAs = info.views[i]; + info.judges[i].node.background.innerHTML = lib.translate[info.views[i] + "_bg"] || get.translation(info.views[i])[0] + } + player.node.judges.appendChild(info.judges[i]); + } + ui.updatej(player); + if (!player.setModeState) { + if (!game.getIdentityList && info.identityNode) { + player.node.identity.innerHTML = info.identityNode[0]; + player.node.identity.dataset.color = info.identityNode[1]; + } + else if (player == game.me || player.identityShown || observe) { + player.setIdentity(); + player.forceShown = true; + } + else { + player.setIdentity("cai"); + } + if (!lib.configOL.observe_handcard && (lib.configOL.mode == "identity" || lib.configOL.mode == "guozhan")) { + if (observe && !player.identityShown) { + player.setIdentity("cai"); + player.forceShown = false; + } + } + } + player.update(); + } + game.arrangePlayers(); + ui.create.me(true); + + _status.event = lib.element.GameEvent.initialGameEvent(); + _status.paused = false; + _status.dying = get.parsedResult(state.dying) || []; + + if (game.updateState) { + game.updateState(state2); + } + var next = game.createEvent("game", false); + next.setContent(lib.init.startOnline); + if (observe) { + next.custom.replace.target = function (player) { + if (!lib.configOL.observe_handcard && lib.configOL.mode == "guozhan") { + return; + } + if (player.isAlive()) { + if (!game.me.identityShown && lib.configOL.mode == "guozhan") { + game.me.node.identity.firstChild.innerHTML = "猜"; + game.me.node.identity.dataset.color = "unknown"; + } + game.swapPlayer(player); + if (!game.me.identityShown && lib.configOL.mode == "guozhan") { + game.me.node.identity.firstChild.innerHTML = ""; + } + } + } + } + else { + if (Array.isArray(onreconnect)) { + onreconnect.shift().apply(this, onreconnect); + } + } + game.loop(); + game.send("reinited"); + game.showHistory(); + _status.gameStarted = true; + if (lib.config.show_cardpile) { + ui.cardPileButton.style.display = ""; + } + if (!observe && game.me && (game.me.isDead() || _status.over)) { + ui.create.exit(); + } + ui.updatehl(); + ui.create.connecting(true); + }); + }, + exec: function (func) { + var key = game.onlineKey; + if (typeof func == "function") { + var args = Array.from(arguments); + args.shift(); + func.apply(this, args); + } + if (key) { + game.onlineKey = key; + localStorage.setItem(lib.configprefix + "key", game.onlineKey); + } + }, + denied: function (reason) { + switch (reason) { + case "version": + alert("加入失败:版本不匹配,请将游戏更新至最新版"); + game.saveConfig("tmp_owner_roomId"); + game.saveConfig("tmp_user_roomId"); + game.saveConfig("reconnect_info"); + break; + case "gaming": alert("加入失败:游戏已开始"); break; + case "number": alert("加入失败:房间已满"); break; + case "banned": alert("加入失败:房间拒绝你加入"); break; + case "key": + alert("您的游戏版本过低,请升级到最新版"); + game.saveConfig("tmp_owner_roomId"); + game.saveConfig("tmp_user_roomId"); + game.saveConfig("reconnect_info"); + break; + case "offline": + if (_status.paused && _status.event.name == "game") { + setTimeout(game.resume, 500); + } + break; + } + game.ws.close(); + if (_status.connectDenied) { + _status.connectDenied(); + } + }, + cancel: function (id) { + if (_status.event._parent_id == id) { + ui.click.cancel(); + } + if (_status.event.id == id) { + if (_status.event._backup) ui.click.cancel(); + ui.click.cancel(); + if (ui.confirm) { + ui.confirm.close(); + } + if (_status.event.result) { + _status.event.result.id = id; + } + } + }, + closeDialog: function (id) { + var dialog = get.idDialog(id); + if (dialog) { + dialog.close(); + } + }, + createDialog: function (id) { + var args = Array.from(arguments); + args.shift(); + ui.create.dialog.apply(this, args).videoId = id; + }, + gameStart: function () { + for (var i = 0; i < game.connectPlayers.length; i++) { + game.connectPlayers[i].delete(); + } + delete game.connectPlayers; + if (ui.connectStartButton) { + ui.connectStartButton.delete(); + delete ui.connectStartButton; + } + if (ui.connectStartBar) { + ui.connectStartBar.delete(); + delete ui.connectStartBar; + } + if (ui.connectShareButton) { + ui.connectShareButton.delete(); + delete ui.connectShareButton; + } + if (ui.roomInfo) { + ui.roomInfo.remove(); + delete ui.roomInfo; + } + if (ui.exitroom) { + ui.exitroom.remove(); + delete ui.exitroom; + } + ui.auto.show(); + ui.pause.show(); + if (lib.config.show_cardpile) { + ui.cardPileButton.style.display = ""; + } + _status.gameStarted = true; + game.showHistory(); + }, + updateWaiting: function (map) { + if (!game.connectPlayers) return; + if (!lib.translate.zhu) { + lib.translate.zhu = "主"; + } + game.onlinezhu = false; + _status.waitingForPlayer = true; + for (var i = 0; i < map.length; i++) { + if (map[i] == "disabled") { + game.connectPlayers[i].classList.add("unselectable2"); + } + else { + game.connectPlayers[i].classList.remove("unselectable2"); + if (map[i]) { + game.connectPlayers[i].initOL(map[i][0], map[i][1]); + game.connectPlayers[i].playerid = map[i][2]; + if (map[i][3] == "zhu") { + game.connectPlayers[i].setIdentity("zhu"); + if (map[i][2] == game.onlineID) { + game.onlinezhu = true; + if (ui.roomInfo) { + ui.roomInfo.innerHTML = "房间设置"; + } + if (ui.connectStartButton) { + ui.connectStartButton.innerHTML = "开始游戏"; + } + } + } + else { + game.connectPlayers[i].node.identity.firstChild.innerHTML = ""; + } + } + else { + game.connectPlayers[i].uninitOL(); + delete game.connectPlayers[i].playerid; + } + } + } + } + } +}; diff --git a/noname/library/mode.js b/noname/library/mode.js new file mode 100644 index 000000000..ec86ef09d --- /dev/null +++ b/noname/library/mode.js @@ -0,0 +1,2453 @@ +export const MODE = { + identity: { + name: "身份", + connect: { + update(config, map) { + if (config.connect_identity_mode == "stratagem") { + map.connect_round_one_use_fury.show(); + } + else { + map.connect_round_one_use_fury.hide(); + } + if (config.connect_identity_mode == "zhong") { + map.connect_player_number.hide(); + map.connect_limit_zhu.hide(); + map.connect_enhance_zhu.hide(); + map.connect_double_nei.hide(); + map.connect_enable_commoner.hide(); + map.connect_enable_year_limit.show(); + map.connect_zhong_card.show(); + map.connect_special_identity.hide(); + map.connect_double_character.show(); + } + else if (config.connect_identity_mode == "stratagem") { + map.connect_double_character.show(); + map.connect_player_number.show(); + map.connect_limit_zhu.hide(); + map.connect_enhance_zhu.hide(); + map.connect_double_nei.hide(); + map.connect_enable_commoner.hide(); + map.connect_enable_year_limit.show(); + map.connect_zhong_card.hide(); + map.connect_special_identity.hide(); + } + else if (config.connect_identity_mode == "purple") { + map.connect_player_number.hide(); + map.connect_limit_zhu.hide(); + map.connect_enhance_zhu.hide(); + map.connect_double_nei.hide(); + map.connect_enable_commoner.hide(); + map.connect_enable_year_limit.hide(); + map.connect_zhong_card.hide(); + map.connect_special_identity.hide(); + map.connect_double_character.hide(); + } + else { + map.connect_double_character.show(); + map.connect_player_number.show(); + map.connect_limit_zhu.show(); + map.connect_enhance_zhu.show(); + map.connect_double_nei[config.connect_player_number != "2" && !config.connect_enable_commoner ? "show" : "hide"](); + map.connect_enable_commoner[config.connect_player_number != "2" && !config.connect_double_nei ? "show" : "hide"](); + map.connect_enable_year_limit.show(); + map.connect_zhong_card.hide(); + + if (config.connect_player_number == "8") { + map.connect_special_identity.show(); + } + else { + map.connect_special_identity.hide(); + } + } + }, + connect_identity_mode: { + name: "游戏模式", + init: "normal", + item: { + normal: "标准", + zhong: "明忠", + stratagem: "谋攻", + purple: "3v3v2", + }, + restart: true, + frequent: true, + intro: "明忠模式和3v3v2模式详见帮助" + }, + connect_player_number: { + name: "游戏人数", + init: "8", + get item() { + return lib.mode.identity.config.player_number.item; + }, + frequent: true, + restart: true, + }, + connect_limit_zhu: { + name: "常备主候选武将数", + init: "group", + restart: true, + item: { + off: "不限制", + group: "按势力筛选", + "4": "四", + "6": "六", + "8": "八", + }, + }, + connect_zhong_card: { + name: "明忠卡牌替换", + init: true, + frequent: true, + restart: true + }, + connect_double_nei: { + name: "双内奸", + init: false, + restart: true, + // frequent:true, + get intro() { + return lib.mode.identity.config.double_nei.intro; + } + }, + connect_enable_commoner: { + name: "启用平民", + init: false, + restart: true, + frequent: false, + get intro() { + return lib.mode.identity.config.enable_commoner.intro; + } + }, + connect_double_character: { + name: "双将模式", + init: false, + frequent: true, + restart: true, + }, + connect_change_card: { + name: "启用手气卡", + init: false, + frequent: true, + restart: true, + }, + connect_special_identity: { + name: "特殊身份", + init: false, + restart: true, + frequent: true, + intro: "开启后游戏中将增加军师、大将、贼首三个身份" + }, + connect_enable_year_limit: { + name: "启用年机制", + init: false, + restart: true, + frequent: false, + get intro() { + return lib.mode.identity.config.enable_year_limit.intro; + } + }, + connect_round_one_use_fury: { + name: "开启首轮强化卡牌", + init: false, + frequent: false, + restart: true, + intro: "谋攻篇规则为第二轮开始才可使用怒气强化卡牌,开启此选项从游戏开始即可强化卡牌。" + }, + connect_enhance_zhu: { + name: "加强主公", + init: false, + restart: true, + intro: "为主公增加一个额外技能" + }, + }, + config: { + update(config, map) { + if (config.identity_mode == "stratagem") { + map.round_one_use_fury.show(); + map.nei_auto_mark_camouflage.show(); + } + else { + map.round_one_use_fury.hide(); + map.nei_auto_mark_camouflage.hide(); + } + if (config.identity_mode == "zhong") { + map.player_number.hide(); + map.enhance_zhu.hide(); + map.double_nei.hide(); + map.auto_identity.hide(); + map.choice_zhu.hide(); + map.limit_zhu.hide(); + map.choice_zhong.hide(); + map.choice_nei.hide(); + map.choice_fan.hide(); + map.enable_commoner.hide(); + map.choice_commoner.hide(); + map.enable_year_limit.show(); + map.ban_identity.hide(); + map.ban_identity2.hide(); + map.ban_identity3.hide(); + map.zhong_card.show(); + map.special_identity.hide(); + map.choose_group.show(); + map.change_choice.show(); + map.auto_mark_identity.show(); + map.double_character.show(); + map.free_choose.show(); + map.change_identity.show(); + if (config.double_character) { + map.double_hp.show(); + } + else { + map.double_hp.hide(); + } + map.continue_game.show(); + } + else if (config.identity_mode == "stratagem") { + map.continue_game.show(); + map.player_number.show(); + map.enhance_zhu.hide(); + map.auto_identity.hide(); + if (config.player_number != "2") { + map.double_nei.show(); + } + else { + map.double_nei.hide(); + } + map.choice_zhu.show(); + map.limit_zhu.hide(); + map.choice_zhong.show(); + map.choice_nei.show(); + map.choice_fan.show(); + map.enable_commoner.hide(); + map.choice_commoner.hide(); + map.enable_year_limit.show(); + map.ban_identity.show(); + if (config.ban_identity == "off") { + map.ban_identity2.hide(); + } + else { + map.ban_identity2.show(); + } + if (config.ban_identity == "off" || config.ban_identity2 == "off") { + map.ban_identity3.hide(); + } + else { + map.ban_identity3.show(); + } + map.zhong_card.hide(); + map.choose_group.show(); + map.auto_mark_identity.hide(); + map.change_choice.show(); + map.free_choose.show(); + map.change_identity.show(); + map.special_identity.hide(); + map.double_character.show(); + if (config.double_character) { + map.double_hp.show(); + } + else { + map.double_hp.hide(); + } + } + else if (config.identity_mode == "purple") { + map.player_number.hide(); + map.enhance_zhu.hide(); + map.double_nei.hide(); + map.auto_identity.hide(); + map.choice_zhu.hide(); + map.limit_zhu.hide(); + map.choice_zhong.hide(); + map.choice_nei.hide(); + map.choice_fan.hide(); + map.enable_commoner.hide(); + map.choice_commoner.hide(); + map.enable_year_limit.hide(); + map.ban_identity.hide(); + map.ban_identity2.hide(); + map.ban_identity3.hide(); + map.zhong_card.hide(); + map.special_identity.hide(); + map.double_character.hide(); + map.double_hp.hide(); + map.choose_group.hide(); + map.auto_mark_identity.hide(); + map.change_choice.hide(); + map.free_choose.hide(); + map.change_identity.hide(); + map.continue_game.hide(); + } + else { + map.continue_game.show(); + map.player_number.show(); + map.enhance_zhu.show(); + map.auto_identity.show(); + map.double_nei[config.player_number != "2" && !config.enable_commoner ? "show" : "hide"](); + map.choice_zhu.show(); + map.limit_zhu.show(); + map.choice_zhong.show(); + map.choice_nei.show(); + map.choice_fan.show(); + map.enable_commoner[config.player_number != "2" && !config.double_nei ? "show" : "hide"](); + map.choice_commoner[config.enable_commoner ? "show" : "hide"](); + map.enable_year_limit.show(); + map.ban_identity.show(); + if (config.ban_identity == "off") { + map.ban_identity2.hide(); + } + else { + map.ban_identity2.show(); + } + if (config.ban_identity == "off" || config.ban_identity2 == "off") { + map.ban_identity3.hide(); + } + else { + map.ban_identity3.show(); + } + map.zhong_card.hide(); + map.choose_group.show(); + map.auto_mark_identity.show(); + map.change_choice.show(); + map.free_choose.show(); + map.change_identity.show(); + if (config.player_number == "8") { + map.special_identity.show(); + } + else { + map.special_identity.hide(); + } + map.double_character.show(); + if (config.double_character) { + map.double_hp.show(); + } + else { + map.double_hp.hide(); + } + } + }, + identity_mode: { + name: "游戏模式", + init: "normal", + item: { + normal: "标准", + zhong: "明忠", + stratagem: "谋攻", + purple: "3v3v2", + }, + restart: true, + frequent: true, + intro: "明忠模式与谋攻模式详见帮助" + }, + player_number: { + name: "游戏人数", + init: "8", + get item() { + const minimumNumberOfPlayers = 2, maximumNumberOfPlayers = Math.max(_status.maximumNumberOfPlayers || 10, minimumNumberOfPlayers), item = {}; + for (let playerNumber = minimumNumberOfPlayers; playerNumber <= maximumNumberOfPlayers; playerNumber++) { + item[playerNumber] = `${get.cnNumber(playerNumber)}人`; + } + return item; + }, + frequent: true, + restart: true, + }, + double_nei: { + name: "双内奸", + init: false, + restart: true, + frequent: true, + intro: "若游戏人数不大于9,则开启后游戏中将有两个内奸(内奸胜利条件仍为主内1v1时击杀主公)" + }, + choose_group: { + name: "神武将选择势力", + init: true, + restart: true, + frequent: true, + intro: "若开启此选项,选择神武将的玩家需在亮出自己的武将牌之前为自己选择一个势力。" + }, + nei_fullscreenpop: { + name: "主内单挑特效", + intro: "在进入主内单挑时,弹出全屏文字特效", + init: true, + unfrequent: true, + }, + double_character: { + name: "双将模式", + init: false, + frequent: true, + restart: true, + }, + special_identity: { + name: "特殊身份", + init: false, + restart: true, + frequent: true, + intro: "开启后游戏中将增加军师、大将、贼首三个身份" + }, + zhong_card: { + name: "明忠卡牌替换", + init: true, + frequent: true, + restart: true + }, + double_hp: { + name: "双将体力上限", + init: "pingjun", + item: { + hejiansan: "和减三", + pingjun: "平均值", + zuidazhi: "最大值", + zuixiaozhi: "最小值", + zonghe: "相加", + }, + restart: true, + }, + auto_identity: { + name: "自动显示身份", + item: { + off: "关闭", + one: "一轮", + two: "两轮", + three: "三轮", + always: "始终" + }, + init: "off", + onclick(bool) { + game.saveConfig("auto_identity", bool, this._link.config.mode); + if (get.config("identity_mode") == "zhong") return; + var num; + switch (bool) { + case "一轮": num = 1; break; + case "两轮": num = 2; break; + case "三轮": num = 3; break; + default: num = 0; break; + } + if (num & !_status.identityShown && game.phaseNumber > game.players.length * num && game.showIdentity) { + _status.identityShown = true; + game.showIdentity(false); + } + }, + intro: "游戏进行若干轮将自动显示所有角色的身份", + }, + auto_mark_identity: { + name: "自动标记身份", + init: true, + intro: "根据角色的出牌行为自动标记可能的身份", + }, + enhance_zhu: { + name: "加强主公", + init: false, + restart: true, + intro: "为主公增加一个额外技能" + }, + free_choose: { + name: "自由选将", + init: true, + onclick(bool) { + game.saveConfig("free_choose", bool, this._link.config.mode); + if (get.mode() != this._link.config.mode || !_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat2 && get.config("free_choose")) ui.create.cheat2(); + else if (ui.cheat2 && !get.config("free_choose")) { + ui.cheat2.close(); + delete ui.cheat2; + } + } + }, + change_identity: { + name: "自由选择身份和座位", + init: true, + onclick(bool) { + game.saveConfig("change_identity", bool, this._link.config.mode); + if (get.mode() != "identity" || !_status.event.getParent().showConfig && !_status.event.showConfig) return; + var dialog; + if (ui.cheat2 && ui.cheat2.backup) dialog = ui.cheat2.backup; + else dialog = _status.event.dialog; + if (!_status.brawl || !_status.brawl.noAddSetting) { + if (!dialog.querySelector("table") && get.config("change_identity")) _status.event.getParent().addSetting(dialog); + else _status.event.getParent().removeSetting(dialog); + } + ui.update(); + } + }, + change_choice: { + name: "开启换将卡", + init: true, + onclick(bool) { + game.saveConfig("change_choice", bool, this._link.config.mode); + if (get.mode() != "identity" || !_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat && get.config("change_choice")) ui.create.cheat(); + else if (ui.cheat && !get.config("change_choice")) { + ui.cheat.close(); + delete ui.cheat; + } + } + }, + change_card: { + name: "开启手气卡", + init: "disabled", + item: { + disabled: "禁用", + once: "一次", + twice: "两次", + unlimited: "无限", + }, + }, + round_one_use_fury: { + name: "开启首轮强化卡牌", + init: false, + frequent: false, + restart: true, + intro: "谋攻篇规则为第二轮开始才可使用怒气强化卡牌,开启此选项从游戏开始即可强化卡牌。" + }, + nei_auto_mark_camouflage: { + name: "内奸自动标记伪装反贼", + intro: "玩家内奸在游戏开始洞察结束后,自动将被洞察角色标记为反贼。", + init: false, + unfrequent: true, + }, + continue_game: { + name: "显示再战", + init: false, + onclick(bool) { + game.saveConfig("continue_game", bool, this._link.config.mode); + if (get.config("continue_game") && get.mode() == "identity") { + 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; + } + }, + intro: "游戏结束后可选择用相同的武将再进行一局游戏" + }, + dierestart: { + name: "死亡后显示重来", + init: true, + onclick(bool) { + game.saveConfig("dierestart", bool, this._link.config.mode); + if (get.config("dierestart") && get.mode() == "identity") { + if (!ui.restart && game.me.isDead() && !_status.connectMode) { + ui.restart = ui.create.control("restart", game.reload); + } + } + else if (ui.restart) { + ui.restart.close(); + delete ui.restart; + } + } + }, + revive: { + name: "死亡后显示复活", + init: false, + onclick(bool) { + game.saveConfig("revive", bool, this._link.config.mode); + if (get.config("revive") && get.mode() == "identity") { + if (!ui.revive && game.me.isDead()) { + ui.revive = ui.create.control("revive", ui.click.dierevive); + } + } + else if (ui.revive) { + ui.revive.close(); + delete ui.revive; + } + } + }, + ban_identity: { + name: "屏蔽身份", + init: "off", + item: { + off: "关闭", + zhu: "主公", + zhong: "忠臣", + nei: "内奸", + fan: "反贼", + }, + }, + ban_identity2: { + name: "屏蔽身份2", + init: "off", + item: { + off: "关闭", + zhu: "主公", + zhong: "忠臣", + nei: "内奸", + fan: "反贼", + }, + }, + ban_identity3: { + name: "屏蔽身份3", + init: "off", + item: { + off: "关闭", + zhu: "主公", + zhong: "忠臣", + nei: "内奸", + fan: "反贼", + }, + }, + ai_strategy: { + name: "内奸策略", + init: "ai_strategy_1", + item: { + ai_strategy_1: "均衡", + ai_strategy_2: "偏反", + ai_strategy_3: "偏忠", + ai_strategy_4: "酱油", + ai_strategy_5: "天使", + ai_strategy_6: "仇主", + }, + intro: "设置内奸对主忠反的态度" + }, + difficulty: { + name: "AI对人类态度", + init: "normal", + item: { + easy: "友好", + normal: "一般", + hard: "仇视", + }, + }, + choice_zhu: { + name: "主公候选武将数", + init: "3", + restart: true, + item: { + "3": "三", + "4": "四", + "5": "五", + "6": "六", + "8": "八", + "10": "十", + }, + }, + limit_zhu: { + name: "常备主候选武将数", + init: "group", + restart: true, + item: { + off: "不限制", + group: "按势力筛选", + "4": "四", + "6": "六", + "8": "八", + }, + }, + choice_zhong: { + name: "忠臣候选武将数", + init: "4", + restart: true, + item: { + "3": "三", + "4": "四", + "5": "五", + "6": "六", + "8": "八", + "10": "十", + }, + }, + choice_nei: { + name: "内奸候选武将数", + init: "5", + restart: true, + item: { + "3": "三", + "4": "四", + "5": "五", + "6": "六", + "8": "八", + "10": "十", + }, + }, + choice_fan: { + name: "反贼候选武将数", + init: "3", + restart: true, + item: { + "3": "三", + "4": "四", + "5": "五", + "6": "六", + "8": "八", + "10": "十", + }, + }, + enable_commoner: { + name: "启用平民", + init: false, + restart: true, + frequent: false, + intro: "开启后游戏中将有一个平民(身份)加入游戏。
      具体规则请查看帮助。", + }, + choice_commoner: { + name: "平民候选武将数", + init: "4", + restart: true, + item: { + "3": "三", + "4": "四", + "5": "五", + "6": "六", + "8": "八", + "10": "十", + }, + }, + enable_year_limit: { + name: "启用年机制", + init: false, + restart: true, + frequent: false, + intro: "开启后将会加入年机制。
      年机制的具体规则请查看帮助。", + }, + } + }, + guozhan: { + name: "国战", + connect: { + connect_guozhan_mode: { + name: "游戏模式", + init: "normal", + item: { + normal: "势备", + yingbian: "应变", + old: "怀旧", + }, + frequent: true, + restart: true, + intro: "
    • 势备:默认模式,使用线下《君临天下·势备篇》的牌堆进行游戏。
    • 应变:使用OL的应变国战牌堆进行游戏。
    • 怀旧:使用传统国战的牌堆进行游戏。", + }, + connect_player_number: { + name: "游戏人数", + init: "8", + get item() { + return lib.mode.guozhan.config.player_number.item; + }, + frequent: true, + restart: true, + }, + connect_aozhan: { + name: "鏖战模式", + init: true, + intro: "若开启此选项,则将在游戏中引入“鏖战模式”的规则:
      当游戏中仅剩四名或更少角色时(七人以下游戏时改为三名或更少),若此时全场没有超过一名势力相同的角色,则从一个新的回合开始,游戏进入鏖战模式直至游戏结束。
      ◇在鏖战模式下,【桃】只能当做【杀】或【闪】使用或打出,不能用来回复体力。
      注:进入鏖战模式后,即使之后有两名或者更多势力相同的角色出现,仍然不会取消鏖战模式。", + frequent: true, + restart: true, + }, + get connect_separatism() { + return lib.mode.guozhan.config.separatism; + }, + connect_initshow_draw: { + name: "首亮奖励", + item: { + "off": "关闭", + "draw": "摸牌", + "mark": "标记", + }, + init: "mark", + frequent: true, + intro: "第一个明置武将牌的角色可获得首亮奖励" + }, + connect_viewnext: { + name: "观看下家副将", + init: false, + intro: "若开启此选项,所有的玩家将在挑选武将后,分发起始手牌之前,分别观看自己下家的副将。", + }, + connect_zhulian: { + name: "珠联璧合", + init: true, + intro: "主将和副将都明置后,若为特定组合,可获得【珠联璧合】标记" + }, + connect_junzhu: { + name: "替换君主", + init: true, + restart: true, + intro: "若开启此选项,玩家的第一个回合开始时,若其主武将牌有对应的君主武将牌,则其可以将此武将牌替换为对应的君主武将牌,然后重新调整体力上限。若玩家的体力上限因此增大,则玩家回复等量的体力。" + }, + connect_change_card: { + name: "启用手气卡", + init: false, + frequent: true, + restart: true, + } + }, + config: { + update(config, map) { + if (config.onlyguozhan) { + map.junzhu.show(); + } + else { + map.junzhu.hide(); + } + ui.aozhan_bgm = map.aozhan_bgm; + map.aozhan_bgm._link.config.updatex.call(map.aozhan_bgm, []); + }, + guozhan_mode: { + name: "游戏模式", + init: "normal", + item: { + normal: "势备", + yingbian: "应变", + old: "怀旧", + free: "自由", + }, + frequent: true, + restart: true, + intro: "
    • 势备:默认模式,使用线下《君临天下·势备篇》的牌堆进行游戏。
    • 应变:使用OL的应变国战牌堆进行游戏。
    • 怀旧:使用传统国战的牌堆进行游戏。
    • 自由:使用玩家的自定义牌堆进行游戏。", + }, + player_number: { + name: "游戏人数", + init: "8", + get item() { + const minimumNumberOfPlayers = 2, maximumNumberOfPlayers = Math.max(_status.maximumNumberOfPlayers || 12, minimumNumberOfPlayers), item = {}; + for (let playerNumber = minimumNumberOfPlayers; playerNumber <= maximumNumberOfPlayers; playerNumber++) { + item[playerNumber] = `${get.cnNumber(playerNumber)}人`; + } + return item; + }, + frequent: true, + restart: true, + }, + aozhan: { + name: "鏖战模式", + init: true, + frequent: true, + restart: true, + intro: "若开启此选项,则将在游戏中引入“鏖战模式”的规则:
      当游戏中仅剩四名或更少角色时(七人以下游戏时改为三名或更少),若此时全场没有超过一名势力相同的角色,则从一个新的回合开始,游戏进入鏖战模式直至游戏结束。
      ◇在鏖战模式下,【桃】只能当做【杀】或【闪】使用或打出,不能用来回复体力。
      注:进入鏖战模式后,即使之后有两名或者更多势力相同的角色出现,仍然不会取消鏖战模式。", + }, + separatism: { + name: "群雄割据", + init: false, + frequent: true, + restart: true, + intro: "开放不同势力组合,以优先亮出的武将牌作为自己的势力,双势力武将则使用列表的第一个势力" + }, + initshow_draw: { + name: "首亮奖励", + item: { + "off": "关闭", + "draw": "摸牌", + "mark": "标记", + }, + init: "mark", + frequent: true, + intro: "第一个明置身份牌的角色可获得摸牌奖励" + }, + viewnext: { + name: "观看下家副将", + init: false, + intro: "若开启此选项,所有的玩家将在挑选武将后,分发起始手牌之前,分别观看自己下家的副将。", + }, + aozhan_bgm: { + updatex() { + this.lastChild.innerHTML = this._link.config.item[lib.config.mode_config.guozhan.aozhan_bgm]; + if (!Array.isArray(_status.aozhanBGMToRemove)) return; + const menu = this._link.menu; + for (let i = 0; i < menu.childElementCount; i++) { + const link = menu.childNodes[i]._link; + if (["disabled", "random"].includes(link) || !_status.aozhanBGMToRemove.includes(link)) continue; + _status.aozhanBGMToRemove.remove(link); + menu.childNodes[i].delete(); + } + }, + name: "鏖战背景音乐", + item: { + disabled: "不启用", + online: "Online", + rewrite: "Rewrite", + chaoming: "潮鸣", + random: "随机播放", + }, + init: "rewrite", + onclick(item) { + game.saveConfig("aozhan_bgm", item, this._link.config.mode); + if (_status._aozhan == true) game.playBackgroundMusic(); + }, + }, + zhulian: { + name: "珠联璧合", + init: true, + // frequent:true, + intro: "主将和副将都明置后,若为特定组合,可获得【珠联璧合】标记" + }, + changeViceType: { + name: "副将变更方式", + init: "default", + item: { + default: "发现式", + online: "随机式", + }, + frequent: true, + restart: true, + }, + onlyguozhan: { + name: "使用国战武将", + init: true, + frequent: true, + restart: true, + intro: "开启武将技能将替换为国战版本并禁用非国战武将" + }, + guozhanSkin: { + name: "使用国战皮肤", + init: true, + frequent: true, + restart: true, + intro: "开启此选项后,将会把有国战专属皮肤的武将替换为国战皮肤" + }, + junzhu: { + name: "替换君主", + init: true, + // frequent:true, + restart: true, + intro: "若开启此选项,玩家的第一个回合开始时,若其主武将牌有对应的君主武将牌,则其可以将此武将牌替换为对应的君主武将牌,然后重新调整体力上限。若玩家的体力上限因此增大,则玩家回复等量的体力。" + }, + double_hp: { + name: "双将体力上限", + init: "pingjun", + item: { + hejiansan: "和减三", + pingjun: "平均值", + zuidazhi: "最大值", + zuixiaozhi: "最小值", + zonghe: "相加", + }, + restart: true, + }, + free_choose: { + name: "自由选将", + init: true, + onclick(bool) { + game.saveConfig("free_choose", bool, this._link.config.mode); + if (get.mode() != this._link.config.mode || !_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat2 && get.config("free_choose")) ui.create.cheat2(); + else if (ui.cheat2 && !get.config("free_choose")) { + ui.cheat2.close(); + delete ui.cheat2; + } + } + }, + onlyguozhanexpand: { + name: "默认展开自由选将", + init: false, + restart: true, + intro: "开启后自由选将对话框将默认显示全部武将" + }, + change_identity: { + name: "自由选择座位", + init: true, + onclick(bool) { + game.saveConfig("change_identity", bool, this._link.config.mode); + if (get.mode() != "guozhan" || !_status.event.getParent().showConfig && !_status.event.showConfig) return; + var dialog; + if (ui.cheat2 && ui.cheat2.backup) dialog = ui.cheat2.backup; + else dialog = _status.event.dialog; + if (!_status.brawl || !_status.brawl.noAddSetting) { + if (!dialog.querySelector("table") && get.config("change_identity")) _status.event.getParent().addSetting(dialog); + else _status.event.getParent().removeSetting(dialog); + } + ui.update(); + } + }, + change_choice: { + name: "开启换将卡", + init: true, + onclick(bool) { + game.saveConfig("change_choice", bool, this._link.config.mode); + if (get.mode() != "guozhan" || !_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat && get.config("change_choice")) ui.create.cheat(); + else if (ui.cheat && !get.config("change_choice")) { + ui.cheat.close(); + delete ui.cheat; + } + } + }, + change_card: { + name: "开启手气卡", + init: "disabled", + item: { + disabled: "禁用", + once: "一次", + twice: "两次", + 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; + } + } + }, + dierestart: { + name: "死亡后显示重来", + init: true, + onclick(bool) { + game.saveConfig("dierestart", bool, this._link.config.mode); + if (get.config("dierestart") && get.mode() == "guozhan") { + if (!ui.restart && game.me.isDead() && !_status.connectMode) { + ui.restart = ui.create.control("restart", game.reload); + } + } + else if (ui.restart) { + ui.restart.close(); + delete ui.restart; + } + } + }, + revive: { + name: "死亡后显示复活", + init: false, + onclick(bool) { + game.saveConfig("revive", bool, this._link.config.mode); + if (get.config("revive") && get.mode() == "guozhan") { + if (!ui.revive && game.me.isDead()) { + ui.revive = ui.create.control("revive", ui.click.dierevive); + } + } + else if (ui.revive) { + ui.revive.close(); + delete ui.revive; + } + } + }, + difficulty: { + name: "AI对人类态度", + init: "normal", + item: { + easy: "友好", + normal: "一般", + hard: "仇视", + } + }, + choice_num: { + name: "候选武将数", + init: "7", + restart: true, + item: { + "5": "五", + "6": "六", + "7": "七", + "8": "八", + "9": "九", + "10": "十", + } + }, + } + }, + versus: { + name: "对决", + connect: { + update(config, map) { + if (config.connect_versus_mode == "1v1") { + map.connect_choice_num.show(); + map.connect_replace_number.show(); + } + else { + map.connect_choice_num.hide(); + map.connect_replace_number.hide(); + } + if (config.connect_versus_mode == "2v2" || config.connect_versus_mode == "3v3") { + map.connect_replace_handcard.show(); + } + else { + map.connect_replace_handcard.hide(); + } + }, + connect_versus_mode: { + name: "游戏模式", + init: "1v1", + item: { + "1v1": "1v1", + "2v2": "2v2", + "3v3": "3v3", + "4v4": "4v4", + "guandu": "官渡", + }, + frequent: true + }, + connect_replace_handcard: { + name: "四号位保护", + init: true, + frequent: true, + intro: "最后行动的角色起始手牌数+1" + }, + connect_olfeiyang_four: { + name: "四号位获得【飞扬】", + init: true, + frequent: true, + intro: "最后行动的角色获得技能【飞扬】(准备阶段,你可以弃置三张牌,然后弃置判定区的一张牌)", + }, + connect_choice_num: { + name: "侯选武将数", + init: "20", + frequent: true, + item: { + "12": "12人", + "16": "16人", + "20": "20人", + "24": "24人", + "40": "40人", + } + }, + connect_replace_number: { + name: "替补人数", + init: "2", + frequent: true, + item: { + "0": "无", + "1": "1人", + "2": "2人", + "3": "3人", + "4": "4人", + "5": "5人", + } + } + }, + config: { + update(config, map) { + if (config.versus_mode == "four") { + map.change_choice.hide(); + map.ladder.show(); + if (config.ladder) { + map.ladder_monthly.show(); + map.ladder_reset.show(); + } + else { + map.ladder_monthly.hide(); + map.ladder_reset.hide(); + } + map.enable_all.show(); + map.enable_all_cards_four.show(); + map.four_assign.show(); + map.four_phaseswap.show(); + map.expand_dialog.show(); + map.fouralign.show(); + map.edit_character_four.show(); + map.reset_character_four.show(); + } + else { + map.change_choice.show(); + map.ladder.hide(); + map.ladder_monthly.hide(); + map.ladder_reset.hide(); + map.enable_all.hide(); + map.enable_all_cards_four.hide(); + map.four_assign.hide(); + map.four_phaseswap.hide(); + map.expand_dialog.hide(); + map.fouralign.hide(); + map.edit_character_four.hide(); + map.reset_character_four.hide(); + } + if (config.versus_mode == "three") { + map.edit_character_three.show(); + map.reset_character_three.show(); + } + else { + map.edit_character_three.hide(); + map.reset_character_three.hide(); + } + if (config.versus_mode == "three" || config.versus_mode == "one") { + map.enable_all_three.show(); + map.enable_all_cards.show(); + } + else { + map.enable_all_three.hide(); + map.enable_all_cards.hide(); + } + if (config.versus_mode == "jiange" || config.versus_mode == "two" || config.versus_mode == "endless" || + config.versus_mode == "three" || config.versus_mode == "one" || config.versus_mode == "siguo") { + map.free_choose.show(); + } + else { + map.free_choose.hide(); + } + if (config.versus_mode == "jiange") { + map.double_character_jiange.show(); + } + else { + map.double_character_jiange.hide(); + } + if (config.versus_mode == "two") { + map.replace_handcard_two.show(); + map.olfeiyang_four.show(); + map.replace_character_two.show(); + map.two_assign.show(); + map.two_phaseswap.show(); + } + else { + map.replace_handcard_two.hide(); + map.olfeiyang_four.hide(); + map.replace_character_two.hide(); + map.two_assign.hide(); + map.two_phaseswap.hide(); + } + if (config.versus_mode == "two" || config.versus_mode == "siguo" || config.versus_mode == "four") { + if (config.versus_mode == "four" && (config.four_assign || config.four_phaseswap)) { + map.change_identity.hide(); + } + else { + map.change_identity.show(); + } + } + else { + map.change_identity.hide(); + } + if (config.versus_mode == "siguo") { + map.siguo_character.show(); + } + else { + map.siguo_character.hide(); + } + }, + versus_mode: { + name: "游戏模式", + init: "four", + item: { + four: "对抗", + three: "统率", + two: "欢乐", + guandu: "官渡", + jiange: "剑阁", + siguo: "四国", + standard: "自由" + }, + restart: true, + frequent: true, + }, + ladder: { + name: "天梯模式", + init: true, + frequent: true, + restart: true + }, + ladder_monthly: { + name: "每月重置天梯", + init: true, + frequent: true, + }, + enable_all: { + name: "启用全部武将", + init: false, + frequent: true, + restart: true, + }, + enable_all_cards_four: { + name: "启用全部卡牌", + init: false, + frequent: true, + restart: true, + }, + enable_all_three: { + name: "启用全部武将", + init: false, + frequent: true, + restart: true, + }, + enable_all_cards: { + name: "启用全部卡牌", + init: false, + frequent: true, + restart: true, + }, + four_assign: { + name: "代替队友选将", + init: false, + restart: true, + }, + four_phaseswap: { + name: "代替队友行动", + init: false, + restart: true, + }, + two_assign: { + name: "代替队友选将", + init: false, + restart: true, + }, + two_phaseswap: { + name: "代替队友行动", + init: false, + restart: true, + }, + free_choose: { + name: "自由选将", + init: true, + frequent: true, + onclick(bool) { + game.saveConfig("free_choose", bool, this._link.config.mode); + if (!ui.create.cheat2) return; + if (get.mode() != this._link.config.mode || !_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat2 && get.config("free_choose")) ui.create.cheat2(); + else if (ui.cheat2 && !get.config("free_choose")) { + ui.cheat2.close(); + delete ui.cheat2; + } + } + }, + fouralign: { + name: "自由选择阵型", + init: false + }, + change_identity: { + name: "自由选择座位", + init: true, + onclick(bool) { + game.saveConfig("change_identity", bool, this._link.config.mode); + if (!_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (_status.mode == "four") { + if (get.config("four_assign") || get.config("four_phaseswap")) return; + if (bool) { + if (_status.event.parent.addSetting) { + _status.event.parent.addSetting(); + } + } + else { + var seats = _status.event.parent.seatsbutton; + if (seats) { + while (seats.length) { + seats.shift().remove(); + } + delete _status.event.parent.seatsbutton; + } + } + } + else { + var dialog; + if (ui.cheat2 && ui.cheat2.backup) dialog = ui.cheat2.backup; + else dialog = _status.event.dialog; + if (!_status.brawl || !_status.brawl.noAddSetting) { + if (!dialog.querySelector("table") && get.config("change_identity")) _status.event.getParent().addSetting(dialog); + else _status.event.getParent().removeSetting(dialog); + } + ui.update(); + } + } + }, + change_choice: { + name: "开启换将卡", + init: true, + onclick(bool) { + game.saveConfig("change_choice", bool, this._link.config.mode); + if (!_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat && get.config("change_choice")) ui.create.cheat(); + else if (ui.cheat && !get.config("change_choice")) { + ui.cheat.close(); + delete ui.cheat; + } + }, + frequent: true, + }, + double_character_jiange: { + name: "双将模式", + init: false, + frequent: true, + }, + replace_handcard_two: { + name: "四号位保护", + init: true, + frequent: true, + intro: "最后行动的角色起始手牌+1" + }, + olfeiyang_four: { + name: "四号位获得【飞扬】", + init: true, + frequent: true, + intro: "最后行动的角色获得技能【飞扬】(准备阶段,你可以弃置三张牌,然后弃置判定区的一张牌)", + }, + replace_character_two: { + name: "替补模式", + init: false, + frequent: true, + intro: "每个额外选择一名武将,死亡后用该武将代替重新上场,替补武将用完时失败" + }, + expand_dialog: { + name: "默认展开选将框", + intro: "选将框打开时直接显示全部武将(可能使游戏在开始时卡顿)", + init: false, + }, + siguo_character: { + name: "专属武将出场率", + init: "increase", + item: { + increase: "大概率", + normal: "默认概率", + off: "不出现", + }, + frequent: true + }, + ladder_reset: { + name: "重置天梯数据", + onclick() { + var node = this; + if (node._clearing) { + game.save("ladder", { + current: 900, + top: 900, + month: (new Date()).getMonth() + }); + ui.ladder.innerHTML = "卫士五"; + clearTimeout(node._clearing); + node.firstChild.innerHTML = "重置天梯数据"; + delete node._clearing; + return; + } + node.firstChild.innerHTML = "单击以确认 (3)"; + node._clearing = setTimeout(function () { + node.firstChild.innerHTML = "单击以确认 (2)"; + node._clearing = setTimeout(function () { + node.firstChild.innerHTML = "单击以确认 (1)"; + node._clearing = setTimeout(function () { + node.firstChild.innerHTML = "重置天梯数据"; + delete node._clearing; + }, 1000); + }, 1000); + }, 1000); + }, + clear: true, + }, + edit_character_three: { + name: "编辑统率将池", + clear: true, + onclick() { + if (get.mode() != "versus") { + alert("请进入对决模式,然后再编辑将池"); + return; + } + var container = ui.create.div(".popup-container.editor"); + var node = container; + var map = get.config("character_three") || lib.choiceThree; + var str = "character=[\n "; + for (var i = 0; i < map.length; i++) { + str += `"${map[i]}",`; + if (i + 1 < map.length && (i + 1) % 5 == 0) str += "\n "; + } + str += "\n];"; + node.code = str; + ui.window.classList.add("shortcutpaused"); + ui.window.classList.add("systempaused"); + var saveInput = function () { + var code; + if (container.editor) { + code = container.editor.getValue(); + } + else if (container.textarea) { + code = container.textarea.value; + } + try { + var character = null; + eval(code); + if (!Array.isArray(character)) { + throw ("err"); + } + } + catch (e) { + var tip = lib.getErrorTip(e) || ""; + alert("代码语法有错误,请仔细检查(" + e + ")" + tip); + window.focus(); + if (container.editor) { + container.editor.focus(); + } + else if (container.textarea) { + container.textarea.focus(); + } + return; + } + game.saveConfig("character_three", character, "versus"); + ui.window.classList.remove("shortcutpaused"); + ui.window.classList.remove("systempaused"); + container.delete(); + container.code = code; + delete window.saveNonameInput; + }; + window.saveNonameInput = saveInput; + var editor = ui.create.editor(container, saveInput); + if (node.aced) { + ui.window.appendChild(node); + node.editor.setValue(node.code, 1); + } + else if (lib.device == "ios") { + ui.window.appendChild(node); + if (!node.textarea) { + var textarea = document.createElement("textarea"); + editor.appendChild(textarea); + node.textarea = textarea; + lib.setScroll(textarea); + } + node.textarea.value = node.code; + } + else { + if (!window.CodeMirror) { + lib.init.js(lib.assetURL + "game", "codemirror", () => lib.codeMirrorReady(node, editor)); + lib.init.css(lib.assetURL + "layout/default", "codemirror"); + } + else { + lib.codeMirrorReady(node, editor); + } + } + }, + }, + reset_character_three: { + name: "重置统率将池", + intro: "将统率三军模式下的将池重置为默认将池", + clear: true, + onclick() { + if (confirm("该操作不可撤销!是否清除统率三军模式的自定义将池,并将其重置为默认将池?")) { + game.saveConfig("character_three", null, "versus"); + alert("将池已重置"); + } + }, + }, + edit_character_four: { + name: "编辑4v4将池", + clear: true, + onclick() { + if (get.mode() != "versus") { + alert("请进入对决模式,然后再编辑将池"); + return; + } + var container = ui.create.div(".popup-container.editor"); + var node = container; + var map = get.config("character_four") || lib.choiceFour; + var str = "character=[\n "; + for (var i = 0; i < map.length; i++) { + str += `"${map[i]}",`; + if (i + 1 < map.length && (i + 1) % 5 == 0) str += "\n "; + } + str += "\n];"; + node.code = str; + ui.window.classList.add("shortcutpaused"); + ui.window.classList.add("systempaused"); + var saveInput = function () { + var code; + if (container.editor) { + code = container.editor.getValue(); + } + else if (container.textarea) { + code = container.textarea.value; + } + try { + var character = null; + eval(code); + if (!Array.isArray(character)) { + throw ("err"); + } + } + catch (e) { + var tip = lib.getErrorTip(e) || ""; + alert("代码语法有错误,请仔细检查(" + e + ")" + tip); + window.focus(); + if (container.editor) { + container.editor.focus(); + } + else if (container.textarea) { + container.textarea.focus(); + } + return; + } + game.saveConfig("character_four", character, "versus"); + ui.window.classList.remove("shortcutpaused"); + ui.window.classList.remove("systempaused"); + container.delete(); + container.code = code; + delete window.saveNonameInput; + }; + window.saveNonameInput = saveInput; + var editor = ui.create.editor(container, saveInput); + if (node.aced) { + ui.window.appendChild(node); + node.editor.setValue(node.code, 1); + } + else if (lib.device == "ios") { + ui.window.appendChild(node); + if (!node.textarea) { + var textarea = document.createElement("textarea"); + editor.appendChild(textarea); + node.textarea = textarea; + lib.setScroll(textarea); + } + node.textarea.value = node.code; + } + else { + if (!window.CodeMirror) { + lib.init.js(lib.assetURL + "game", "codemirror", () => lib.codeMirrorReady(node, editor)); + lib.init.css(lib.assetURL + "layout/default", "codemirror"); + } + else { + lib.codeMirrorReady(node, editor); + } + } + }, + }, + reset_character_four: { + name: "重置4v4将池", + intro: "将4v4模式下的将池重置为默认将池", + clear: true, + onclick() { + if (confirm("该操作不可撤销!是否清除4v4模式的自定义将池,并将其重置为默认将池?")) { + game.saveConfig("character_four", null, "versus"); + alert("将池已重置"); + } + }, + }, + } + }, + connect: { + name: "联机", + config: { + connect_nickname: { + name: "联机昵称", + input: true, + frequent: true, + }, + connect_avatar: { + name: "联机头像", + init: "caocao", + item: {}, + frequent: true, + onclick(item) { + game.saveConfig("connect_avatar", item); + game.saveConfig("connect_avatar", item, "connect"); + } + }, + hall_ip: { + name: "联机大厅", + input: true, + frequent: true, + }, + hall_button: { + name: "联机大厅按钮", + init: true, + frequent: true, + onclick(bool) { + game.saveConfig("hall_button", bool, "connect"); + if (ui.hall_button) { + if (bool) { + ui.hall_button.style.display = ""; + } + else { + ui.hall_button.style.display = "none"; + } + } + } + }, + wss_mode: { + name: "使用WSS协议", + init: false, + frequent: true, + intro: "在用户填写的IP地址没有直接指定使用WS/WSS协议的情况下,默认使用WSS协议,而非WS协议来连接到联机服务器。
      请不要轻易勾选此项!", + }, + read_clipboard: { + name: "读取邀请链接", + init: false, + frequent: true, + intro: "读取剪贴板以解析邀请链接自动加入联机房间", + } + } + }, + boss: { + name: "挑战", + config: { + free_choose: { + name: "自由选将", + init: true, + frequent: true, + onclick(bool) { + game.saveConfig("free_choose", bool, this._link.config.mode); + if (get.mode() != this._link.config.mode || !_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat2 && get.config("free_choose")) ui.create.cheat2(); + else if (ui.cheat2 && !get.config("free_choose")) { + ui.cheat2.close(); + delete ui.cheat2; + } + } + }, + change_choice: { + name: "开启换将卡", + init: true, + onclick(bool) { + game.saveConfig("change_choice", bool, this._link.config.mode); + if (!_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat && get.config("change_choice")) ui.create.cheat(); + else if (ui.cheat && !get.config("change_choice")) { + ui.cheat.close(); + delete ui.cheat; + } + }, + frequent: true, + }, + single_control: { + name: "单人控制", + init: true, + frequent: true, + onclick(bool) { + game.saveConfig("single_control", bool, this._link.config.mode); + if (ui.single_swap && game.me != game.boss) { + if (bool) { + ui.single_swap.style.display = "none"; + } + else { + ui.single_swap.style.display = ""; + } + } + }, + intro: "只控制一名角色,其他角色由AI控制" + } + } + }, + doudizhu: { + name: "斗地主", + connect: { + update(config, map) { + if (config.connect_doudizhu_mode == "online") { + map.connect_change_card.hide(); + } + else { + map.connect_change_card.show(); + } + if (config.connect_doudizhu_mode != "normal") { + map.connect_double_character.hide(); + } + else { + map.connect_double_character.show(); + } + }, + connect_doudizhu_mode: { + name: "游戏模式", + init: "normal", + item: { + normal: "休闲", + kaihei: "开黑", + huanle: "欢乐", + binglin: "兵临", + online: "智斗", + }, + restart: true, + frequent: true, + }, + connect_double_character: { + name: "双将模式", + init: false, + frequent: true, + restart: true, + }, + connect_change_card: { + name: "启用手气卡", + init: false, + frequent: true, + restart: true, + }, + }, + config: { + update(config, map) { + if (config.doudizhu_mode == "online") { + map.change_card.hide(); + map.edit_character.show(); + map.reset_character.show(); + } + else { + map.change_card.show(); + map.edit_character.hide(); + map.reset_character.hide(); + } + if (config.doudizhu_mode != "normal") { + map.double_character.hide(); + map.free_choose.hide(); + map.change_identity.hide(); + map.change_choice.hide(); + map.continue_game.hide(); + map.dierestart.hide(); + map.choice_zhu.hide(); + map.choice_fan.hide(); + map.revive.hide(); + } + else { + map.double_character.show(); + map.free_choose.show(); + map.change_identity.show(); + map.change_choice.show(); + map.continue_game.show(); + map.dierestart.show(); + map.choice_zhu.show(); + map.choice_fan.show(); + map.revive.show(); + } + if (config.double_character && config.doudizhu_mode == "normal") { + map.double_hp.show(); + } + else { + map.double_hp.hide(); + } + }, + doudizhu_mode: { + name: "游戏模式", + init: "normal", + item: { + normal: "休闲", + kaihei: "开黑", + huanle: "欢乐", + binglin: "兵临", + online: "智斗", + }, + restart: true, + frequent: true, + }, + double_character: { + name: "双将模式", + init: false, + frequent: true, + restart: true, + }, + double_hp: { + name: "双将体力上限", + init: "pingjun", + item: { + hejiansan: "和减三", + pingjun: "平均值", + zuidazhi: "最大值", + zuixiaozhi: "最小值", + zonghe: "相加", + }, + restart: true, + }, + free_choose: { + name: "自由选将", + init: true, + onclick(bool) { + game.saveConfig("free_choose", bool, this._link.config.mode); + if (get.mode() != this._link.config.mode || !_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat2 && get.config("free_choose")) ui.create.cheat2(); + else if (ui.cheat2 && !get.config("free_choose")) { + ui.cheat2.close(); + delete ui.cheat2; + } + } + }, + change_identity: { + name: "自由选择身份和座位", + init: true, + onclick(bool) { + game.saveConfig("change_identity", bool, this._link.config.mode); + if (!_status.event.getParent().showConfig && !_status.event.showConfig) return; + var dialog; + if (ui.cheat2 && ui.cheat2.backup) dialog = ui.cheat2.backup; + else dialog = _status.event.dialog; + if (!_status.brawl || !_status.brawl.noAddSetting) { + if (!dialog.querySelector("table") && get.config("change_identity")) _status.event.getParent().addSetting(dialog); + else _status.event.getParent().removeSetting(dialog); + } + ui.update(); + } + }, + change_choice: { + name: "开启换将卡", + init: true, + onclick(bool) { + game.saveConfig("change_choice", bool, this._link.config.mode); + if (!_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat && get.config("change_choice")) ui.create.cheat(); + else if (ui.cheat && !get.config("change_choice")) { + ui.cheat.close(); + delete ui.cheat; + } + } + }, + change_card: { + name: "开启手气卡", + init: "disabled", + item: { + disabled: "禁用", + once: "一次", + twice: "两次", + unlimited: "无限", + }, + }, + continue_game: { + name: "显示再战", + init: false, + onclick(bool) { + game.saveConfig("continue_game", bool, this._link.config.mode); + if (get.config("continue_game")) { + 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; + } + }, + intro: "游戏结束后可选择用相同的武将再进行一局游戏" + }, + dierestart: { + name: "死亡后显示重来", + init: true, + onclick(bool) { + game.saveConfig("dierestart", bool, this._link.config.mode); + if (get.config("dierestart")) { + if (!ui.restart && game.me.isDead() && !_status.connectMode) { + ui.restart = ui.create.control("restart", game.reload); + } + } + else if (ui.restart) { + ui.restart.close(); + delete ui.restart; + } + } + }, + revive: { + name: "死亡后显示复活", + init: false, + onclick(bool) { + game.saveConfig("revive", bool, this._link.config.mode); + if (get.config("revive")) { + if (!ui.revive && game.me.isDead()) { + ui.revive = ui.create.control("revive", ui.click.dierevive); + } + } + else if (ui.revive) { + ui.revive.close(); + delete ui.revive; + } + } + }, + choice_zhu: { + name: "地主候选武将数", + init: "3", + restart: true, + item: { + "3": "三", + "4": "四", + "5": "五", + "6": "六", + "8": "八", + "10": "十", + }, + }, + choice_fan: { + name: "农民候选武将数", + init: "3", + restart: true, + item: { + "3": "三", + "4": "四", + "5": "五", + "6": "六", + "8": "八", + "10": "十", + }, + }, + edit_character: { + name: "编辑将池", + clear: true, + onclick() { + if (get.mode() != "doudizhu") { + alert("请进入斗地主模式,然后再编辑将池"); + return; + } + var container = ui.create.div(".popup-container.editor"); + var node = container; + var map = get.config("character_online") || lib.characterOnline; + node.code = "character=" + get.stringify(map) + "\n/*\n 这里是智斗三国模式的武将将池。\n 您可以在这里编辑对武将将池进行编辑,然后点击“保存”按钮即可保存。\n 将池中的Key势力武将,仅同时在没有被禁用的情况下,才会出现在选将框中。\n 而非Key势力的武将,只要所在的武将包没有被隐藏,即可出现在选将框中。\n 该将池为单机模式/联机模式通用将池。在这里编辑后,即使进入联机模式,也依然会生效。\n 但联机模式本身禁用的武将(如神貂蝉)不会出现在联机模式的选将框中。\n*/"; + ui.window.classList.add("shortcutpaused"); + ui.window.classList.add("systempaused"); + var saveInput = function () { + var code; + if (container.editor) { + code = container.editor.getValue(); + } + else if (container.textarea) { + code = container.textarea.value; + } + try { + var character = null; + eval(code); + if (!get.is.object(character)) { + throw ("err"); + } + var groups = []; + for (var i in character) { + if (!Array.isArray(character[i])) throw ("type"); + if (character[i].length >= 3) groups.push(i); + } + if (groups.length < 3) throw ("enough"); + } + catch (e) { + if (e == "type") { + alert("请严格按照格式填写,不要写入不为数组的数据"); + } + else if (e == "enough") { + alert("请保证至少写入了3个势力,且每个势力至少有3个武将"); + } + else if (e == "err") { + alert("代码格式有错误,请对比示例代码仔细检查"); + } + else { + var tip = lib.getErrorTip(e) || ""; + alert("代码语法有错误,请仔细检查(" + e + ")" + tip); + } + window.focus(); + if (container.editor) { + container.editor.focus(); + } + else if (container.textarea) { + container.textarea.focus(); + } + return; + } + game.saveConfig("character_online", character, "doudizhu"); + ui.window.classList.remove("shortcutpaused"); + ui.window.classList.remove("systempaused"); + container.delete(); + container.code = code; + delete window.saveNonameInput; + }; + window.saveNonameInput = saveInput; + var editor = ui.create.editor(container, saveInput); + if (node.aced) { + ui.window.appendChild(node); + node.editor.setValue(node.code, 1); + } + else if (lib.device == "ios") { + ui.window.appendChild(node); + if (!node.textarea) { + var textarea = document.createElement("textarea"); + editor.appendChild(textarea); + node.textarea = textarea; + lib.setScroll(textarea); + } + node.textarea.value = node.code; + } + else { + if (!window.CodeMirror) { + lib.init.js(lib.assetURL + "game", "codemirror", () => lib.codeMirrorReady(node, editor)); + lib.init.css(lib.assetURL + "layout/default", "codemirror"); + } + else { + lib.codeMirrorReady(node, editor); + } + } + }, + }, + reset_character: { + name: "重置将池", + intro: "将智斗三国模式下的将池重置为默认将池", + clear: true, + onclick() { + if (confirm("该操作不可撤销!是否清除智斗三国模式的自定义将池,并将其重置为默认将池?")) { + game.saveConfig("character_online", null, "doudizhu"); + alert("将池已重置"); + } + }, + }, + } + }, + single: { + name: "单挑", + connect: { + connect_single_mode: { + name: "游戏模式", + init: "normal", + item: { + normal: "新1v1", + dianjiang: "点将单挑", + changban: "血战长坂坡", + }, + restart: true, + frequent: true, + }, + connect_enable_jin: { + name: "启用晋势力武将", + init: false, + restart: true, + frequent: true, + }, + update(config, map) { + if (config.connect_single_mode != "normal") { + map.connect_enable_jin.hide(); + } + else { + map.connect_enable_jin.show(); + } + }, + }, + config: { + single_mode: { + name: "游戏模式", + init: "normal", + item: { + normal: "新1v1", + dianjiang: "点将单挑", + changban: "血战长坂坡", + }, + restart: true, + frequent: true, + }, + enable_jin: { + name: "启用晋势力武将", + init: false, + restart: true, + frequent: true, + }, + update(config, map) { + if (config.single_mode != "normal") { + map.enable_jin.hide(); + } + else { + map.enable_jin.show(); + } + }, + } + }, + chess: { + name: "战棋", + config: { + chess_mode: { + name: "游戏模式", + init: "combat", + item: { + combat: "自由", + three: "统率", + leader: "君主", + }, + restart: true, + frequent: true, + }, + update(config, map) { + if (config.chess_mode == "leader") { + map.chess_leader_save.show(); + map.chess_leader_clear.show(); + map.chess_leader_allcharacter.show(); + map.chess_character.hide(); + } + else { + map.chess_leader_save.hide(); + map.chess_leader_clear.hide(); + map.chess_leader_allcharacter.hide(); + map.chess_character.show(); + } + if (config.chess_mode == "combat") { + map.free_choose.show(); + map.change_choice.show(); + } + else { + map.free_choose.hide(); + map.change_choice.hide(); + } + }, + chess_leader_save: { + name: "选择历程", + init: "save1", + item: { + save1: "一", + save2: "二", + save3: "三", + save4: "四", + save5: "五", + }, + restart: true, + frequent: true, + }, + chess_leader_allcharacter: { + name: "启用全部角色", + init: true, + onclick(bool) { + if (confirm("调整该设置将清除所有进度,是否继续?")) { + for (var i = 1; i < 6; i++) game.save("save" + i, null, "chess"); + game.saveConfig("chess_leader_allcharacter", bool, "chess") + if (get.mode() == "chess") game.reload(); + return; + } + else this.classList.toggle("on"); + }, + }, + chess_leader_clear: { + name: "清除进度", + onclick() { + var node = this; + if (node._clearing) { + for (var i = 1; i < 6; i++) game.save("save" + i, null, "chess"); + game.reload(); + return; + } + node._clearing = true; + node.firstChild.innerHTML = "单击以确认 (3)"; + setTimeout(function () { + node.firstChild.innerHTML = "单击以确认 (2)"; + setTimeout(function () { + node.firstChild.innerHTML = "单击以确认 (1)"; + setTimeout(function () { + node.firstChild.innerHTML = "清除进度"; + delete node._clearing; + }, 1000); + }, 1000); + }, 1000); + }, + clear: true, + frequent: true, + }, + chess_obstacle: { + name: "随机路障", + init: "0.2", + item: { + "0": "关闭", + "0.2": "少量", + "0.333": "中量", + "0.5": "大量", + }, + frequent: true, + }, + show_range: { + name: "显示卡牌范围", + init: true, + }, + show_distance: { + name: "显示距离", + init: true, + }, + chess_character: { + name: "战棋武将", + init: true, + frequent: true, + }, + chess_card: { + name: "战棋卡牌", + init: true, + frequent: true, + }, + free_choose: { + name: "自由选将", + init: true, + onclick(bool) { + game.saveConfig("free_choose", bool, this._link.config.mode); + if (get.mode() != this._link.config.mode || !_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat2 && get.config("free_choose")) ui.create.cheat2(); + else if (ui.cheat2 && !get.config("free_choose")) { + ui.cheat2.close(); + delete ui.cheat2; + } + }, + }, + change_choice: { + name: "开启换将卡", + init: true, + onclick(bool) { + game.saveConfig("change_choice", bool, this._link.config.mode); + if (!_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat && get.config("change_choice")) ui.create.cheat(); + else if (ui.cheat && !get.config("change_choice")) { + ui.cheat.close(); + delete ui.cheat; + } + }, + }, + chessscroll_speed: { + name: "边缘滚动速度", + init: "20", + intro: "鼠标移至屏幕边缘时自动滚屏", + item: { + "0": "不滚动", + "10": "10格/秒", + "20": "20格/秒", + "30": "30格/秒", + } + } + } + }, + tafang: { + name: "塔防", + config: { + tafang_turn: { + name: "游戏胜利", + init: "10", + frequent: true, + item: { + "10": "十回合", + "20": "二十回合", + "30": "三十回合", + "1000": "无限", + } + }, + tafang_difficulty: { + name: "战斗难度", + init: "2", + frequent: true, + item: { + "1": "简单", + "2": "普通", + "3": "困难", + } + }, + show_range: { + name: "显示卡牌范围", + init: true, + }, + show_distance: { + name: "显示距离", + init: true, + }, + chessscroll_speed: { + name: "边缘滚动速度", + intro: "鼠标移至屏幕边缘时自动滚屏", + init: "20", + item: { + "0": "不滚动", + "10": "10格/秒", + "20": "20格/秒", + "30": "30格/秒", + } + } + } + }, + brawl: { + name: "乱斗", + config: { + huanhuazhizhan: { + name: "幻化之战", + init: true, + frequent: true + }, + duzhansanguo: { + name: "毒战三国", + init: true, + frequent: true + }, + daozhiyueying: { + name: "导师月英", + init: true, + frequent: true + }, + weiwoduzun: { + name: "唯我独尊", + init: true, + frequent: true + }, + tongxingzhizheng: { + name: "同姓之争", + init: true, + frequent: true + }, + jiazuzhizheng: { + name: "家族之争", + init: true, + frequent: true + }, + tongqueduopao: { + name: "铜雀夺袍", + init: true, + frequent: true + }, + tongjiangmoshi: { + name: "同将模式", + init: true, + frequent: true + }, + baiyidujiang: { + name: "白衣渡江", + init: true, + frequent: true + }, + qianlidanji: { + name: "千里单骑", + init: true, + frequent: true + }, + liangjunduilei: { + name: "两军对垒", + init: true, + frequent: true + }, + scene: { + name: "创建场景", + init: true, + frequent: true + } + } + }, + stone: { + name: "炉石", + config: { + battle_number: { + name: "出场人数", + init: "1", + frequent: true, + item: { + "1": "一人", + "2": "两人", + "3": "三人", + "4": "四人", + "6": "六人", + "8": "八人", + "10": "十人", + }, + onclick(num) { + game.saveConfig("battle_number", num, this._link.config.mode); + if (_status.connectMode) return; + if (!_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (_status.event.getParent().changeDialog) { + _status.event.getParent().changeDialog(); + } + } + }, + mana_mode: { + name: "行动值变化", + init: "inc", + item: { + inf: "涨落", + inc: "递增" + }, + frequent: true + }, + skill_bar: { + name: "怒气值", + init: true, + frequent: true, + restart: true, + }, + double_character: { + name: "双将模式", + init: false, + frequent: true, + restart() { + return _status.event.getParent().name != "chooseCharacter" || _status.event.name != "chooseButton"; + } + }, + free_choose: { + name: "自由选将", + init: true, + onclick(bool) { + game.saveConfig("free_choose", bool, this._link.config.mode); + if (_status.connectMode) return; + if (get.mode() != this._link.config.mode || !_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat2 && get.config("free_choose")) ui.create.cheat2(); + else if (ui.cheat2 && !get.config("free_choose")) { + ui.cheat2.close(); + delete ui.cheat2; + } + } + }, + change_choice: { + name: "开启换将卡", + init: true, + onclick(bool) { + game.saveConfig("change_choice", bool, this._link.config.mode); + if (_status.connectMode) return; + if (!_status.event.getParent().showConfig && !_status.event.showConfig) return; + if (!ui.cheat && get.config("change_choice")) ui.create.cheat(); + else if (ui.cheat && !get.config("change_choice")) { + ui.cheat.close(); + delete ui.cheat; + } + } + } + } + } +}; diff --git a/noname/library/nature-audio.js b/noname/library/nature-audio.js new file mode 100644 index 000000000..2b3a5410d --- /dev/null +++ b/noname/library/nature-audio.js @@ -0,0 +1,39 @@ +export const natureAudio = { + damage: { + fire: "default",//默认,即语音放置在audio/effect下,以damage_fire.mp3 damage_fire2.mp3命名。 + thunder: "default", + ice: "default", + stab: "normal",//正常,即与普通伤害音效相同。 + /* + "example":{ + 1:"../extension/XXX/damage_example.mp3",//1点伤害。 + 2:"../extension/XXX/damage_example2.mp3",//2点及以上伤害 + } + */ + }, + hujia_damage: { + fire: "default",//默认,即语音放置在audio/effect下,以hujia_damage_fire.mp3 hujia_damage_fire2.mp3命名。 + thunder: "default", + ice: "normal",//正常,即与普通伤害音效相同。 + /* + "example":{ + 1:"../extension/XXX/damage_example.mp3",//1点伤害。 + 2:"../extension/XXX/damage_example2.mp3",//2点及以上伤害 + } + */ + }, + sha: { + fire: "default",//默认,即语音放置在audio/card/male与audio/card/female下,命名为sha_fire.mp3 + thunder: "default", + ice: "default", + stab: "default", + poison: "normal",//正常,即播放“杀”的音效。 + kami: "normal", + /* + "example":{ + "male":"../extension/XXXX/sha_example_male.mp3", + "female":"../extension/XXXX/sha_example_female.mp3" + } + */ + } +}; diff --git a/noname/library/other.js b/noname/library/other.js new file mode 100644 index 000000000..753080374 --- /dev/null +++ b/noname/library/other.js @@ -0,0 +1,7 @@ +export class Other { + constructor() { + throw new TypeError(`${new.target.name} is not a constructor`); + } + + static ignore() { } +} diff --git a/noname/library/perfect-pair.js b/noname/library/perfect-pair.js new file mode 100644 index 000000000..4f9b0b11c --- /dev/null +++ b/noname/library/perfect-pair.js @@ -0,0 +1 @@ +export const perfectPair = {}; diff --git a/noname/library/skill.js b/noname/library/skill.js new file mode 100644 index 000000000..76e8c6efd --- /dev/null +++ b/noname/library/skill.js @@ -0,0 +1,1307 @@ +export const skill = { + stratagem_fury: { + marktext: "🔥", + intro: { + name: "怒气", + content: (storage, player) => { + const stratagemFuryMax = _status.stratagemFuryMax, fury = storage || 0; + return `当前怒气值:${typeof stratagemFuryMax == "number" ? `${fury}/${stratagemFuryMax}` : fury}`; + } + } + }, + _stratagem_add_buff: { + log: false, + enable: "chooseToUse", + filter: (event, player) => { + const fury = player.storage.stratagem_fury; + if (!fury) return false; + const stratagemSettings = event.stratagemSettings; + if (!stratagemSettings || !stratagemSettings.roundOneUseFury && game.roundNumber < 2) return false; + const cards = player.getCards("hs"); + if (!cards.length) return false; + const cost = lib.stratagemBuff.cost, names = Array.from(cost.keys()); + if (!names.length) return false; + return cards.some(card => game.checkMod(card, player, "unchanged", "cardEnabled2", player) && names.some(availableName => availableName == get.name(card, player) && event.filterCard(new lib.element.VCard({ + name: availableName, + nature: get.nature(card, player), + isCard: true, + cards: [card] + }), player, event) && fury >= cost.get(availableName))); + }, + onChooseToUse: event => { + const player = _status.event.player, fury = player.storage.stratagem_fury; + if (!fury) return; + if (!event.stratagemSettings && !game.online) event.set("stratagemSettings", { + roundOneUseFury: _status.connectMode ? lib.configOL.round_one_use_fury : get.config("round_one_use_fury") + }); + const cost = lib.stratagemBuff.cost.get("shan"); + if (typeof cost != "number" || !event.shanRequired) return; + event.addNumber("shanIgnored", Math.min(player.countCards(lib.skill._stratagem_add_buff.position, { + name: "shan" + }), Math.floor(fury / cost))); + }, + check: card => { + const player = _status.event.player; + if (_status.event.type == "phase") { + const cardName = get.name(card, player); + if (cardName == "sha") { + if (game.hasPlayer(current => { + if (!player.canUse(card, current)) return false; + const storage = player.storage, zhibi = storage.zhibi; + return (zhibi && !zhibi.includes(current) || (get.effect(current, card, player, player) >= 2 - Math.max(0, (storage.stratagem_fury || 0) - 1))) && current.mayHaveShan() && player.hasSkill("jiu"); + })) return 1; + return 0; + } + if (cardName == "tao") { + if (player.hp <= 2 && player.getDamagedHp() >= 2) return 1; + return 0; + } + return 1; + } + if (_status.event.type == "dying") return get.attitude(player, _status.event.dying) > 3 ? 1 : 0; + return (_status.event.getParent().shanRequired || 1) > 1 && get.damageEffect(player, _status.event.getParent().player || player, player) < 0 ? 1 : 0; + }, + position: "hs", + filterCard: (card, player, event) => { + if (!event) event = _status.event; + const filterCard = event._backup.filterCard; + const cost = lib.stratagemBuff.cost; + return Array.from(cost.keys()).some(availableName => availableName == get.name(card, player) && filterCard(new lib.element.VCard({ + name: availableName, + nature: get.nature(card, player), + isCard: true, + cards: [card] + }), player, _status.event) && player.storage.stratagem_fury >= cost.get(availableName)); + }, + viewAs: (cards, player) => { + const cardName = get.name(cards[0], player); + return cardName ? new lib.element.VCard({ + name: cardName, + nature: get.nature(cards[0], player), + suit: get.suit(cards[0], player), + number: get.number(cards[0], player), + isCard: true, + cards: [cards[0]], + storage: { + stratagem_buffed: 1 + } + }) : new lib.element.VCard(); + }, + prompt: () => { + const span = document.createElement("span"); + span.classList.add("text"); + span.style.fontFamily = "yuanli"; + const stratagemBuff = lib.stratagemBuff, cost = stratagemBuff.cost; + stratagemBuff.prompt.forEach((prompt, cardName) => { + const li = document.createElement("li"); + li.innerHTML = `【${get.translation(cardName)}】:${cost.get(cardName)}点怒气。${prompt()}`; + span.appendChild(li); + }); + return `当你需要使用位于“强化表”内的非虚拟卡牌时,你可以消耗对应数量的怒气将其强化并使用。${document.createElement("hr").outerHTML}${span.outerHTML}`; + }, + onuse: (result, player) => { + player.logSkill(result.skill); + const stratagemBuff = lib.stratagemBuff, cardName = result.card.name; + player.changeFury(-stratagemBuff.cost.get(cardName), true); + const gameEvent = get.event(), effect = stratagemBuff.effect.get(cardName); + if (typeof effect == "function") gameEvent.pushHandler("onNextUseCard", effect); + gameEvent.pushHandler("onNextUseCard", (event, option) => { + if (event.step == 0 && option.state == "end") game.broadcastAll(cards => cards.forEach(card => card.clone.classList.add("stratagem-fury-glow")), event.cards); + }); + }, + ai: { + order: (item, player) => { + if (!player) player = _status.event.player; + if (_status.event.type == "phase") for (const card of player.getCards("hs")) { + if (!game.checkMod(card, player, "unchanged", "cardEnabled2", player)) continue; + const cardName = get.name(card, player); + if (cardName == "sha") { + if (game.hasPlayer(current => { + if (!player.canUse(card, current)) return false; + const storage = player.storage, zhibi = storage.zhibi; + return (zhibi && !zhibi.contains(current) || (get.effect(current, card, player, player) >= 2 - Math.max(0, (storage.stratagem_fury || 0) - 1))) && current.mayHaveShan(); + })) return get.order(card, player) + 0.5; + } + else if (cardName == "tao" && player.hp <= 2 && player.getDamagedHp() >= 2) return get.order(card, player) + 0.5; + return 8; + } + return 3.5; + }, + directHit_ai: true, + skillTagFilter: (player, tag, arg) => { + const card = get.autoViewAs(arg.card); + if (card.name != "sha" || !card.storage.stratagem_buffed) return false; + const target = arg.target; + if (target.countCards("h", "shan") >= 1 && !target.storage.stratagem_fury) return false; + } + } + }, + expandedSlots: { + markimage: "image/card/expandedSlots.png", + intro: { + markcount: function (storage, player) { + var all = 0, storage = player.expandedSlots; + if (!storage) return 0; + for (var key in storage) { + var num = storage[key]; + if (typeof num == "number" && num > 0) { + all += num; + } + } + return all; + }, + content: function (storage, player) { + storage = player.expandedSlots; + if (!storage) return "当前没有扩展装备栏"; + const keys = Object.keys(storage).sort(), combined = get.is.mountCombined(); + let str = ""; + for (const key of keys) { + const num = storage[key]; + if (typeof num == "number" && num > 0) { + let trans = get.translation(key); + if (combined && key == "equip3") trans = "坐骑"; + str += "
    • " + trans + "栏:" + num + "个
      " + } + } + if (str.length) return str.slice(0, str.length - 4); + return "当前没有扩展装备栏"; + }, + }, + }, + charge: { + markimage: "image/card/charge.png", + intro: { + content: "当前蓄力点数:#", + }, + }, + cooperation: { + charlotte: true, + trigger: { + global: ["phaseAfter", "dieAfter"], + }, + forced: true, + lastDo: true, + filter: function (event, player) { + if (event.name == "die" && event.player.isAlive()) return false; + var storage = player.getStorage("cooperation"); + for (var info of storage) { + if (info.target == event.player) return true; + } + return false; + }, + content: function () { + for (var i = 0; i < player.storage.cooperation.length; i++) { + var info = player.storage.cooperation[i]; + if (info.target == trigger.player) { + player.removeCooperation(info); + i--; + } + } + }, + onremove: function (player, skill) { + var storage = player.getStorage(skill); + var reasons = []; + for (var i of storage) reasons.add(i.type); + for (var i of reasons) player.removeSkill(skill + "_" + i); + delete player.storage[i]; + }, + subSkill: { + damage: { + mark: true, + trigger: { global: "damage" }, + forced: true, + charlotte: true, + popup: false, + firstDo: true, + filter: function (event, player) { + if (!event.source) return false; + var storage = player.getStorage("cooperation"); + for (var info of storage) { + if (info.type == "damage" && (event.source == player || event.source == info.target)) return true; + } + return false; + }, + checkx: (info) => (info.damage && info.damage > 3), + content: function () { + var source = trigger.source; + var storage = player.getStorage("cooperation"); + for (var info of storage) { + if (info.type == "damage" && (source == player || source == info.target)) { + if (!info.damage) info.damage = 0; + info.damage += trigger.num; + } + } + player.markSkill("cooperation_damage"); + }, + marktext: "仇", + intro: { + name: "协力 - 同仇", + markcount: function (storage, player) { + return Math.max.apply(Math, player.getStorage("cooperation").map(function (info) { + return info.damage || 0; + })); + }, + content: function (storage, player) { + var str = "", storage = player.getStorage("cooperation"); + for (var info of storage) { + if (info.type == "damage") { + str += "
    • 协力角色:" + get.translation(info.target); + str += "
    • 协力原因:" + get.translation(info.reason); + str += "
    • 协力进度:" + var num = (info.damage || 0); + str += num; + str += "/4"; + str += (num > 3 ? " (已完成)" : " (未完成)"); + str += "
        "; + } + } + return str.slice(4, str.length - 6); + }, + }, + }, + draw: { + mark: true, + trigger: { global: "gainAfter" }, + forced: true, + charlotte: true, + popup: false, + firstDo: true, + filter: function (event, player) { + if (event.getParent().name != "draw") return false; + var storage = player.getStorage("cooperation"); + for (var info of storage) { + if (info.type == "draw" && (event.player == player || event.player == info.target)) return true; + } + return false; + }, + checkx: (info) => (info.draw && info.draw > 7), + content: function () { + var source = trigger.player; + var storage = player.getStorage("cooperation"); + for (var info of storage) { + if (info.type == "draw" && (source == player || source == info.target)) { + if (!info.draw) info.draw = 0; + info.draw += trigger.cards.length; + } + } + player.markSkill("cooperation_draw"); + }, + marktext: "进", + intro: { + name: "协力 - 并进", + markcount: function (storage, player) { + return Math.max.apply(Math, player.getStorage("cooperation").map(function (info) { + return info.draw || 0; + })); + }, + content: function (storage, player) { + var str = "", storage = player.getStorage("cooperation"); + for (var info of storage) { + if (info.type == "draw") { + str += "
    • 协力角色:" + get.translation(info.target); + str += "
    • 协力原因:" + get.translation(info.reason); + str += "
    • 协力进度:" + var num = (info.draw || 0); + str += num; + str += "/8"; + str += (num > 7 ? " (已完成)" : " (未完成)"); + str += "
        "; + } + } + return str.slice(4, str.length - 6); + }, + }, + }, + discard: { + mark: true, + trigger: { global: "loseAfter" }, + forced: true, + charlotte: true, + popup: false, + firstDo: true, + filter: function (event, player) { + if (event.type != "discard") return false; + var storage = player.getStorage("cooperation"); + for (var info of storage) { + if (info.type == "discard" && (event.player == player || event.player == info.target)) return true; + } + return false; + }, + checkx: (info) => (info.discard && info.discard.length > 3), + content: function () { + var source = trigger.player; + var storage = player.getStorage("cooperation"); + for (var info of storage) { + if (info.type == "discard" && (source == player || source == info.target)) { + if (!info.discard) info.discard = []; + for (var i of trigger.cards2) { + var suit = get.suit(i, player); + if (lib.suit.contains(suit)) info.discard.add(suit); + } + } + } + player.markSkill("cooperation_discard"); + }, + marktext: "财", + intro: { + name: "协力 - 疏财", + markcount: function (storage, player) { + return Math.max.apply(Math, player.getStorage("cooperation").map(function (info) { + return info.discard ? info.discard.length : 0; + })); + }, + content: function (storage, player) { + var str = "", storage = player.getStorage("cooperation"); + for (var info of storage) { + if (info.type == "discard") { + str += "
    • 协力角色:" + get.translation(info.target); + str += "
    • 协力原因:" + get.translation(info.reason); + str += "
    • 进度:"; + var suits = info.discard || []; + var suits2 = [["spade", "♠", "♤"], ["heart", "♥", "♡"], ["club", "♣", "♧"], ["diamond", "♦", "♢"]]; + for (var i of suits2) { + str += (suits.contains(i[0]) ? i[1] : i[2]); + } + str += (suits.length > 3 ? " (已完成)" : " (未完成)"); + str += "
        "; + } + } + return str.slice(4, str.length - 6); + }, + }, + }, + use: { + mark: true, + trigger: { global: "useCard1" }, + forced: true, + charlotte: true, + popup: false, + firstDo: true, + filter: function (event, player) { + var suit = get.suit(event.card); + if (!lib.suit.contains(suit)) return false; + var storage = player.getStorage("cooperation"); + for (var info of storage) { + if (info.type == "use" + && (event.player == player || event.player == info.target) && + (!info.used || !info.used.contains(suit))) return true; + } + return false; + }, + checkx: (info) => (info.used && info.used.length > 3), + content: function () { + var source = trigger.player, suit = get.suit(trigger.card); + var storage = player.getStorage("cooperation"); + for (var info of storage) { + if (info.type == "use" && (source == player || source == info.target)) { + if (!info.used) info.used = []; + info.used.add(suit); + } + } + player.markSkill("cooperation_use"); + }, + marktext: "戮", + intro: { + name: "协力 - 戮力", + markcount: function (storage, player) { + return Math.max.apply(Math, player.getStorage("cooperation").map(function (info) { + return info.used ? info.used.length : 0; + })); + }, + content: function (storage, player) { + var str = "", storage = player.getStorage("cooperation"); + for (var info of storage) { + if (info.type == "use") { + str += "
    • 协力角色:" + get.translation(info.target); + str += "
    • 协力原因:" + get.translation(info.reason); + str += "
    • 进度:"; + var suits = info.used || []; + var suits2 = [["spade", "♠", "♤"], ["heart", "♥", "♡"], ["club", "♣", "♧"], ["diamond", "♦", "♢"]]; + for (var i of suits2) { + str += (suits.contains(i[0]) ? i[1] : i[2]); + } + str += (suits.length > 3 ? " (已完成)" : " (未完成)"); + str += "
        "; + } + } + return str.slice(4, str.length - 6); + }, + }, + }, + }, + }, + zhengsu: { + trigger: { player: "phaseDiscardEnd" }, + forced: true, + charlotte: true, + filter: function (event, player) { + return (player.storage.zhengsu_leijin || player.storage.zhengsu_bianzhen || player.storage.zhengsu_mingzhi); + }, + content: function () { + player.chooseDrawRecover(2, "整肃奖励:摸两张牌或回复1点体力"); + }, + subSkill: { + leijin: { + mod: { + aiOrder: function (player, card, num) { + if (typeof card.number != "number") return; + var history = player.getHistory("useCard", evt => evt.isPhaseUsing()); + if (history.length == 0) return num + 10 * (14 - card.number); + var num = get.number(history[0].card); + if (!num) return; + for (var i = 1; i < history.length; i++) { + var num2 = get.number(history[i].card); + if (!num2 || num2 <= num) return; + num = num2; + } + if (card.number > num) return num + 10 * (14 - card.number); + }, + }, + mark: true, + trigger: { player: "useCard1" }, + lastDo: true, + charlotte: true, + forced: true, + popup: false, + onremove: true, + filter: function (event, player) { + return player.isPhaseUsing() && player.storage.zhengsu_leijin !== false; + }, + content: function () { + var list = player.getHistory("useCard", function (evt) { + return evt.isPhaseUsing(player); + }); + var goon = true; + for (var i = 0; i < list.length; i++) { + var num = get.number(list[i].card); + if (typeof num != "number") { + goon = false; + break; + } + if (i > 0) { + var num2 = get.number(list[i - 1].card); + if (typeof num2 != "number" || num2 >= num) { + goon = false; + break; + } + } + } + if (!goon) { + game.broadcastAll(function (player) { + player.storage.zhengsu_leijin = false; + if (player.marks.zhengsu_leijin) player.marks.zhengsu_leijin.firstChild.innerHTML = "╳"; + delete player.storage.zhengsu_leijin_markcount; + }, player); + } + else { + if (list.length > 2) { + game.broadcastAll(function (player, num) { + if (player.marks.zhengsu_leijin) player.marks.zhengsu_leijin.firstChild.innerHTML = "○"; + player.storage.zhengsu_leijin = true; + player.storage.zhengsu_leijin_markcount = num; + }, player, num); + } + else game.broadcastAll(function (player, num) { + player.storage.zhengsu_leijin_markcount = num; + }, player, num); + } + player.markSkill("zhengsu_leijin"); + }, + intro: { + content: "
    • 条件:回合内所有于出牌阶段使用的牌点数递增且不少于三张。", + }, + }, + bianzhen: { + mark: true, + trigger: { player: "useCard1" }, + firstDo: true, + charlotte: true, + forced: true, + popup: false, + onremove: true, + filter: function (event, player) { + return player.isPhaseUsing() && player.storage.zhengsu_bianzhen !== false; + }, + content: function () { + var list = player.getHistory("useCard", function (evt) { + return evt.isPhaseUsing(); + }); + var goon = true, suit = get.suit(list[0].card, false); + if (suit == "none") { + goon = false; + } + else { + for (var i = 1; i < list.length; i++) { + if (get.suit(list[i]) != suit) { + goon = false; + break; + } + } + } + if (!goon) { + game.broadcastAll(function (player) { + player.storage.zhengsu_bianzhen = false; + if (player.marks.zhengsu_bianzhen) player.marks.zhengsu_bianzhen.firstChild.innerHTML = "╳"; + }, player); + } + else { + if (list.length > 1) { + game.broadcastAll(function (player) { + if (player.marks.zhengsu_bianzhen) player.marks.zhengsu_bianzhen.firstChild.innerHTML = "○"; + player.storage.zhengsu_bianzhen = true; + }, player); + } + else game.broadcastAll(function (player, suit) { + if (player.marks.zhengsu_bianzhen) player.marks.zhengsu_bianzhen.firstChild.innerHTML = get.translation(suit); + }, player, suit); + } + player.markSkill("zhengsu_bianzhen"); + }, + intro: { + content: "
    • 条件:回合内所有于出牌阶段使用的牌花色相同且不少于两张。", + }, + ai: { + effect: { + player_use: function (card, player, target) { + if (typeof card != "object" || !player.isPhaseUsing()) return; + var suitx = get.suit(card); + var history = player.getHistory("useCard"); + if (!history.length) { + var val = 0; + if (player.hasCard(function (cardx) { + return get.suit(cardx) == suitx && card != cardx && (!card.cards || !card.cards.contains(cardx)) && player.hasValueTarget(cardx); + }, "hs")) val = [2, 0.1]; + if (val) return val; + return; + } + var num = 0; + var suit = false; + for (var i = 0; i < history.length; i++) { + var suit2 = get.suit(history[i].card); + if (!lib.suit.contains(suit2)) return; + if (suit && suit != suit2) return; + suit = suit2; + num++; + } + if (suitx == suit && num == 1) return [1, 0.1]; + if (suitx != suit && (num > 1 || num <= 1 && player.hasCard(function (cardx) { + return get.suit(cardx) == suit && player.hasValueTarget(cardx); + }, "hs"))) return "zeroplayertarget"; + }, + }, + }, + }, + mingzhi: { + mark: true, + trigger: { player: "loseAfter" }, + firstDo: true, + charlotte: true, + forced: true, + popup: false, + onremove: true, + filter: function (event, player) { + if (player.storage.zhengsu_mingzhi === false || event.type != "discard") return false; + var evt = event.getParent("phaseDiscard"); + return evt && evt.player == player; + }, + content: function () { + var goon = true, list = []; + player.getHistory("lose", function (event) { + if (!goon || event.type != "discard") return false; + var evt = event.getParent("phaseDiscard"); + if (evt && evt.player == player) { + for (var i of event.cards2) { + var suit = get.suit(i, player); + if (list.contains(suit)) { + goon = false; + break; + } + else list.push(suit); + } + } + }); + if (!goon) { + game.broadcastAll(function (player) { + player.storage.zhengsu_mingzhi = false; + if (player.marks.zhengsu_mingzhi) player.marks.zhengsu_mingzhi.firstChild.innerHTML = "╳"; + delete player.storage.zhengsu_mingzhi_list; + }, player); + } + else { + if (list.length > 1) { + game.broadcastAll(function (player, list) { + if (player.marks.zhengsu_mingzhi) player.marks.zhengsu_mingzhi.firstChild.innerHTML = "○"; + player.storage.zhengsu_mingzhi = true; + player.storage.zhengsu_mingzhi_list = list; + player.storage.zhengsu_mingzhi_markcount = list.length; + }, player, list); + } + else game.broadcastAll(function (player, list) { + player.storage.zhengsu_mingzhi_list = list; + player.storage.zhengsu_mingzhi_markcount = list.length; + }, player, list); + } + player.markSkill("zhengsu_mingzhi"); + }, + intro: { + content: "
    • 条件:回合内所有于弃牌阶段弃置的牌花色均不相同且不少于两张。", + }, + }, + }, + }, + renku: { + intro: { + markcount: function () { + return _status.renku.length; + }, + mark: function (dialog, content, player) { + if (!_status.renku.length) return "仁库中没有牌"; + else dialog.addAuto(_status.renku); + }, + content: function () { + if (!_status.renku.length) return "仁库中没有牌"; + return get.translation(_status.renku); + }, + }, + }, + _showHiddenCharacter: { + trigger: { player: ["changeHp", "phaseBeginStart", "loseMaxHpBegin", "gainMaxHpBegin"] }, + firstDo: true, + forced: true, + popup: false, + priority: 25, + filter: function (event, player, name) { + return player.isUnseen(2) && get.mode() != "guozhan"; + }, + content: function () { + player.showCharacter(2); + player.removeSkill("g_hidden_ai"); + }, + }, + _kamisha: { + trigger: { source: "damageBegin2" }, + //forced:true, + popup: false, + prompt: function (event, player) { + return "是否防止即将对" + get.translation(event.player) + "造成的伤害,改为令其减少" + get.cnNumber(event.num) + "点体力上限?"; + }, + filter: function (event, player) { + return event.hasNature("kami") && event.num > 0; + }, + ruleSkill: true, + check: function (event, player) { + var att = get.attitude(player, event.player); + if (event.player.hp == event.player.maxHp) return att < 0; + if (event.player.hp == event.player.maxHp - 1 && + (event.player.maxHp <= 3 || event.player.hasSkillTag("maixie"))) return att < 0; + return att > 0; + }, + content: function () { + trigger.cancel(); + trigger.player.loseMaxHp(trigger.num).source = player; + }, + }, + aozhan: { + charlotte: true, + mod: { + targetEnabled: function (card) { + if (card.name == "tao" && (card.isCard && card.cardid || get.itemtype(card) == "card")) return false; + }, + cardSavable: function (card) { + if (card.name == "tao" && (card.isCard && card.cardid || get.itemtype(card) == "card")) return false; + }, + }, + group: ["aozhan_sha", "aozhan_shan"], + subSkill: { + sha: { + enable: ["chooseToUse", "chooseToRespond"], + filterCard: { + name: "tao", + }, + viewAs: { + name: "sha", + isCard: true, + }, + viewAsFilter: function (player) { + if (!player.countCards("hs", "tao")) return false; + }, + position: "hs", + prompt: "将一张桃当杀使用或打出", + check: function () { return 1 }, + ai: { + respondSha: true, + skillTagFilter: function (player) { + if (!player.countCards("hs", "tao")) return false; + }, + order: function () { + return get.order({ name: "sha" }) - 0.1; + }, + }, + sub: true, + }, + shan: { + enable: ["chooseToRespond", "chooseToUse"], + filterCard: { + name: "tao", + }, + viewAs: { + name: "shan", + isCard: true, + }, + prompt: "将一张桃当闪打出", + check: function () { return 1 }, + viewAsFilter: function (player) { + if (!player.countCards("hs", "tao")) return false; + }, + position: "hs", + ai: { + respondShan: true, + skillTagFilter: function (player) { + if (!player.countCards("hs", "tao")) return false; + }, + }, + sub: true, + }, + }, + }, + global: [], + globalmap: {}, + storage: {}, + undist: {}, + others: {}, + zhu: {}, + zhuSkill: {}, + land_used: {}, + unequip: { ai: { unequip: true } }, + subplayer: { + trigger: { player: "dieBefore" }, + forced: true, + priority: -9, + onremove: true, + mark: "character", + intro: { + content: function (storage, player) { + if (typeof storage.intro2 == "string") return storage.intro2; + if (typeof storage.intro2 == "function") return storage.intro2(storage, player); + return "死亡前切换回主武将" + }, + name: function (storage) { + return get.rawName(storage.name); + } + }, + content: function () { + trigger.cancel(); + var evt = trigger.getParent("damage"); + if (evt.player == player) { + evt.untrigger(false, player); + } + player.exitSubPlayer(true); + }, + ai: { + nosave: true + } + }, + autoswap: { + firstDo: true, + trigger: { + player: ["playercontrol", "chooseToUseBegin", "chooseToRespondBegin", "chooseToDiscardBegin", "chooseToCompareBegin", + "chooseButtonBegin", "chooseCardBegin", "chooseTargetBegin", "chooseCardTargetBegin", "chooseControlBegin", + "chooseBoolBegin", "choosePlayerCardBegin", "discardPlayerCardBegin", "gainPlayerCardBegin", "chooseToMoveBegin", "chooseToPlayBeatmapBegin"] + }, + forced: true, + priority: 100, + forceDie: true, + popup: false, + filter: function (event, player) { + if (event.autochoose && event.autochoose()) return false; + if (lib.filter.wuxieSwap(event)) return false; + if (_status.auto || !player.isUnderControl()) return false; + return true; + }, + content: function () { + game.swapPlayerAuto(player); + }, + }, + dualside: { + charlotte: true, + subSkill: { + turn: { + trigger: { player: ["turnOverAfter", "dieBefore"] }, + silent: true, + filter: function (event, player) { + if (player.storage.dualside_over) return false; + return Array.isArray(player.storage.dualside); + }, + content: function () { + var cfg = player.storage.dualside; + var bool = player.isTurnedOver(); + if (trigger.name == "die") { + bool = !bool; + } + if (bool) { + cfg[1] = player.hp; + cfg[2] = player.maxHp; + player.reinit(cfg[0], cfg[3], [cfg[4], cfg[5]]); + player.unmarkSkill("dualside"); + player.markSkillCharacter("dualside", { name: cfg[0] }, "正面", "当前体力:" + cfg[1] + "/" + cfg[2]); + } + else { + cfg[4] = player.hp; + cfg[5] = player.maxHp; + player.reinit(cfg[3], cfg[0], [cfg[1], cfg[2]]); + player.unmarkSkill("dualside"); + player.markSkillCharacter("dualside", { name: cfg[3] }, "背面", "当前体力:" + cfg[4] + "/" + cfg[5]); + } + + if (trigger.name == "die") { + trigger.cancel(); + delete player.storage.dualside; + player.storage.dualside_over = true; + player.unmarkSkill("dualside"); + } + } + }, + init: { + trigger: { global: "gameStart", player: "enterGame" }, + silent: true, + content: function () { + var list = [player.name, player.name1, player.name2]; + for (var i = 0; i < list.length; i++) { + if (list[i] && lib.character[list[i]]) { + var info = lib.character[list[i]]; + if (info[3].contains("dualside") && info[4]) { + player.storage.dualside = [list[i], player.hp, player.maxHp]; + for (var j = 0; j < info[4].length; j++) { + if (info[4][j].startsWith("dualside:")) { + var name2 = info[4][j].slice(9); + var info2 = lib.character[name2]; + player.storage.dualside.push(name2); + player.storage.dualside.push(get.infoHp(info2[2])); + player.storage.dualside.push(get.infoMaxHp(info2[2])); + } + } + } + } + } + var cfg = player.storage.dualside; + if (get.mode() == "guozhan") { + if (player.name1 == cfg[0]) { + player.showCharacter(0); + } + else { + player.showCharacter(1); + } + } + player.markSkillCharacter("dualside", { name: cfg[3] }, "背面", "当前体力:" + cfg[4] + "/" + cfg[5]); + } + } + }, + group: ["dualside_init", "dualside_turn"] + }, + fengyin: { + init: function (player, skill) { + player.addSkillBlocker(skill); + }, + onremove: function (player, skill) { + player.removeSkillBlocker(skill); + }, + charlotte: true, + skillBlocker: function (skill, player) { + return !lib.skill[skill].charlotte && !get.is.locked(skill, player); + }, + mark: true, + intro: { + content: function (storage, player, skill) { + var list = player.getSkills(null, false, false).filter(function (i) { + return lib.skill.fengyin.skillBlocker(i, player); + }); + if (list.length) return "失效技能:" + get.translation(list); + return "无失效技能"; + } + } + }, + baiban: { + init: function (player, skill) { + player.addSkillBlocker(skill); + }, + onremove: function (player, skill) { + player.removeSkillBlocker(skill); + }, + charlotte: true, + skillBlocker: function (skill, player) { + return !lib.skill[skill].charlotte; + }, + mark: true, + intro: { + content: function (storage, player, skill) { + var list = player.getSkills(null, false, false).filter(function (i) { + return lib.skill.baiban.skillBlocker(i, player); + }); + if (list.length) return "失效技能:" + get.translation(list); + return "无失效技能"; + } + } + }, + qianxing: { + mark: true, + nopop: true, + init: function (player) { + game.log(player, "获得了", "【潜行】"); + }, + intro: { + content: "锁定技,你不能成为其他角色的卡牌的目标" + }, + mod: { + targetEnabled: function (card, player, target) { + if (player != target) return false; + } + } + }, + mianyi: { + trigger: { player: "damageBefore" }, + mark: true, + forced: true, + init: function (player) { + game.log(player, "获得了", "【免疫】"); + }, + content: function () { + trigger.cancel(); + }, + ai: { + nofire: true, + nothunder: true, + nodamage: true, + effect: { + target: function (card, player, target, current) { + if (get.tag(card, "damage")) return [0, 0]; + } + }, + }, + intro: { + content: "防止一切伤害" + } + }, + mad: { + mark: true, + locked: true, + intro: { + content: "已进入混乱状态", + name: "混乱", + onunmark: function (storage, player) { + game.log(player, "解除混乱状态"); + } + } + }, + ghujia: { + intro: { + content: function (content, player) { + return "已有" + get.cnNumber(player.hujia) + "点护甲值"; + } + }, + markimage: "image/card/shield.png", + }, + counttrigger: { + trigger: { global: "phaseAfter" }, + silent: true, + charlotte: true, + priority: -100, + lastDo: true, + content: function () { + player.removeSkill("counttrigger"); + delete player.storage.counttrigger; + }, + group: "counttrigger_2", + subSkill: { + 2: { + trigger: { global: ["phaseBeforeStart", "roundStart"] }, + silent: true, + charlotte: true, + firstDo: true, + priority: 100, + content: function () { + player.removeSkill("counttrigger"); + delete player.storage.counttrigger; + }, + } + } + }, + _recovercheck: { + trigger: { player: "recoverBefore" }, + forced: true, + priority: 100, + firstDo: true, + popup: false, + filter: function (event, player) { + return player.hp >= player.maxHp; + }, + content: function () { + trigger.cancel(); + }, + }, + _usecard: { + trigger: { global: "useCardAfter" }, + forced: true, + popup: false, + priority: -100, + lastDo: true, + filter: function (event) { + return !event._cleared && event.card.name != "wuxie"; + }, + content: function () { + game.broadcastAll(function () { + ui.clear(); + }); + event._cleared = true; + } + }, + _discard: { + trigger: { global: ["discardAfter", "loseToDiscardpileAfter", "loseAsyncAfter"] }, + forced: true, + popup: false, + priority: -100, + lastDo: true, + filter: function (event) { + return ui.todiscard[event.discardid] ? true : false; + }, + content: function () { + game.broadcastAll(function (id) { + var todiscard = ui.todiscard[id]; + delete ui.todiscard[id]; + if (todiscard) { + var time = 1000; + if (typeof todiscard._discardtime == "number") { + time += todiscard._discardtime - get.time(); + } + if (time < 0) { + time = 0; + } + setTimeout(function () { + for (var i = 0; i < todiscard.length; i++) { + todiscard[i].delete(); + } + }, time); + } + }, trigger.discardid); + } + }, + _save: { + priority: 5, + forced: true, + popup: false, + filter: function (event, player) { + return false; + }, + content: function () { + "step 0" + event.dying = trigger.player; + if (!event.acted) event.acted = []; + "step 1" + if (trigger.player.isDead()) { + event.finish(); + return; + } + event.acted.push(player); + var str = get.translation(trigger.player) + "濒死,是否帮助?"; + var str2 = "当前体力:" + trigger.player.hp; + if (lib.config.tao_enemy && event.dying.side != player.side && lib.config.mode != "identity" && lib.config.mode != "guozhan" && !event.dying.hasSkillTag("revertsave")) { + event._result = { bool: false } + } + else if (player.canSave(event.dying)) { + player.chooseToUse({ + filterCard: function (card, player, event) { + event = event || _status.event; + return lib.filter.cardSavable(card, player, event.dying); + }, + filterTarget: function (card, player, target) { + if (target != _status.event.dying) return false; + if (!card) return false; + var info = get.info(card); + if (!info.singleCard || ui.selected.targets.length == 0) { + var mod = game.checkMod(card, player, target, "unchanged", "playerEnabled", player); + if (mod == false) return false; + var mod = game.checkMod(card, player, target, "unchanged", "targetEnabled", target); + if (mod != "unchanged") return mod; + } + return true; + }, + prompt: str, + prompt2: str2, + ai1: function (card) { + if (typeof card == "string") { + var info = get.info(card); + if (info.ai && info.ai.order) { + if (typeof info.ai.order == "number") { + return info.ai.order; + } + else if (typeof info.ai.order == "function") { + return info.ai.order(); + } + } + } + return 1; + }, + ai2: get.effect_use, + type: "dying", + targetRequired: true, + dying: event.dying + }); + } + else { + event._result = { bool: false } + } + "step 2" + if (result.bool) { + var player = trigger.player; + if (player.hp <= 0 && !trigger.nodying && !player.nodying && player.isAlive() && !player.isOut() && !player.removed) event.goto(0); + else trigger.untrigger(); + } + else { + for (var i = 0; i < 20; i++) { + if (event.acted.contains(event.player.next)) { + break; + } + else { + event.player = event.player.next; + if (!event.player.isOut()) { + event.goto(1); + break; + } + } + } + } + } + }, + _ismin: { + mod: { + cardEnabled: function (card, player) { + if (player.isMin()) { + if (get.type(card) == "equip") return false; + } + } + } + }, + _recasting: { + enable: "phaseUse", + logv: false, + prompt: "将要重铸的牌置入弃牌堆并摸一张牌", + filter: (event, player) => player.hasCard(card => lib.skill._recasting.filterCard(card, player), lib.skill._recasting.position), + position: "he", + filterCard: (card, player) => player.canRecast(card, null, true), + discard: false, + lose: false, + delay: false, + content: () => { + player.recast(cards, null, (player, cards) => { + var numberOfCardsToDraw = cards.length; + cards.forEach(value => { + if (lib.config.mode == "stone" && _status.mode == "deck" && !player.isMin() && get.type(value).startsWith("stone")) { + var stonecard = get.stonecard(1, player.career); + if (stonecard.length) { + numberOfCardsToDraw -= stonecard.length; + player.gain(game.createCard(stonecard.randomGet()), "draw"); + } + else player.draw({ + drawDeck: 1 + }).log = false; + } + else if (get.subtype(value) == "spell_gold") { + var libCard = get.libCard(info => info.subtype == "spell_silver"); + if (!libCard.length) return; + numberOfCardsToDraw--; + player.gain(game.createCard(libCard.randomGet()), "draw"); + } + else if (get.subtype(value) == "spell_silver") { + var libCard = get.libCard(info => info.subtype == "spell_bronze"); + if (!libCard.length) return; + numberOfCardsToDraw--; + player.gain(game.createCard(libCard.randomGet()), "draw"); + } + }); + if (numberOfCardsToDraw) player.draw(numberOfCardsToDraw).log = false; + }); + }, + ai: { + basic: { + order: 6 + }, + result: { + player: 1 + } + } + }, + _lianhuan: { + trigger: { player: "damageAfter" }, + filter: function (event, player) { + return event.lianhuanable == true; + }, + forced: true, + popup: false, + logv: false, + forceDie: true, + //priority:-5, + content: function () { + "step 0" + event.logvid = trigger.getLogv(); + "step 1" + event.targets = game.filterPlayer(function (current) { + return current != event.player && current.isLinked(); + }); + lib.tempSortSeat = _status.currentPhase || player; + event.targets.sort(lib.sort.seat); + delete lib.tempSortSeat; + event._args = [trigger.num, trigger.nature, trigger.cards, trigger.card]; + if (trigger.source) event._args.push(trigger.source); + else event._args.push("nosource"); + "step 2" + if (event.targets.length) { + var target = event.targets.shift(); + if (target.isLinked()) target.damage.apply(target, event._args.slice(0)); + event.redo(); + } + }, + }, + _lianhuan4: { + trigger: { player: "changeHp" }, + priority: -10, + forced: true, + popup: false, + forceDie: true, + filter: function (event, player) { + var evt = event.getParent(); + return evt && evt.name == "damage" && evt.hasNature("linked") && player.isLinked(); + }, + content: function () { + player.link(); + if (trigger.getParent().notLink()) trigger.getParent().lianhuanable = true; + } + }, + /** + * @deprecated + */ + _chongzhu: { + get filter() { + return lib.skill._recasting.filter; + }, + set filter(filter) { + lib.skill._recasting.filter = filter; + }, + get filterCard() { + return lib.skill._recasting.filterCard; + }, + set filterCard(filterCard) { + lib.skill._recasting.filterCard = filterCard; + }, + get content() { + return lib.skill._recasting.content; + }, + set content(content) { + lib.skill._recasting.content = content; + }, + get ai() { + return lib.skill._recasting.ai; + }, + set ai(ai) { + lib.skill._recasting.ai = ai; + } + } +}; diff --git a/noname/library/sort.js b/noname/library/sort.js new file mode 100644 index 000000000..54375c6b1 --- /dev/null +++ b/noname/library/sort.js @@ -0,0 +1,133 @@ +export class Sort { + constructor() { + throw new TypeError(`${new.target.name} is not a constructor`); + } + static nature(a, b) { + return (lib.nature.get(b) || 0) - (lib.nature.get(a) || 0); + } + static group(a, b) { + const groupSort = function (group) { + let base = 0; + if (group == "wei") return base; + if (group == "shu") return base + 1; + if (group == "wu") return base + 2; + if (group == "qun") return base + 3; + if (group == "jin") return base + 4; + if (group == "key") return base + 5; + if (group == "western") return base + 6; + if (group == "shen") return base + 7; + if (group == "double") return base + 7; + return base + 9; + } + return groupSort(a) - groupSort(b); + } + static character(a, b) { + const groupSort = function (name) { + const info = get.character(name); + if (!info) return 7; + let base = 0; + if (get.is.double(name, true)) base = 9; + const group = info[1]; + if (group == "shen") return base - 1; + if (group == "wei") return base; + if (group == "shu") return base + 1; + if (group == "wu") return base + 2; + if (group == "qun") return base + 3; + if (group == "jin") return base + 4; + if (group == "key") return base + 5; + if (group == "western") return base + 6; + return base + 7; + } + const del = groupSort(a) - groupSort(b); + if (del != 0) return del; + let aa = a, bb = b; + if (a.includes("_")) { + a = a.slice(a.indexOf("_") + 1); + } + if (b.includes("_")) { + b = b.slice(b.indexOf("_") + 1); + } + if (a != b) { + return a > b ? 1 : -1; + } + return aa > bb ? 1 : -1; + } + static card(a, b) { + var typeSort = function (name) { + var type = get.type(name); + if (!type) return 10; + if (type == "basic") return -1; + if (type == "trick") return 0; + if (type == "delay") return 1; + if (type == "equip") { + var type2 = get.subtype(name, false); + if (type2 && type2.slice) return 1 + parseInt(type2.slice(5) || 7); + return 8.5 + } + return 9; + } + var del = typeSort(a) - typeSort(b); + if (del != 0) return del; + var aa = a, bb = b; + if (a.includes("_")) { + a = a.slice(a.indexOf("_") + 1); + } + if (b.includes("_")) { + b = b.slice(b.indexOf("_") + 1); + } + if (a != b) { + return a > b ? 1 : -1; + } + return aa > bb ? 1 : -1; + } + static random() { + return (Math.random() - 0.5); + } + static seat(a, b) { + var player = lib.tempSortSeat || _status.event.player; + var delta = get.distance(player, a, "absolute") - get.distance(player, b, "absolute"); + if (delta) return delta; + delta = parseInt(a.dataset.position) - parseInt(b.dataset.position); + if (player.side == game.me.side) return delta; + return -delta; + } + static position(a, b) { + return parseInt(a.dataset.position) - parseInt(b.dataset.position); + } + static priority(a, b) { + var i1 = get.info(a[0]), i2 = get.info(b[0]); + if (i1.priority == undefined) i1.priority = 0; + if (i2.priority == undefined) i2.priority = 0; + if (i1.priority == i2.priority) { + if (i1.forced == undefined && i2.forced == undefined) return 0; + if (i1.forced && i2.forced) return 0; + if (i1.forced) return 1; + if (i2.forced) return -1; + } + return i2.priority - i1.priority; + } + static number(a, b) { + return get.number(a) - get.number(b); + } + static number2(a, b) { + return get.number(b) - get.number(a); + } + static capt(a, b) { + var aa = a, bb = b; + if (aa.includes("_")) { + aa = aa.slice(aa.indexOf("_") + 1); + } + if (bb.includes("_")) { + bb = bb.slice(bb.indexOf("_") + 1); + } + if (aa != bb) { + return aa > bb ? 1 : -1; + } + return a > b ? 1 : -1; + } + static name(a, b) { + if (a > b) return 1; + if (a < b) return -1; + return 0; + } +} diff --git a/noname/library/translate.js b/noname/library/translate.js new file mode 100644 index 000000000..dfdcbaea5 --- /dev/null +++ b/noname/library/translate.js @@ -0,0 +1,217 @@ +export const translate = { + flower: "鲜花", + egg: "鸡蛋", + wine: "酒杯", + shoe: "拖鞋", + yuxisx: "玉玺", + jiasuo: "枷锁", + junk: "平凡", + common: "普通", + rare: "精品", + epic: "史诗", + legend: "传说", + default: "默认", + special: "特殊", + zhenfa: "阵法", + aozhan: "鏖战", + mode_derivation_card_config: "衍生", + mode_banned_card_config: "禁卡", + mode_favourite_character_config: "收藏", + mode_banned_character_config: "禁将", + heart: "♥︎", + diamond: "♦︎", + spade: "♠︎", + club: "♣︎", + none: "◈", + ghujia: "护甲", + ghujia_bg: "甲", + heart2: "红桃", + diamond2: "方片", + spade2: "黑桃", + club2: "梅花", + none2: "无色", + red: "红色", + black: "黑色", + ok: "确定", + ok2: "确定", + cancel: "取消", + cancel2: "取消", + restart: "重新开始", + setting: "设置", + start: "开始", + random: "随机", + _out: "无效", + agree: "同意", + refuse: "拒绝", + fire: "火", + thunder: "雷", + poison: "毒", + kami: "神", + ice: "冰", + stab: "刺", + wei: "魏", + shu: "蜀", + wu: "吴", + qun: "群", + shen: "神", + western: "西", + key: "键", + jin: "晋", + double: "双", + wei2: "魏国", + shu2: "蜀国", + wu2: "吴国", + qun2: "群雄", + shen2: "神明", + western2: "西方", + key2: "KEY", + jin2: "晋朝", + double2: "双势力", + male: "男", + female: "女", + mad: "混乱", + mad_bg: "疯", + draw_card: "摸牌", + discard_card: "弃牌", + take_damage: "受伤害", + reset_character: "复原武将牌", + recover_hp: "回复体力", + lose_hp: "失去体力", + get_damage: "受伤害", + weiColor: "#b0d0e2", + shuColor: "#ffddb9", + wuColor: "#b2d9a9", + qunColor: "#f6f6f6", + shenColor: "#ffe14c", + westernColor: "#ffe14c", + jinColor: "#ffe14c", + keyColor: "#c9b1fd", + basic: "基本", + equip: "装备", + trick: "锦囊", + delay: "延时锦囊", + character: "角色", + revive: "复活", + equip1: "武器", + equip2: "防具", + equip3: "防御马", + "equip3_4": "坐骑", + equip4: "攻击马", + equip5: "宝物", + equip6: "特殊装备", + zero: "零", + one: "一", + two: "二", + three: "三", + four: "四", + five: "五", + six: "六", + seven: "七", + eight: "八", + nine: "九", + ten: "十", + _recasting: "重铸", + _lianhuan: "连环", + _lianhuan2: "连环", + _kamisha: "神杀", + _icesha: "冰杀", + qianxing: "潜行", + mianyi: "免疫", + fengyin: "封印", + baiban: "白板", + _disableJudge: "判定区", + + xiaowu_emotion: "小无表情", + guojia_emotion: "郭嘉表情", + zhenji_emotion: "甄姬表情", + shibing_emotion: "士兵表情", + xiaosha_emotion: "小杀表情", + xiaotao_emotion: "小桃表情", + xiaojiu_emotion: "小酒表情", + xiaokuo_emotion: "小扩表情", + + pause: "暂停", + config: "选项", + auto: "托管", + + unknown: "未知", + unknown0: "一号位", + unknown1: "二号位", + unknown2: "三号位", + unknown3: "四号位", + unknown4: "五号位", + unknown5: "六号位", + unknown6: "七号位", + unknown7: "八号位", + unknown8: "九号位", + unknown9: "十号位", + unknown10: "十一号位", + unknown11: "十二号位", + + feichu_equip1: "已废除", + feichu_equip1_info: "武器栏已废除", + feichu_equip2: "已废除", + feichu_equip2_info: "防具栏已废除", + feichu_equip3: "已废除", + feichu_equip3_info: "防御坐骑栏已废除", + feichu_equip4: "已废除", + feichu_equip4_info: "攻击坐骑栏已废除", + feichu_equip5: "已废除", + feichu_equip5_info: "宝物栏已废除", + feichu_equip6: "已废除", + feichu_equip6_info: "特殊装备栏已废除", + feichu_equip1_bg: "废", + feichu_equip2_bg: "废", + feichu_equip3_bg: "废", + feichu_equip4_bg: "废", + feichu_equip5_bg: "废", + feichu_equip6_bg: "废", + disable_judge: "已废除", + disable_judge_info: "判定区已废除", + disable_judge_bg: "废", + pss: "手势", + pss_paper: "布", + pss_scissor: "剪刀", + pss_stone: "石头", + pss_paper_info: "石头剪刀布时的一种手势。克制石头,但被剪刀克制。", + pss_scissor_info: "石头剪刀布时的一种手势。克制布,但被石头克制。", + pss_stone_info: "石头剪刀布时的一种手势。克制剪刀,但被布克制。", + renku: "仁库", + group_wei: "魏势力", + group_shu: "蜀势力", + group_wu: "吴势力", + group_qun: "群势力", + group_key: "键势力", + group_jin: "晋势力", + group_wei_bg: "魏", + group_shu_bg: "蜀", + group_wu_bg: "吴", + group_qun_bg: "群", + group_key_bg: "键", + group_jin_bg: "晋", + zhengsu: "整肃", + zhengsu_leijin: "擂进", + zhengsu_bianzhen: "变阵", + zhengsu_mingzhi: "鸣止", + zhengsu_leijin_info: "回合内所有于出牌阶段使用的牌点数递增且不少于三张。", + zhengsu_bianzhen_info: "回合内所有于出牌阶段使用的牌花色相同且不少于两张。", + zhengsu_mingzhi_info: "回合内所有于弃牌阶段弃置的牌花色均不相同且不少于两张。", + db_atk: "策略", + db_atk1: "全军出击", + db_atk2: "分兵围城", + db_def: "策略", + db_def1: "奇袭粮道", + db_def2: "开城诱敌", + cooperation_damage: "同仇", + cooperation_damage_info: "双方累计造成至少4点伤害", + cooperation_draw: "并进", + cooperation_draw_info: "双方累计摸至少八张牌", + cooperation_discard: "疏财", + cooperation_discard_info: "双方累计弃置至少4种花色的牌", + cooperation_use: "戮力", + cooperation_use_info: "双方累计使用至少4种花色的牌", + charge: "蓄力值", + expandedSlots: "扩展装备栏", + stratagem_fury: "怒气", + _stratagem_add_buff: "强化" +}; diff --git a/noname/status.js b/noname/status.js index 4a54b1d68..da2043a33 100644 --- a/noname/status.js +++ b/noname/status.js @@ -1,7 +1,7 @@ import { GameEvent } from "./library/element/game-event.js"; -import { ai } from "./status/ai.js"; -import { cardTag } from "./status/card-tag.js"; -import { postReconnect } from "./status/post-reconnect.js"; +import { ai } from "./game-status/ai.js"; +import { cardTag } from "./game-status/card-tag.js"; +import { postReconnect } from "./game-status/post-reconnect.js"; export const status = { paused: false, @@ -11,14 +11,14 @@ export const status = { clicked: false, auto: false, event: GameEvent.initialGameEvent(), - ai, + ai: ai, lastdragchange: [], skillaudio: [], dieClose: [], dragline: [], dying: [], /** - * @type {import("./status/global-history.js").GlobalHistory[]} + * @type {import("./game-status/global-history.js").GlobalHistory[]} */ globalHistory: [{ cardMove: [],