Migrate `Library`.

This commit is contained in:
Tipx-L 2023-12-11 22:07:18 -08:00
parent a04a2d4732
commit eff1fdd8a6
46 changed files with 30935 additions and 39 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1 @@
export { Library as InternalLibrary } from "../library.js";

View File

@ -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: "",
}],
["经典", {
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 = "赋值中的左侧无效即numberstring等不可赋值的非变量数据";
}
} 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 = "请在严格模式下运行letconstclass";
} 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 its 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);
}
}

View File

@ -0,0 +1 @@
export const cardPile = {};

93
noname/library/card.js Normal file
View File

@ -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
}
};

View File

@ -0,0 +1 @@
export const character = {};

View File

@ -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();
}
}

5
noname/library/color.js Normal file
View File

@ -0,0 +1,5 @@
export const color = {
black: ["club", "spade"],
red: ["diamond", "heart"],
none: ["none"]
};

View File

@ -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;
}
}

View File

@ -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, "", "<div></div><div></div><div></div><div></div>");
}
},
onclick: gnc.of(function* (theme) {
onclick: GNC.of(function* (theme) {
Game.saveConfig("theme", theme);
UI.arena.hide();
Initialization.background();

View File

@ -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 "";
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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;
}
}

View File

@ -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])}<span style="font-family:xinwei"> </span><span style="font-family:xinwei">${cardnum}</span>`;
}
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 = ` <span class="cardtag">`;
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<tags.length-1) tagstr+=" ";
}
tagstr += "</span>";
this.node.range.innerHTML += tagstr;
}
}
return this;
}
updateTransform(bool, delay) {
if (delay) {
var that = this;
setTimeout(function () {
that.updateTransform(that.classList.contains("selected"));
}, delay);
}
else {
if (_status.event.player != game.me) return;
if (this._transform && this.parentNode && this.parentNode.parentNode &&
this.parentNode.parentNode.parentNode == ui.me &&
(!_status.mousedown || _status.mouseleft) &&
(!this.parentNode.parentNode.classList.contains("scrollh") || (game.layout == "long2" || game.layout == "nova"))) {
if (bool) {
this.style.transform = this._transform + " translateY(-20px)";
}
else {
this.style.transform = this._transform || "";
}
}
}
}
aiexclude() {
_status.event._aiexclude.add(this);
}
//为此牌添加知情者。参数可为数组,若参数为字符串"everyone",则所有玩家均为知情者。
addKnower(player) {
if (!this._knowers) {
this._knowers = [];
}
if (typeof player == "string") {
this._knowers.add(player);
} else {
let type = get.itemtype(player);
if (type == "player") {
this._knowers.add(player.playerid);
} else if (type == "players") {
player.forEach(p => 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));
}
}

View File

@ -0,0 +1,61 @@
export class Client {
/**
* @param {NodeWS | InstanceType<typeof import("ws").WebSocket>} 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;
}
}

View File

@ -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;
}
}

View File

@ -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("<div")) this.add(str);
else if (center !== false) {
this.add(`<div class="text center">${str}</div>`);
}
else {
this.add(`<div class="text">${str}</div>`);
}
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;
}
}

View File

@ -0,0 +1,74 @@
export class GameEventPromise extends Promise {
// 我谢谢你,这里是必须有的
// 否则Promise的方法对其子类无效
static get [Symbol.species]() {
return Promise;
}
/**
* @param { GameEvent } event
* @returns { Promise<GameEvent> & 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);
});
}
}

View File

@ -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<typeof this.hasHandler>[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<typeof this.hasHandler>[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<string>}`} [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<typeof this.hasHandler>[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> | 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<string, any>}
*/
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> & GameEvent }
*/
toPromise() {
if (this.async && this.resolve) {
throw new TypeError("This event has been converted into a promise");
}
return new lib.element.GameEventPromise(this);
}
}

View File

@ -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);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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<string, any>}
*/
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);
}
}

View File

@ -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;
}
}

453
noname/library/filter.js Normal file
View File

@ -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 players 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;
}
}
}
}
}

