Change the structure.
This commit is contained in:
parent
611658114f
commit
c53db8f4f5
|
@ -1,4 +0,0 @@
|
|||
export * from "./noname/ai.js";
|
||||
export * from "./noname/status.js";
|
||||
export * from "./noname/library.js";
|
||||
export * from "./noname/get.js";
|
|
@ -1,7 +1,7 @@
|
|||
import { Get } from "../noname.js";
|
||||
import { BasicAI } from "./ai/basic.js";
|
||||
import { Basic } from "./ai/basic.js";
|
||||
import { Get } from "./get.js";
|
||||
|
||||
export const ai = {
|
||||
basic: BasicAI,
|
||||
basic: Basic,
|
||||
get: Get
|
||||
};
|
||||
|
|
|
@ -1,24 +1,32 @@
|
|||
import { status as _status } from "../../noname.js";
|
||||
import { Game } from "../game.js";
|
||||
import { Get } from "../get.js";
|
||||
import { status } from "../status.js";
|
||||
import { Click } from "../ui/click.js";
|
||||
import { selected } from "../ui/selected.js";
|
||||
|
||||
export class Basic {
|
||||
constructor() {
|
||||
throw new TypeError(`${new.target.name} is not a constructor`);
|
||||
}
|
||||
|
||||
export class BasicAI {
|
||||
static chooseButton(check) {
|
||||
var event = _status.event;
|
||||
var event = status.event;
|
||||
var i, j, range, buttons, buttons2;
|
||||
var ok = false, forced = event.forced;
|
||||
var iwhile = 100;
|
||||
while (iwhile--) {
|
||||
range = get.select(event.selectButton);
|
||||
if (ui.selected.buttons.length >= range[0]) {
|
||||
range = Get.select(event.selectButton);
|
||||
if (selected.buttons.length >= range[0]) {
|
||||
ok = true;
|
||||
}
|
||||
if (range[1] <= -1) {
|
||||
j = 0;
|
||||
for (i = 0; i < ui.selected.buttons.length; i++) {
|
||||
j += check(ui.selected.buttons[i]);
|
||||
for (i = 0; i < selected.buttons.length; i++) {
|
||||
j += check(selected.buttons[i]);
|
||||
}
|
||||
return (j > 0);
|
||||
}
|
||||
buttons = get.selectableButtons();
|
||||
buttons = Get.selectableButtons();
|
||||
if (buttons.length == 0) {
|
||||
return ok;
|
||||
}
|
||||
|
@ -41,40 +49,41 @@ export class BasicAI {
|
|||
}
|
||||
}
|
||||
buttons[ix].classList.add('selected');
|
||||
ui.selected.buttons.add(buttons[ix]);
|
||||
game.check();
|
||||
if (ui.selected.buttons.length >= range[0]) {
|
||||
selected.buttons.add(buttons[ix]);
|
||||
Game.check();
|
||||
if (selected.buttons.length >= range[0]) {
|
||||
ok = true;
|
||||
}
|
||||
if (ui.selected.buttons.length == range[1]) {
|
||||
if (selected.buttons.length == range[1]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static chooseCard(check) {
|
||||
var event = _status.event;
|
||||
var event = status.event;
|
||||
if (event.filterCard == undefined) return (check() > 0);
|
||||
var i, j, range, cards, cards2, skills, check, effect;
|
||||
var ok = false, forced = event.forced;
|
||||
var iwhile = 100;
|
||||
while (iwhile--) {
|
||||
range = get.select(event.selectCard);
|
||||
if (ui.selected.cards.length >= range[0]) {
|
||||
range = Get.select(event.selectCard);
|
||||
if (selected.cards.length >= range[0]) {
|
||||
ok = true;
|
||||
}
|
||||
if (range[1] <= -1) {
|
||||
if (ui.selected.cards.length == 0) return true;
|
||||
if (selected.cards.length == 0) return true;
|
||||
j = 0;
|
||||
for (i = 0; i < ui.selected.cards.length; i++) {
|
||||
effect = check(ui.selected.cards[i]);
|
||||
for (i = 0; i < selected.cards.length; i++) {
|
||||
effect = check(selected.cards[i]);
|
||||
if (effect < 0) j -= Math.sqrt(-effect);
|
||||
else j += Math.sqrt(effect);
|
||||
}
|
||||
return (j > 0);
|
||||
}
|
||||
cards = get.selectableCards();
|
||||
if (!_status.event.player._noSkill) {
|
||||
cards = cards.concat(get.skills());
|
||||
cards = Get.selectableCards();
|
||||
if (!status.event.player._noSkill) {
|
||||
cards = cards.concat(Get.skills());
|
||||
}
|
||||
if (cards.length == 0) {
|
||||
return ok;
|
||||
|
@ -98,11 +107,11 @@ export class BasicAI {
|
|||
}
|
||||
}
|
||||
if (typeof cards[ix] == 'string') {
|
||||
ui.click.skill(cards[ix]);
|
||||
var info = get.info(event.skill);
|
||||
Click.skill(cards[ix]);
|
||||
var info = Get.info(event.skill);
|
||||
if (info.filterCard) {
|
||||
check = info.check || get.unuseful2;
|
||||
return (ai.basic.chooseCard(check));
|
||||
check = info.check || Get.unuseful2;
|
||||
return (this.chooseCard(check));
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
|
@ -110,32 +119,33 @@ export class BasicAI {
|
|||
}
|
||||
else {
|
||||
cards[ix].classList.add('selected');
|
||||
ui.selected.cards.add(cards[ix]);
|
||||
game.check();
|
||||
if (ui.selected.cards.length >= range[0]) {
|
||||
selected.cards.add(cards[ix]);
|
||||
Game.check();
|
||||
if (selected.cards.length >= range[0]) {
|
||||
ok = true;
|
||||
}
|
||||
if (ui.selected.cards.length == range[1]) {
|
||||
if (selected.cards.length == range[1]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static chooseTarget(check) {
|
||||
var event = _status.event;
|
||||
var event = status.event;
|
||||
if (event.filterTarget == undefined) return (check() > 0);
|
||||
var i, j, range, targets, targets2, effect;
|
||||
var ok = false, forced = event.forced;
|
||||
var iwhile = 100;
|
||||
while (iwhile--) {
|
||||
range = get.select(event.selectTarget);
|
||||
if (ui.selected.targets.length >= range[0]) {
|
||||
range = Get.select(event.selectTarget);
|
||||
if (selected.targets.length >= range[0]) {
|
||||
ok = true;
|
||||
}
|
||||
if (range[1] <= -1) {
|
||||
j = 0;
|
||||
for (i = 0; i < ui.selected.targets.length; i++) {
|
||||
effect = check(ui.selected.targets[i]);
|
||||
for (i = 0; i < selected.targets.length; i++) {
|
||||
effect = check(selected.targets[i]);
|
||||
if (effect < 0) j -= Math.sqrt(-effect);
|
||||
else j += Math.sqrt(effect);
|
||||
}
|
||||
|
@ -144,7 +154,7 @@ export class BasicAI {
|
|||
else if (range[1] == 0) {
|
||||
return check() > 0
|
||||
}
|
||||
targets = get.selectableTargets();
|
||||
targets = Get.selectableTargets();
|
||||
if (targets.length == 0) {
|
||||
return range[0] == 0 || ok;
|
||||
}
|
||||
|
@ -167,12 +177,12 @@ export class BasicAI {
|
|||
}
|
||||
}
|
||||
targets[ix].classList.add('selected');
|
||||
ui.selected.targets.add(targets[ix]);
|
||||
game.check();
|
||||
if (ui.selected.targets.length >= range[0]) {
|
||||
selected.targets.add(targets[ix]);
|
||||
Game.check();
|
||||
if (selected.targets.length >= range[0]) {
|
||||
ok = true;
|
||||
}
|
||||
if (ui.selected.targets.length == range[1]) {
|
||||
if (selected.targets.length == range[1]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
export class Game {
|
||||
constructor() {
|
||||
throw new TypeError(`${new.target.name} is not a constructor`);
|
||||
}
|
||||
}
|
104
noname/get.js
104
noname/get.js
|
@ -1,6 +1,10 @@
|
|||
import { Library as lib, status as _status } from "../noname.js";
|
||||
import { status as _status } from "./status";
|
||||
|
||||
export class Get {
|
||||
constructor() {
|
||||
throw new TypeError(`${new.target.name} is not a constructor`);
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @overload
|
||||
|
@ -14,4 +18,102 @@ export class Get {
|
|||
static event(key) {
|
||||
return key ? _status.event[key] : _status.event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
static translation(str, arg) {
|
||||
if (str && typeof str == "object" && (str.name || str._tempTranslate)) {
|
||||
if (str._tempTranslate) return str._tempTranslate;
|
||||
var str2;
|
||||
if (arg == "viewAs" && str.viewAs) {
|
||||
str2 = get.translation(str.viewAs);
|
||||
}
|
||||
else {
|
||||
str2 = get.translation(str.name);
|
||||
}
|
||||
if (str2 == "杀") {
|
||||
str2 = "";
|
||||
if (typeof str.nature == "string") {
|
||||
let natures = str.nature.split(lib.natureSeparator).sort(lib.sort.nature);
|
||||
for (let nature of natures) {
|
||||
str2 += lib.translate["nature_" + nature] || lib.translate[nature] || "";
|
||||
}
|
||||
}
|
||||
str2 += "杀";
|
||||
}
|
||||
if (get.itemtype(str) == "card" || str.isCard) {
|
||||
if (_status.cardtag && str.cardid) {
|
||||
var tagstr = "";
|
||||
for (var i in _status.cardtag) {
|
||||
if (_status.cardtag[i].contains(str.cardid)) {
|
||||
tagstr += lib.translate[i + "_tag"];
|
||||
}
|
||||
}
|
||||
if (tagstr) {
|
||||
str2 += "·" + tagstr;
|
||||
}
|
||||
}
|
||||
if (str.suit && str.number || str.isCard) {
|
||||
var cardnum = get.number(str, false) || "";
|
||||
if ([1, 11, 12, 13].contains(cardnum)) {
|
||||
cardnum = { "1": "A", "11": "J", "12": "Q", "13": "K" }[cardnum]
|
||||
}
|
||||
if (arg == "viewAs" && str.viewAs != str.name && str.viewAs) {
|
||||
str2 += "(" + get.translation(str) + ")";
|
||||
}
|
||||
else {
|
||||
str2 += "【" + get.translation(get.suit(str, false)) + cardnum + "】";
|
||||
}
|
||||
}
|
||||
}
|
||||
return str2;
|
||||
}
|
||||
if (Array.isArray(str)) {
|
||||
var str2 = get.translation(str[0], arg);
|
||||
for (var i = 1; i < str.length; i++) {
|
||||
str2 += "、" + get.translation(str[i], arg);
|
||||
}
|
||||
return str2;
|
||||
}
|
||||
if (get.itemtype(str) == "natures") {
|
||||
let natures = str.split(lib.natureSeparator).sort(lib.sort.nature);
|
||||
var str2 = "";
|
||||
for (var nature of natures) {
|
||||
str2 += lib.translate["nature_" + nature] || lib.translate[nature] || "";
|
||||
}
|
||||
return str2;
|
||||
}
|
||||
if (arg == "skill") {
|
||||
if (lib.translate[str + "_ab"]) return lib.translate[str + "_ab"];
|
||||
if (lib.translate[str]) return lib.translate[str].slice(0, 2);
|
||||
return str;
|
||||
}
|
||||
else if (arg == "info") {
|
||||
if (lib.translate[str + "_info"]) return lib.translate[str + "_info"];
|
||||
var str2 = str.slice(0, str.length - 1);
|
||||
if (lib.translate[str2 + "_info"]) return lib.translate[str2 + "_info"];
|
||||
if (str.lastIndexOf("_") > 0) {
|
||||
str2 = str.slice(0, str.lastIndexOf("_"));
|
||||
if (lib.translate[str2 + "_info"]) return lib.translate[str2 + "_info"];
|
||||
}
|
||||
str2 = str.slice(0, str.length - 2);
|
||||
if (lib.translate[str2 + "_info"]) return lib.translate[str2 + "_info"];
|
||||
if (lib.skill[str] && lib.skill[str].prompt) return lib.skill[str].prompt;
|
||||
}
|
||||
if (lib.translate[str]) {
|
||||
return lib.translate[str];
|
||||
}
|
||||
if (typeof str == "string") {
|
||||
if (lib.translate["nature_" + str]) return lib.translate["nature_" + str];
|
||||
return str;
|
||||
}
|
||||
if (typeof str == "number" || typeof str == "boolean") {
|
||||
return str.toString();
|
||||
}
|
||||
if (str && str.toString) {
|
||||
return str.toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,31 @@
|
|||
import { animate } from "./library/animate.js";
|
||||
import { announce } from "./library/announce.js";
|
||||
import { cardPack } from "./library/card-pack.js";
|
||||
import { cardType } from "./library/card-type.js";
|
||||
import { Channel } from "./library/channel.js";
|
||||
import { CharacterDialogGroup } from "./library/character-dialog-group.js";
|
||||
import { characterFilter } from "./library/character-filter.js";
|
||||
import { characterIntro } from "./library/character-intro.js";
|
||||
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 { configMenu } from "./library/config-menu.js";
|
||||
import { dynamicTranslate } from "./library/dynamic-translate.js";
|
||||
import { element } from "./library/element.js";
|
||||
import { emotionList } from "./library/emotion-list.js";
|
||||
import { extensionPack } from "./library/extension-pack.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 { pinyins } from "./library/pinyins.js";
|
||||
import { skin } from "./library/skin.js";
|
||||
import { stratagemBuff } from "./library/stratagem-buff.js";
|
||||
import { updateURLs } from "./library/update-urls.js";
|
||||
import { yingbian } from "./library/yingbian.js";
|
||||
|
||||
const nonameInitialized = localStorage.getItem('noname_inited');
|
||||
const nonameInitialized = localStorage.getItem("noname_inited");
|
||||
|
||||
export class Library {
|
||||
static configprefix = "noname_0.9_";
|
||||
|
@ -23,9 +34,9 @@ export class Library {
|
|||
static updateURL = updateURLs.github;
|
||||
static mirrorURL = updateURLs.coding;
|
||||
static hallURL = "47.99.105.222";
|
||||
static assetURL = typeof nonameInitialized != 'string' || nonameInitialized == 'nodejs' ? '' : nonameInitialized;
|
||||
static assetURL = typeof nonameInitialized != "string" || nonameInitialized == "nodejs" ? "" : nonameInitialized;
|
||||
static userAgent = navigator.userAgent.toLowerCase();
|
||||
static compatibleEdition = Boolean(typeof nonameInitialized == 'string' && nonameInitialized.match(/\/(?:com\.widget|yuri\.nakamura)\.noname\//));
|
||||
static compatibleEdition = Boolean(typeof nonameInitialized == "string" && nonameInitialized.match(/\/(?:com\.widget|yuri\.nakamura)\.noname\//));
|
||||
static changeLog = [];
|
||||
static updates = [];
|
||||
static canvasUpdates = [];
|
||||
|
@ -61,9 +72,53 @@ export class Library {
|
|||
static extensions = [];
|
||||
static extensionPack = extensionPack;
|
||||
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.
|
||||
*/
|
||||
static announce = announce;
|
||||
/**
|
||||
* @type {Map<string, string>}
|
||||
*/
|
||||
static objectURL = new Map();
|
||||
static hookmap = hookMap;
|
||||
static imported = imported;
|
||||
static layoutfixed = ["chess", "tafang", "stone"];
|
||||
static pinyins = pinyins;
|
||||
static yingbian = yingbian;
|
||||
static stratagemBuff = stratagemBuff;
|
||||
/**
|
||||
* The actual card name
|
||||
*
|
||||
* 实际的卡牌名称
|
||||
*/
|
||||
static actualCardName = new Map([
|
||||
["挟令", "挟天子以令诸侯"],
|
||||
["霹雳投石车", "霹雳车"]
|
||||
])
|
||||
static characterDialogGroup = CharacterDialogGroup;
|
||||
static configMenu = configMenu;
|
||||
|
||||
constructor() {
|
||||
throw new TypeError(`${new.target.name} is not a constructor`);
|
||||
}
|
||||
|
||||
static listenEnd(node) {
|
||||
if (!node._listeningEnd) {
|
||||
node._listeningEnd = true;
|
||||
node.listenTransition(function () {
|
||||
delete node._listeningEnd;
|
||||
if (node._onEndMoveDelete) {
|
||||
node.moveDelete(node._onEndMoveDelete);
|
||||
}
|
||||
else if (node._onEndDelete) {
|
||||
node.delete();
|
||||
}
|
||||
node._transitionEnded = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { animateCard } from "./animate/card.js";
|
||||
import { animateSkill } from "./animate/skill.js";
|
||||
import { card } from "./animate/card.js";
|
||||
import { skill } from "./animate/skill.js";
|
||||
|
||||
export const animate = {
|
||||
skill: animateSkill,
|
||||
card: animateCard
|
||||
skill,
|
||||
card
|
||||
};
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
interface AnimateCard extends Record<string, Function> { }
|
||||
interface Card extends Record<string, Function> { }
|
||||
|
||||
export const animateCard: AnimateCard;
|
||||
export const card: Card;
|
||||
|
|
|
@ -1 +1 @@
|
|||
export const animateCard = {};
|
||||
export const card = {};
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
interface AnimateSkill extends Record<string, Function> { }
|
||||
interface Skill extends Record<string, Function> { }
|
||||
|
||||
export const animateSkill: AnimateSkill;
|
||||
export const skill: Skill;
|
||||
|
|
|
@ -1 +1 @@
|
|||
export const animateSkill = {};
|
||||
export const skill = {};
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
|
||||
/**
|
||||
* **无名杀消息推送库**
|
||||
*
|
||||
* 通过`EventTarget`机制,实现消息推送和接收的解耦,
|
||||
* 从而使消息接收方无需依赖发布方,发布方也无需考虑接收方
|
||||
*
|
||||
* > `lib.announce`不是`actor`模型,若不存在订阅者,则消息发送将无意义
|
||||
*
|
||||
* @example
|
||||
* // 甲扩展(如《千幻聆音》)在角色皮肤切换后,调用:
|
||||
* lib.announce.publish("skinChange", {
|
||||
* player,
|
||||
* playerName: "zhangfei",
|
||||
* originSkin: "image/xxx.jpg",
|
||||
* currentSkin: "image/yyy.jpg"
|
||||
* });
|
||||
*
|
||||
* // 乙扩展监听此`skinChange`事件,并修改自己扩展相关界面的图片:
|
||||
* const method = lib.announce.subscribe("skinChange", (e) => {
|
||||
* div.setBackgroundImage(e.currentSkin);
|
||||
* });
|
||||
*
|
||||
* // 若此时乙扩展不想继续订阅`skinChange`事件,可以通过`unsubscribe`解除订阅
|
||||
* lib.announce.unsubscribe("skinChange", method);
|
||||
*/
|
||||
export const announce = {
|
||||
_announce: document.createElement("Announce"),
|
||||
/**
|
||||
* @type {Map<(values: T) => void, Map<string, (event: Event) => void>>}
|
||||
*/
|
||||
_announce_cache: new Map(),
|
||||
/**
|
||||
* 推送任意数据给所有监听了指定事件的订阅者,并返回给定的数据
|
||||
*
|
||||
* 若不存在订阅指定事件的订阅者,则推送的数据将无意义
|
||||
*
|
||||
* @template T
|
||||
* @param {string} name - 要推送事件的名称
|
||||
* @param {T} values - 要推送的数据
|
||||
* @returns {T}
|
||||
*/
|
||||
publish(name, values) {
|
||||
if (this._announce) this._announce.dispatchEvent(new CustomEvent(name, {
|
||||
detail: values
|
||||
}));
|
||||
return values;
|
||||
},
|
||||
/**
|
||||
* 订阅给定名字的事件,并返回给定的函数
|
||||
*
|
||||
* 在事件触发时执行给定的函数
|
||||
*
|
||||
* 给定的函数将被存储至当前实例中,用于取消订阅时获取
|
||||
*
|
||||
* @template T
|
||||
* @param {string} name - 要订阅事件的名称
|
||||
* @param {(values: T) => void} method - 事件触发时执行的函数
|
||||
* @returns {(values: T) => void}
|
||||
*/
|
||||
subscribe(name, method) {
|
||||
if (this._announce && this._announce_cache) {
|
||||
let subscribeFunction;
|
||||
if (this._announce_cache.has(method)) {
|
||||
let records = this._announce_cache.get(method);
|
||||
subscribeFunction = records.get("Listener");
|
||||
records.get("EventTargets").add(name);
|
||||
}
|
||||
else {
|
||||
subscribeFunction = event => method(event.detail);
|
||||
let records = new Map();
|
||||
records.set("Listener", subscribeFunction);
|
||||
records.set("EventTargets", [name]);
|
||||
this._announce_cache.set(method, records);
|
||||
}
|
||||
this._announce.addEventListener(name, subscribeFunction);
|
||||
}
|
||||
return method;
|
||||
},
|
||||
/**
|
||||
* 取消指定事件某一函数的订阅,并返回该函数
|
||||
*
|
||||
* 给定的函数将不再于事件触发时执行,其余同事件需触发的函数不受限制
|
||||
*
|
||||
* @template T
|
||||
* @param {string} name - 要取消订阅事件的名称
|
||||
* @param {(values: T) => void} method - 订阅指定事件的函数
|
||||
* @returns {(values: T) => void}
|
||||
*/
|
||||
unsubscribe(name, method) {
|
||||
if (this._announce && this._announce_cache && this._announce_cache.has(method)) {
|
||||
let records = this._announce_cache.get(method);
|
||||
const listener = records.get("Listener");
|
||||
let eventTargets = records.get("EventTargets");
|
||||
eventTargets.remove(name);
|
||||
if (eventTargets.length <= 0) this._announce_cache.remove(method);
|
||||
this._announce.removeEventListener(name, listener);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* **无名杀频道推送机制**
|
||||
*
|
||||
* 鉴于`Javascript`的特性及自身对所需功能的思考,这是一个参考`Golang`的`channel`设计的、完全和`go channel`不一样的异步消息传递对象
|
||||
*
|
||||
* 当且仅当接收方和发送方均存在时进行消息传递,完全保证信息传递的单一性(发送方/接收方一旦确定则无法更改)和准确性(发送方必然将消息发送给接收方)
|
||||
*
|
||||
* 若存在发送方/接收方时调用`send`/`receive`,将报错
|
||||
*
|
||||
* 若需要异步/不报错发送信息,请等待`lib.actor`
|
||||
*
|
||||
* @template T
|
||||
* @example
|
||||
* // 创建一个频道
|
||||
* const channel = new lib.channel();
|
||||
*
|
||||
* // 从某个角落接收channel发出的消息,若无消息则等待
|
||||
* const message = await channel.receive();
|
||||
*
|
||||
* // 从某个角落向channel发消息,若无消息接收则等待
|
||||
* await channel.send(item);
|
||||
*/
|
||||
export class Channel {
|
||||
constructor() {
|
||||
/**
|
||||
* @type {"active" | "receiving" | "sending"}
|
||||
*/
|
||||
this.status = "active";
|
||||
|
||||
/**
|
||||
* @type {import("./promise-resolve").PromiseResolve<T> | [T, import("./promise-resolve").PromiseResolve<void>] | null}
|
||||
*/
|
||||
this._buffer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 向该频道发送消息,在消息未被接受前将等待
|
||||
*
|
||||
* @param {T} value - 要发送的消息
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
send(value) {
|
||||
return new Promise((resolve, reject) => {
|
||||
switch (this.status) {
|
||||
case "sending":
|
||||
// TODO: handle the error.
|
||||
reject(new Error());
|
||||
break;
|
||||
case "receiving": {
|
||||
/**
|
||||
* @type {import("./promise-resolve").PromiseResolve<T>}
|
||||
*/
|
||||
const buffer = this._buffer;
|
||||
this._buffer = null;
|
||||
buffer(value);
|
||||
this.status = "active";
|
||||
resolve();
|
||||
break;
|
||||
}
|
||||
case "active":
|
||||
this.status = "sending";
|
||||
this._buffer = [value, resolve];
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收频道所发送的消息,若无消息发送则等待
|
||||
*
|
||||
* @returns {Promise<T>} 接收到的消息
|
||||
*/
|
||||
receive() {
|
||||
return new Promise((resolve, reject) => {
|
||||
switch (this.status) {
|
||||
case "receiving":
|
||||
// TODO: handle the error.
|
||||
reject(new Error());
|
||||
break;
|
||||
case "sending": {
|
||||
/**
|
||||
* @type {[T, import("./promise-resolve").PromiseResolve<void>]}
|
||||
*/
|
||||
const buffer = this._buffer;
|
||||
this._buffer = null;
|
||||
resolve(buffer[0]);
|
||||
this.status = "active";
|
||||
buffer[1]();
|
||||
break;
|
||||
}
|
||||
case "active":
|
||||
this.status = "receiving";
|
||||
this._buffer = resolve;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import { Get } from "../get.js";
|
||||
import { config } from "./config.js";
|
||||
|
||||
export class CharacterDialogGroup {
|
||||
constructor() {
|
||||
throw new TypeError(`${new.target.name} is not a constructor`);
|
||||
}
|
||||
|
||||
static 收藏(name, capt) {
|
||||
return config.favouriteCharacter.includes(name) ? capt : null;
|
||||
}
|
||||
|
||||
static 最近(name, capt) {
|
||||
var list = Get.config("recentCharacter") || [];
|
||||
return list.includes(name) ? capt : null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
import { general } from "./config-menu/general.js";
|
||||
|
||||
export const configMenu = {
|
||||
general
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
import { config } from "./general/config.js";
|
||||
|
||||
export const general = {
|
||||
name: "通用",
|
||||
config: config
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
import { lowPerformance } from "./config/low-performance.js";
|
||||
import { mountCombine } from "./config/mount-combine.js";
|
||||
|
||||
export const config = {
|
||||
mount_combine: mountCombine,
|
||||
low_performance: lowPerformance
|
||||
};
|
|
@ -0,0 +1,17 @@
|
|||
import { Game } from "../../../../game.js";
|
||||
import { UI } from "../../../../ui.js";
|
||||
|
||||
export const lowPerformance = {
|
||||
name: "流畅模式",
|
||||
init: false,
|
||||
intro: "减少部分游戏特效,提高游戏速度",
|
||||
onclick(bool) {
|
||||
Game.saveConfig("low_performance", bool);
|
||||
if (bool) {
|
||||
UI.window.classList.add("low_performance");
|
||||
}
|
||||
else {
|
||||
UI.window.classList.remove("low_performance");
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
const listItem = document.createElement("li");
|
||||
listItem.textContent = "将进攻坐骑栏和防御坐骑栏合并为同一个位置(重启后生效)。";
|
||||
|
||||
export const mountCombine = {
|
||||
name: "合并坐骑栏",
|
||||
init: false,
|
||||
intro: listItem.outerHTML,
|
||||
restart: true
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
interface Config extends Record<string, any> {
|
||||
favouriteCharacter: string[];
|
||||
}
|
||||
|
||||
export const config: Config;
|
|
@ -0,0 +1 @@
|
|||
export const config = {};
|
|
@ -2,6 +2,6 @@ import { GameEvent } from "./element/game-event.js";
|
|||
import { Player } from "./element/player.js";
|
||||
|
||||
export const element = {
|
||||
Player: Player,
|
||||
GameEvent: GameEvent
|
||||
Player,
|
||||
GameEvent
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Get as get } from "../../../noname.js";
|
||||
import { Game } from "../../game.js";
|
||||
import { Get } from "../../get.js";
|
||||
|
||||
export class GameEvent {
|
||||
/**
|
||||
|
@ -8,24 +9,24 @@ export class GameEvent {
|
|||
constructor(name, trigger) {
|
||||
if (typeof name == 'string') {
|
||||
this.name = name;
|
||||
const gameEvent = get.event();
|
||||
const gameEvent = Get.event();
|
||||
|
||||
if (gameEvent) {
|
||||
const type = `onNext${name[0].toUpperCase()}${name.slice(1)}`;
|
||||
if (gameEvent.hasHandler(type)) this.pushHandler(...gameEvent.getHandler(type));
|
||||
}
|
||||
|
||||
game.globalEventHandlers.addHandlerToEvent(this);
|
||||
Game.globalEventHandlers.addHandlerToEvent(this);
|
||||
}
|
||||
|
||||
this.step = 0;
|
||||
this.finished = false;
|
||||
/**
|
||||
* @type {GameEvent[]}
|
||||
* @type {this[]}
|
||||
*/
|
||||
this.next = [];
|
||||
/**
|
||||
* @type {GameEvent[]}
|
||||
* @type {this[]}
|
||||
*/
|
||||
this.after = [];
|
||||
this.custom = {
|
||||
|
@ -36,7 +37,7 @@ export class GameEvent {
|
|||
this._notrigger = [];
|
||||
this._result = {};
|
||||
this._set = [];
|
||||
if (trigger !== false && !game.online) this._triggered = 0;
|
||||
if (trigger !== false && !Game.online) this._triggered = 0;
|
||||
}
|
||||
|
||||
static initialGameEvent() {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export class VCard { }
|
|
@ -0,0 +1,3 @@
|
|||
export interface HandlerOption extends Record<string, unknown> {
|
||||
state: "begin" | "end";
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
interface HookMap extends Record<string, true> { }
|
||||
|
||||
export const hookMap: HookMap;
|
|
@ -0,0 +1 @@
|
|||
export const hookMap = {};
|
|
@ -0,0 +1,5 @@
|
|||
import { globalSkill } from "./hook/global-skill.js";
|
||||
|
||||
export const hook = {
|
||||
globalskill: globalSkill
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
export const globalSkill = {};
|
|
@ -0,0 +1,190 @@
|
|||
import { Game } from "../game.js";
|
||||
import { Library } from "../library.js";
|
||||
|
||||
/**
|
||||
* 函数钩子
|
||||
*/
|
||||
export const hooks = {
|
||||
/**
|
||||
* 本体势力的颜色
|
||||
*/
|
||||
addGroup: [(id, _short, _name, config) => {
|
||||
if ("color" in config && config.color != null) {
|
||||
let color1, color2, color3, color4;
|
||||
if (typeof config.color == "string" && /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(config.color)) {
|
||||
let c1 = parseInt(`0x${config.color.slice(1, 3)}`);
|
||||
let c2 = parseInt(`0x${config.color.slice(3, 5)}`);
|
||||
let c3 = parseInt(`0x${config.color.slice(5, 7)}`);
|
||||
color1 = color2 = color3 = color4 = [c1, c2, c3, 1];
|
||||
}
|
||||
else if (Array.isArray(config.color) && config.color.length == 4) {
|
||||
if (config.color.every(item => Array.isArray(item))) {
|
||||
color1 = config.color[0];
|
||||
color2 = config.color[1];
|
||||
color3 = config.color[2];
|
||||
color4 = config.color[3];
|
||||
}
|
||||
else color1 = color2 = color3 = color4 = config.color;
|
||||
}
|
||||
if (color1 && color2 && color3 && color4) {
|
||||
const cs = Library.linq.cselector;
|
||||
const g1 = cs.group(
|
||||
cs.of(
|
||||
cs.class("player", "identity"),
|
||||
cs.isAttr("data-color", `"${id}"`)
|
||||
),
|
||||
cs.of(
|
||||
"div",
|
||||
cs.isAttr("data-nature", `"${id}"`)
|
||||
),
|
||||
cs.of(
|
||||
"span",
|
||||
cs.isAttr("data-nature", `"${id}"`)
|
||||
)
|
||||
);
|
||||
const g2 = cs.group(
|
||||
cs.of(
|
||||
"div",
|
||||
cs.isAttr("data-nature", `"${id}m"`)
|
||||
),
|
||||
cs.of(
|
||||
"span",
|
||||
cs.isAttr("data-nature", `"${id}m"`)
|
||||
)
|
||||
);
|
||||
const g3 = cs.group(
|
||||
cs.of(
|
||||
"div",
|
||||
cs.isAttr("data-nature", `"${id}mm"`)
|
||||
),
|
||||
cs.of(
|
||||
"span",
|
||||
cs.isAttr("data-nature", `"${id}mm"`)
|
||||
)
|
||||
);
|
||||
let result = {};
|
||||
result[g1] = {
|
||||
textShadow: cs.group(
|
||||
"black 0 0 1px",
|
||||
`rgba(${color1.join()}) 0 0 2px`,
|
||||
`rgba(${color2.join()}) 0 0 5px`,
|
||||
`rgba(${color3.join()}) 0 0 10px`,
|
||||
`rgba(${color4.join()}) 0 0 10px`
|
||||
)
|
||||
};
|
||||
result[g2] = {
|
||||
textShadow: cs.group(
|
||||
"black 0 0 1px",
|
||||
`rgba(${color1.join()}) 0 0 2px`,
|
||||
`rgba(${color2.join()}) 0 0 5px`,
|
||||
`rgba(${color3.join()}) 0 0 5px`,
|
||||
`rgba(${color4.join()}) 0 0 5px`,
|
||||
"black 0 0 1px"
|
||||
)
|
||||
};
|
||||
result[g3] = {
|
||||
textShadow: cs.group(
|
||||
"black 0 0 1px",
|
||||
`rgba(${color1.join()}) 0 0 2px`,
|
||||
`rgba(${color2.join()}) 0 0 2px`,
|
||||
`rgba(${color3.join()}) 0 0 2px`,
|
||||
`rgba(${color4.join()}) 0 0 2px`,
|
||||
"black 0 0 1px"
|
||||
)
|
||||
};
|
||||
Game.dynamicStyle.addObject(result);
|
||||
Library.groupnature[id] = id;
|
||||
}
|
||||
}
|
||||
if (typeof config.image == "string") Object.defineProperty(Library.card, `group_${id}`, {
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: {
|
||||
fullskin: true,
|
||||
image: config.image
|
||||
}
|
||||
});
|
||||
}],
|
||||
/**
|
||||
* 增加新属性杀
|
||||
*/
|
||||
addNature: [(nature, _translation, config) => {
|
||||
if (typeof config != "object") config = {};
|
||||
let linked = config.linked, order = config.order, background = config.background, lineColor = config.lineColor;
|
||||
if (typeof linked != "boolean") linked = true;
|
||||
if (typeof order != "number") order = 0;
|
||||
if (typeof background != "string") background = "";
|
||||
if (!Array.isArray(lineColor) || lineColor.length != 3) lineColor = [];
|
||||
else if (background.startsWith("ext:")) {
|
||||
background = background.replace(/^ext:/, "extension/");
|
||||
}
|
||||
if (linked) Library.linked.add(nature);
|
||||
if (lineColor.length) Library.lineColor.set(nature, lineColor);
|
||||
Library.nature.set(nature, order);
|
||||
if (background.length > 0) Library.natureBg.set(nature, background);
|
||||
if (config.audio) {
|
||||
for (let key in config.audio) {
|
||||
if (!Library.natureAudio[key]) {
|
||||
Library.natureAudio[key] = config.audio[key];
|
||||
} else {
|
||||
for (let key2 in config.audio[key]) {
|
||||
Library.natureAudio[key][key2] = config.audio[key][key2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let color1, color2;
|
||||
if (typeof config.color == "string" && /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(config.color)) {
|
||||
let c1 = parseInt(`0x${item[1].slice(1, 3)}`);
|
||||
let c2 = parseInt(`0x${item[1].slice(3, 5)}`);
|
||||
let c3 = parseInt(`0x${item[1].slice(5, 7)}`);
|
||||
color1 = color2 = [c1, c2, c3, 1];
|
||||
}
|
||||
else if (Array.isArray(config.color) && config.color.length >= 2 && config.color.length <= 4) {
|
||||
if (config.color.every(item => Array.isArray(item))) {
|
||||
color1 = config.color[0];
|
||||
color2 = config.color[1];
|
||||
}
|
||||
else {
|
||||
let color = config.color.slice();
|
||||
if (color.length == 3) color.push(1);
|
||||
color1 = color2 = color;
|
||||
}
|
||||
}
|
||||
if (color1 && color2) {
|
||||
const cs = Library.linq.cselector;
|
||||
const g1 = cs.group(
|
||||
cs.of(
|
||||
cs.class("card", "fullskin", `${nature}`),
|
||||
">",
|
||||
cs.class("name")
|
||||
)
|
||||
);
|
||||
let result = {};
|
||||
result[g1] = {
|
||||
color: `rgba(${color1.join()})`,
|
||||
border: cs.merge(
|
||||
"1px",
|
||||
"solid",
|
||||
`rgba(${color2.join()})`
|
||||
),
|
||||
};
|
||||
Game.dynamicStyle.addObject(result);
|
||||
|
||||
const g2 = cs.group(
|
||||
cs.of(
|
||||
cs.class("tempname", `${nature}`),
|
||||
":not([data-nature])>",
|
||||
cs.class("span")
|
||||
)
|
||||
)
|
||||
let result2 = {};
|
||||
result2[g2] = {
|
||||
color: `rgba(${color1.join()})`,
|
||||
};
|
||||
Game.dynamicStyle.addObject(result2);
|
||||
}
|
||||
}]
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
export const imported = {};
|
|
@ -0,0 +1,5 @@
|
|||
import { pinyinsMetadata } from "./pinyins/metadata.js";
|
||||
|
||||
export const pinyins = {
|
||||
_metadata: pinyinsMetadata
|
||||
};
|
|
@ -0,0 +1,10 @@
|
|||
import { nonMedial } from "./metadata/non-medial.js";
|
||||
import { rhyme } from "./metadata/rhyme.js";
|
||||
|
||||
export const pinyinsMetadata = {
|
||||
shengmu: ["zh", "ch", "sh", "b", "p", "m", "f", "d", "t", "l", "n", "g", "k", "h", "j", "q", "x", "r", "z", "c", "s", "y", "w"],
|
||||
special_shengmu: ["j", "q", "x", "y"],
|
||||
feijiemu: nonMedial,
|
||||
zhengtirendu: ["zhi", "chi", "shi", "ri", "zi", "ci", "si"],
|
||||
yunjiao: rhyme
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
export const nonMedial = {
|
||||
i: ["ing", "iu", "ie", "in"],
|
||||
u: ["ui", "un"],
|
||||
ü: ["üe", "ün"],
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
export const rhyme = {
|
||||
一麻: ["a", "ia", "ua"],
|
||||
二波: ["o", "e", "uo"],
|
||||
三皆: ["ie", "üe"],
|
||||
四开: ["ai", "uai"],
|
||||
五微: ["ei", "ui"],
|
||||
六豪: ["ao", "iao"],
|
||||
七尤: ["ou", "iu"],
|
||||
八寒: ["an", "ian", "uan", "üan"],
|
||||
九文: ["en", "in", "un", "ün"],
|
||||
十唐: ["ang", "iang", "uang"],
|
||||
十一庚: ["eng", "ing", "ong", "ung"],
|
||||
十二齐: ["i", "er", "ü"],
|
||||
十三支: ["-i"],
|
||||
十四姑: ["u"]
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
export type PromiseResolve<T> = (value: T) => void;
|
|
@ -0,0 +1,72 @@
|
|||
import { Game } from "../game.js";
|
||||
import { Get } from "../get.js";
|
||||
import { GameEvent } from "./element/game-event.js";
|
||||
import { VCard } from "./element/v-card.js";
|
||||
|
||||
export const stratagemBuff = {
|
||||
cost: new Map([
|
||||
["sha", 1],
|
||||
["shan", 1],
|
||||
["juedou", 2],
|
||||
["huogong", 2],
|
||||
["tao", 3]
|
||||
]),
|
||||
/**
|
||||
* @type {Map<string, (event: GameEvent, option: import("./handler-option").HandlerOption) => void>}
|
||||
*/
|
||||
effect: new Map([
|
||||
["sha", (event, option) => {
|
||||
if (event.step != 0 || option.state != "end") return;
|
||||
Game.log(event.player, "触发了强化效果");
|
||||
Game.log(event.card, "抵消所需要的", new VCard({
|
||||
name: "shan"
|
||||
}), "数+1");
|
||||
const map = event.customArgs;
|
||||
Game.players.concat(Game.dead).forEach(current => {
|
||||
const id = current.playerid;
|
||||
if (!map[id]) map[id] = {};
|
||||
if (typeof map[id].shanRequired == "number") map[id].shanRequired++;
|
||||
else map[id].shanRequired = 2;
|
||||
});
|
||||
}],
|
||||
["shan", (event, option) => {
|
||||
if (event.step != 0 || option.state != "end") return;
|
||||
Game.log(event.player, "触发了强化效果");
|
||||
Game.log("使用", event.card, "时视为两张", new VCard({
|
||||
name: "shan"
|
||||
}), "的效果");
|
||||
event.player.when("useCard").filter(evt => evt == event).then(() => {
|
||||
trigger.getParent(2).decrease("shanRequired", 1);
|
||||
});
|
||||
}],
|
||||
["juedou", (event, option) => {
|
||||
if (event.step != 0 || option.state != "end") return;
|
||||
Game.log(event.player, "触发了强化效果");
|
||||
Game.log("对", event.card, "的目标造成伤害时,伤害+1");
|
||||
event.player.when({
|
||||
source: "damageBegin1"
|
||||
}).filter(evt => evt.getParent(2) == event && event.targets.includes(evt.player)).then(() => {
|
||||
trigger.increase("num");
|
||||
});
|
||||
}],
|
||||
["huogong", (event, option) => {
|
||||
if (event.step != 0 || option.state != "end") return;
|
||||
Game.log(event.player, "触发了强化效果");
|
||||
Game.log(event.card, "造成的伤害+1");
|
||||
event.increase("baseDamage", 1);
|
||||
}],
|
||||
["tao", (event, option) => {
|
||||
if (event.step != 0 || option.state != "end") return;
|
||||
Game.log(event.player, "触发了强化效果");
|
||||
Game.log(event.card, "回复的体力+1");
|
||||
event.increase("baseDamage", 1);
|
||||
}]
|
||||
]),
|
||||
prompt: new Map([
|
||||
["sha", () => `抵消所需要的【${Get.translation("shan")}】数+1。`],
|
||||
["shan", () => `使用时视为两张【${Get.translation("shan")}】的效果。`],
|
||||
["juedou", () => "对此牌的目标造成伤害时,伤害+1。"],
|
||||
["huogong", () => "造成的伤害+1。"],
|
||||
["tao", () => "回复的体力+1。"]
|
||||
])
|
||||
};
|
|
@ -0,0 +1,42 @@
|
|||
import { condition } from "./yingbian/condition.js";
|
||||
|
||||
export const yingbian = {
|
||||
condition,
|
||||
effect: new Map([
|
||||
["add", () => {
|
||||
trigger.yingbian_addTarget = true;
|
||||
}],
|
||||
["remove", () => {
|
||||
trigger.yingbian_removeTarget = true;
|
||||
}],
|
||||
["damage", () => {
|
||||
if (typeof trigger.baseDamage != "number") trigger.baseDamage = 1;
|
||||
trigger.baseDamage++;
|
||||
game.log(card, "的伤害值基数+1");
|
||||
}],
|
||||
["draw", () => {
|
||||
player.draw();
|
||||
}],
|
||||
["gain", () => {
|
||||
const cardx = trigger.respondTo;
|
||||
if (cardx && cardx[1] && cardx[1].cards && cardx[1].cards.filterInD("od").length) player.gain(cardx[1].cards.filterInD("od"), "gain2");
|
||||
}],
|
||||
["hit", () => {
|
||||
trigger.directHit.addArray(game.players).addArray(game.dead);
|
||||
game.log(card, "不可被响应");
|
||||
}],
|
||||
["all", () => {
|
||||
card.yingbian_all = true;
|
||||
game.log(card, "执行所有选项");
|
||||
}]
|
||||
]),
|
||||
prompt: new Map([
|
||||
["add", "目标+1"],
|
||||
["remove", "目标-1"],
|
||||
["damage", "伤害+1"],
|
||||
["draw", "摸一张牌"],
|
||||
["gain", "获得响应的牌"],
|
||||
["hit", "此牌不可被响应"],
|
||||
["all", "无视条件执行所有选项"]
|
||||
])
|
||||
};
|
|
@ -0,0 +1,132 @@
|
|||
export const condition = {
|
||||
color: new Map([
|
||||
["zhuzhan", "wood"],
|
||||
["kongchao", "soil"],
|
||||
["fujia", "orange"],
|
||||
["canqu", "fire"],
|
||||
["force", "metal"]
|
||||
]),
|
||||
complex: new Map([
|
||||
["zhuzhan", function (event) {
|
||||
const yingbianZhuzhan = game.createEvent("yingbianZhuzhan");
|
||||
yingbianZhuzhan.player = event.player;
|
||||
yingbianZhuzhan.card = event.card;
|
||||
yingbianZhuzhan._trigger = event;
|
||||
yingbianZhuzhan.yingbianZhuzhanAI = event.yingbianZhuzhanAI;
|
||||
yingbianZhuzhan.afterYingbianZhuzhan = event.afterYingbianZhuzhan;
|
||||
yingbianZhuzhan.setContent(() => {
|
||||
"step 0"
|
||||
event._global_waiting = true;
|
||||
event.send = (player, card, source, targets, id, id2, yingbianZhuzhanAI, skillState) => {
|
||||
if (skillState) player.applySkills(skillState);
|
||||
var type = get.type2(card), str = get.translation(source);
|
||||
if (targets && targets.length) str += `对${get.translation(targets)}`;
|
||||
str += `使用了${get.translation(card)},是否弃置一张${get.translation(type)}为其助战?`;
|
||||
player.chooseCard({
|
||||
filterCard: (card, player) => get.type2(card) == type && lib.filter.cardDiscardable(card, player),
|
||||
prompt: str,
|
||||
position: "h",
|
||||
_global_waiting: true,
|
||||
id: id,
|
||||
id2: id2,
|
||||
ai: typeof yingbianZhuzhanAI == "function" ? yingbianZhuzhanAI(player, card, source, targets) : cardx => {
|
||||
var info = get.info(card);
|
||||
if (info && info.ai && info.ai.yingbian) {
|
||||
var ai = info.ai.yingbian(card, source, targets, player);
|
||||
if (!ai) return 0;
|
||||
return ai - get.value(cardx);
|
||||
}
|
||||
else if (get.attitude(player, source) <= 0) return 0;
|
||||
return 5 - get.value(cardx);
|
||||
}
|
||||
});
|
||||
if (!game.online) return;
|
||||
_status.event._resultid = id;
|
||||
game.resume();
|
||||
};
|
||||
"step 1"
|
||||
var type = get.type2(card);
|
||||
event.list = game.filterPlayer(current => current != player && current.countCards("h") && (_status.connectMode || current.hasCard(cardx => get.type2(cardx) == type, "h"))).sortBySeat(_status.currentPhase || player);
|
||||
event.id = get.id();
|
||||
"step 2"
|
||||
if (!event.list.length) event.finish();
|
||||
else if (_status.connectMode && (event.list[0].isOnline() || event.list[0] == game.me)) event.goto(4);
|
||||
else event.send(event.current = event.list.shift(), event.card, player, trigger.targets, event.id, trigger.parent.id, trigger.yingbianZhuzhanAI);
|
||||
"step 3"
|
||||
if (result.bool) {
|
||||
event.zhuzhanresult = event.current;
|
||||
event.zhuzhanresult2 = result;
|
||||
if (event.current != game.me) game.delayx();
|
||||
event.goto(8);
|
||||
}
|
||||
else event.goto(2);
|
||||
"step 4"
|
||||
var id = event.id, sendback = (result, player) => {
|
||||
if (result && result.id == id && !event.zhuzhanresult && result.bool) {
|
||||
event.zhuzhanresult = player;
|
||||
event.zhuzhanresult2 = result;
|
||||
game.broadcast("cancel", id);
|
||||
if (_status.event.id == id && _status.event.name == "chooseCard" && _status.paused) return () => {
|
||||
event.resultOL = _status.event.resultOL;
|
||||
ui.click.cancel();
|
||||
if (ui.confirm) ui.confirm.close();
|
||||
};
|
||||
}
|
||||
else if (_status.event.id == id && _status.event.name == "chooseCard" && _status.paused) return () => event.resultOL = _status.event.resultOL;
|
||||
}, withme = false, withol = false, list = event.list;
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var current = list[i];
|
||||
if (current.isOnline()) {
|
||||
withol = true;
|
||||
current.wait(sendback);
|
||||
current.send(event.send, current, event.card, player, trigger.targets, event.id, trigger.parent.id, trigger.yingbianZhuzhanAI, get.skillState(current));
|
||||
list.splice(i--, 1);
|
||||
}
|
||||
else if (current == game.me) {
|
||||
withme = true;
|
||||
event.send(current, event.card, player, trigger.targets, event.id, trigger.parent.id, trigger.yingbianZhuzhanAI);
|
||||
list.splice(i--, 1);
|
||||
}
|
||||
}
|
||||
if (!withme) event.goto(6);
|
||||
if (_status.connectMode && (withme || withol)) game.players.forEach(value => {
|
||||
if (value != player) value.showTimer();
|
||||
});
|
||||
event.withol = withol;
|
||||
"step 5"
|
||||
if (!result || !result.bool || event.zhuzhanresult) return;
|
||||
game.broadcast("cancel", event.id);
|
||||
event.zhuzhanresult = game.me;
|
||||
event.zhuzhanresult2 = result;
|
||||
"step 6"
|
||||
if (event.withol && !event.resultOL) game.pause();
|
||||
"step 7"
|
||||
game.players.forEach(value => value.hideTimer());
|
||||
"step 8"
|
||||
if (event.zhuzhanresult) {
|
||||
var target = event.zhuzhanresult;
|
||||
target.line(player, "green");
|
||||
target.discard(event.zhuzhanresult2.cards).discarder = target;
|
||||
if (typeof event.afterYingbianZhuzhan == "function") event.afterYingbianZhuzhan(event, trigger);
|
||||
var yingbianCondition = event.name.slice(8).toLowerCase(), yingbianConditionTag = `yingbian_${yingbianCondition}_tag`;
|
||||
target.popup(yingbianConditionTag, lib.yingbian.condition.color.get(yingbianCondition));
|
||||
game.log(target, "响应了", player, "发起的", yingbianConditionTag);
|
||||
target.addExpose(0.2);
|
||||
event.result = {
|
||||
bool: true
|
||||
}
|
||||
}
|
||||
else event.result = {
|
||||
bool: false
|
||||
};
|
||||
});
|
||||
yingbianZhuzhan._args = Array.from(arguments);
|
||||
return yingbianZhuzhan;
|
||||
}]
|
||||
]),
|
||||
simple: new Map([
|
||||
["kongchao", event => !event.player.countCards("h")],
|
||||
["fujia", event => event.player.isMaxHandcard()],
|
||||
["canqu", event => event.player.getHp() == 1]
|
||||
])
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
import { Library as lib } from "../noname.js";
|
||||
import { GameEvent } from "./library/element/game-event.js";
|
||||
import { aiStatus } from "./status/ai.js";
|
||||
import { cardTag } from "./status/card-tag.js";
|
||||
import { postReconnect } from "./status/post-reconnect.js";
|
||||
|
@ -10,7 +10,7 @@ export const status = {
|
|||
over: false,
|
||||
clicked: false,
|
||||
auto: false,
|
||||
event: lib.element.GameEvent.initialGameEvent(),
|
||||
event: GameEvent.initialGameEvent(),
|
||||
ai: aiStatus,
|
||||
lastdragchange: [],
|
||||
skillaudio: [],
|
||||
|
@ -30,5 +30,5 @@ export const status = {
|
|||
cardtag: cardTag,
|
||||
renku: [],
|
||||
prehidden_skills: [],
|
||||
postReconnect: postReconnect
|
||||
postReconnect
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import { Click } from "./ui/click.js";
|
||||
import { selected } from "./ui/selected.js";
|
||||
|
||||
class HTMLWindowElement extends HTMLDivElement { }
|
||||
|
||||
customElements.define("window", HTMLWindowElement, {
|
||||
extends: "div"
|
||||
});
|
||||
|
||||
export class UI {
|
||||
static click = Click;
|
||||
static selected = selected;
|
||||
/**
|
||||
* @type {HTMLWindowElement}
|
||||
*/
|
||||
static window;
|
||||
|
||||
constructor() {
|
||||
throw new TypeError(`${new.target.name} is not a constructor`);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export class Click {
|
||||
constructor() {
|
||||
throw new TypeError(`${new.target.name} is not a constructor`);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export const selected = {
|
||||
buttons: [],
|
||||
cards: [],
|
||||
targets: []
|
||||
};
|
Loading…
Reference in New Issue