View File

@ -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"
};

32
noname/library/help.js Normal file
View File

@ -0,0 +1,32 @@
export const HELP = {
关于游戏: `<div style="margin:10px">关于无名杀</div><ul style="margin-top:0"><li>无名杀官方发布地址仅有GitHub仓库<br><a href="https://github.com/libccy/noname">点击前往Github仓库</a><br><li>无名杀基于GPLv3开源协议。<br><a href="https://www.gnu.org/licenses/gpl-3.0.html">点击查看GPLv3协议</a><br><li>其他所有的所谓“无名杀”社群包括但不限于绝大多数“官方”QQ群、QQ频道等均为玩家自发组织与无名杀官方无关`,
游戏操作: "<ul><li>长按/鼠标悬停/右键单击显示信息。<li>触屏模式中,双指点击切换暂停;下划显示菜单,上划切换托管。<li>键盘快捷键<br>" +
"<table><tr><td>A<td>切换托管<tr><td>W<td>切换不询问无懈<tr><td>空格<td>暂停</table><li>编辑牌堆<br>在卡牌包中修改牌堆后,将自动创建一个临时牌堆,在所有模式中共用,当保存当前牌堆后,临时牌堆被清除。每个模式可设置不同的已保存牌堆,设置的牌堆优先级大于临时牌堆。</ul>",
游戏命令: `<div style="margin:10px">变量名</div><ul style="margin-top:0"><li>场上角色<br>game.players<li>阵亡角色<br>game.dead` +
"<li>玩家<br>game.me<li>玩家的上/下家<br>game.me.previous/next" +
"<li>玩家的上/下家(含阵亡)<br>game.me.previousSeat/<br>nextSeat" +
"<li>牌堆<br>ui.cardPile<li>弃牌堆<br>ui.discardPile</ul>" +
`<div style="margin:10px">角色属性</div><ul style="margin-top:0"><li>体力值<br>player.hp` +
`<li>体力上限<br>player.maxHp<li>身份<br>player.identity<li>手牌<br>player.getCards("h")<li>装备牌<br>player.getCards("e")<li>判定牌<br>player.getCards("j")` +
"<li>是否存活/横置/翻面<br>player.isAlive()/<br>isLinked()/<br>isTurnedOver()</ul>" +
`<div style="margin:10px">角色操作</div><ul style="margin-top:0"><li>受到伤害<br>player.damage(source,<br>num)` +
"<li>回复体力<br>player.recover(num)<li>摸牌<br>player.draw(num)<li>获得牌<br>player.gain(cards)<li>弃牌<br>player.discard(cards)" +
"<li>使用卡牌<br>player.useCard(card,<br>targets)<li>死亡<br>player.die()<li>复活<br>player.revive(hp)</ul>" +
`<div style="margin:10px">游戏操作</div><ul style="margin-top:0"><li>在命令框中输出结果<br>game.print(str)<li>清除命令框中的内容<br>cls<li>上一条/下一条输入的内容<br>up/down<li>游戏结束<br>game.over(bool)` +
"<li>角色资料<br>lib.character<li>卡牌资料<br>lib.card</ul>",
游戏名词: "<ul><li>智囊:无名杀默认为过河拆桥/无懈可击/无中生有/洞烛先机。牌堆中没有的智囊牌会被过滤。可在卡牌设置中自行增减。若没有可用的智囊,则改为随机选取的三种锦囊牌的牌名。" +
"<li>仁库:部分武将使用的游戏外共通区域。至多包含六张牌。当有新牌注入后,若牌数超过上限,则将最早进入仁库的溢出牌置入弃牌堆。" +
"<li>护甲和体力类似每点护甲可抵挡1点伤害但不影响手牌上限。" +
"<li>随从:通过技能获得,拥有独立的技能、手牌区和装备区(共享判定区),出场时替代主武将的位置;随从死亡时自动切换回主武将。" +
"<li>发现:从三张随机亮出的牌中选择一张,若无特殊说明,则获得此牌。" +
"<li>蓄能技:发动时可以增大黄色的数字。若如此做,红色数字于技能的结算过程中改为原来的两倍。" +
"<li>施法若技能的拥有者未拥有等待执行的同名“施法”效果则其可以发动“施法”技能。其须选择声明一个数字XX∈[1, 3]在此之后的第X个回合结束时其执行“施法”效果且效果中的数字X视为与技能发动者声明的X相同。" +
"<li>共同拼点:一种特殊的拼点结算。发起者与被指定的拼点目标同时亮出拼点牌,进行一次决算:其中拼点牌点数唯一最大的角色赢,其他角色均没赢;若没有点数唯一最大的拼点牌,则所有角色拼点均没赢。" +
"<li>强令:若一名角色拥有带有“强令”的技能,则该技能的发动时机为“出牌阶段开始时”。若技能拥有者发动该技能,其须发布“强令”给一名其他角色,并在对应技能的时间节点加以判断目标角色是否成功完成该强令所要求的任务条件。成功或失败则会根据技能效果执行不同结算流程。" +
"<li>摧坚若一名角色拥有带有“摧坚”的技能则该技能的发动时机为“当你使用伤害牌指定第一个目标后”。你可以对其中一个目标发动“摧坚”技能然后执行后续效果。其中后续效果里的X等于该目标的非charlotte技能的数量。" +
"<li>妄行一种特殊的选项。若一名角色拥有带有“妄行”的技能则该技能触发时你须选择声明一个数字XX∈{1,2,3,4}技能后续中的X即为你选择的数字。选择完毕后你获得如下效果回合结束时你选择一项1.弃置X张牌2.减1点体力上限。" +
"<li>搏击:若一名角色拥有带有“搏击”的技能,则当该搏击技能触发时,若本次技能的目标角色在你攻击范围内,且你在其攻击范围内,则你执行技能主体效果时,同时额外执行“搏击”后的额外效果。" +
"<li>游击:若一名角色拥有带有“游击”的技能,则当该游击技能执行至“游击”处时,若本次技能的目标角色在你的攻击范围内,且你不在其攻击范围内,则你可以执行“游击”后的额外效果。" +
"<li>激昂:一名角色发动“昂扬技”标签技能后,此技能失效,直至从此刻至满足此技能“激昂”条件后。" +
""
};

File diff suppressed because it is too large Load Diff

View File

@ -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<Event>}
*/
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<HTMLLinkElement>}
*/
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<ProgressEvent>}
*/
req(str, master) {
return new Promise((resolve, reject) => Initialization.req(str, resolve, reject, master));
}
/**
* Promise版的`Initialization.json`
*
* @param {string} url - 要读取的地址
* @returns {Promise<object>}
*/
json(url) {
return new Promise((resolve, reject) => Initialization.json(url, resolve, reject));
}
/**
* Promise版的`Initialization.sheet`
*
* @returns {Promise<HTMLStyleElement>}
*/
sheet() {
return new Promise((resolve, reject) => {
const style = Initialization.sheet(...arguments);
style.addEventListener("load", () => resolve(style));
style.addEventListener("error", reject);
});
}
}

View File

@ -0,0 +1,10 @@
export const internalStatus = {
running: false,
canvas: false,
time: 0,
reload: 0,
delayed: 0,
frameId: 0,
videoId: 0,
globalId: 0
};

106
noname/library/linq.js Normal file
View File

@ -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));
}
}
};

1092
noname/library/message.js Normal file

File diff suppressed because it is too large Load Diff

2453
noname/library/mode.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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"
}
*/
}
};

7
noname/library/other.js Normal file
View File

@ -0,0 +1,7 @@
export class Other {
constructor() {
throw new TypeError(`${new.target.name} is not a constructor`);
}
static ignore() { }
}

View File

@ -0,0 +1 @@
export const perfectPair = {};

1307
noname/library/skill.js Normal file

File diff suppressed because it is too large Load Diff

133
noname/library/sort.js Normal file
View File

@ -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;
}
}

217
noname/library/translate.js Normal file
View File

@ -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: "强化"
};

View File

@ -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: [],