mirror of
https://github.com/Shu-Ying/noname-shuying.git
synced 2026-09-30 17:00:45 +08:00
初始化仓库
This commit is contained in:
+226
@@ -0,0 +1,226 @@
|
||||
export default function initFunction(lib, game, ui, get, ai, _status, shuYing = {}) {
|
||||
game.shuying_getDiscardNamesNum = function () {
|
||||
return Array.from(ui.discardPile.childNodes)
|
||||
.map(card => get.name(card))
|
||||
.unique()
|
||||
.length;
|
||||
};
|
||||
|
||||
game.shuying_getDiscardNum = function () {
|
||||
return game
|
||||
.getGlobalHistory("cardMove", evt => evt.name == "cardsDiscard" || evt.name == "lose" && evt.position == ui.discardPile)
|
||||
.reduce((num, evt) => num + (evt.cards?.length || 0), 0);
|
||||
};
|
||||
|
||||
lib.element.player.shuYing_randomNum = function (max, min = 0) {
|
||||
const upper = Number(max);
|
||||
const lower = Number(min);
|
||||
if (!Number.isFinite(upper) || !Number.isFinite(lower) || upper <= lower) return lower || 0;
|
||||
return Math.floor(Math.random() * (upper - lower)) + lower;
|
||||
};
|
||||
|
||||
lib.element.player.shuYing_numRandom = function () {
|
||||
return this.shuYing_randomNum(100, 1);
|
||||
};
|
||||
|
||||
const getCharacterPack = id => {
|
||||
for (const packName in lib.characterPack) {
|
||||
if (id in lib.characterPack[packName]) return packName;
|
||||
}
|
||||
return "unknown";
|
||||
};
|
||||
|
||||
const getCharacterName = id => get.translation(id) || id;
|
||||
|
||||
const normalizeCharacterDialogItems = list => {
|
||||
return (list || []).map(item => {
|
||||
if (typeof item == "string") {
|
||||
return {
|
||||
key: item,
|
||||
id: item,
|
||||
name: getCharacterName(item),
|
||||
group: getCharacterPack(item),
|
||||
};
|
||||
}
|
||||
const id = item.id || item.name || item.key;
|
||||
return {
|
||||
key: item.key || id,
|
||||
id,
|
||||
name: item.name || getCharacterName(id),
|
||||
group: item.group || getCharacterPack(id),
|
||||
};
|
||||
}).filter(item => item.key && item.id);
|
||||
};
|
||||
|
||||
const getGroupText = group => {
|
||||
if (group == "unknown") return "未知";
|
||||
return lib.translate[`${group}_character_config`] || get.translation(group) || group;
|
||||
};
|
||||
|
||||
const makeSearchMatcher = text => {
|
||||
const value = String(text || "").trim();
|
||||
if (!value) return () => true;
|
||||
try {
|
||||
const regexp = new RegExp(value, "i");
|
||||
return item => regexp.test(item.key) || regexp.test(item.id) || regexp.test(item.name) || regexp.test(get.translation(item.id));
|
||||
} catch (e) {
|
||||
return item => [item.key, item.id, item.name, get.translation(item.id)].some(str => String(str || "").includes(value));
|
||||
}
|
||||
};
|
||||
|
||||
shuYing.chooseCharacterPoolDialog = ({ title = "请选择角色", intro = "", list = [], selected = [] } = {}) => {
|
||||
return new Promise(resolve => {
|
||||
const items = normalizeCharacterDialogItems(list);
|
||||
const selectedSet = new Set(selected);
|
||||
const activeGroups = new Set(items.map(item => item.group));
|
||||
const createNode = (tag, className, text, parent) => {
|
||||
const node = document.createElement(tag);
|
||||
if (className) node.className = className;
|
||||
if (text !== undefined && text !== null) node.textContent = text;
|
||||
if (parent) parent.appendChild(node);
|
||||
return node;
|
||||
};
|
||||
const mask = createNode("div", "shuYing-character-dialog-mask", null, document.body);
|
||||
const dialog = createNode("div", "shuYing-character-dialog", null, mask);
|
||||
const header = createNode("div", "shuYing-character-dialog-header", null, dialog);
|
||||
createNode("div", "shuYing-character-dialog-title", title, header);
|
||||
const countNode = createNode("div", "shuYing-character-dialog-count", "", header);
|
||||
if (intro) createNode("div", "shuYing-character-dialog-intro", intro, dialog);
|
||||
const searchInput = createNode("input", "shuYing-character-dialog-search", null, dialog);
|
||||
searchInput.type = "text";
|
||||
searchInput.placeholder = "搜索武将名 / ID / 正则";
|
||||
searchInput.autocomplete = "off";
|
||||
searchInput.spellcheck = false;
|
||||
const toolbar = createNode("div", "shuYing-character-dialog-toolbar", null, dialog);
|
||||
const groupBox = createNode("div", "shuYing-character-dialog-groups", null, toolbar);
|
||||
const gridWrap = createNode("div", "shuYing-character-dialog-grid-wrap", null, dialog);
|
||||
const grid = createNode("div", "shuYing-character-dialog-grid", null, gridWrap);
|
||||
const controls = createNode("div", "shuYing-character-dialog-controls", null, dialog);
|
||||
let closed = false;
|
||||
let visibleItems = items.slice();
|
||||
|
||||
const close = result => {
|
||||
if (closed) return;
|
||||
closed = true;
|
||||
mask.remove();
|
||||
resolve(result);
|
||||
};
|
||||
|
||||
const refreshCard = card => {
|
||||
card.classList.toggle("selected", selectedSet.has(card.dataset.key));
|
||||
};
|
||||
|
||||
const updateCount = () => {
|
||||
countNode.textContent = `已选择 ${selectedSet.size}/${items.length}`;
|
||||
confirmNode.classList.toggle("disabled", selectedSet.size == 0);
|
||||
confirmNode.disabled = selectedSet.size == 0;
|
||||
};
|
||||
|
||||
const renderGrid = () => {
|
||||
grid.innerHTML = "";
|
||||
const matcher = makeSearchMatcher(searchInput.value);
|
||||
visibleItems = items.filter(item => activeGroups.has(item.group) && matcher(item));
|
||||
if (!visibleItems.length) {
|
||||
createNode("div", "shuYing-character-dialog-empty", "没有符合条件的武将", grid);
|
||||
updateCount();
|
||||
return;
|
||||
}
|
||||
visibleItems.forEach(item => {
|
||||
const card = createNode("div", "shuYing-character-dialog-card", null, grid);
|
||||
card.tabIndex = 0;
|
||||
card.dataset.key = item.key;
|
||||
const avatar = createNode("div", "shuYing-character-dialog-avatar", null, card);
|
||||
avatar.setBackground(item.id, "character");
|
||||
createNode("span", "shuYing-character-dialog-name", item.name || getCharacterName(item.id), card);
|
||||
card.addEventListener("click", event => {
|
||||
event.stopPropagation();
|
||||
if (selectedSet.has(item.key)) selectedSet.delete(item.key);
|
||||
else selectedSet.add(item.key);
|
||||
refreshCard(card);
|
||||
updateCount();
|
||||
});
|
||||
refreshCard(card);
|
||||
});
|
||||
updateCount();
|
||||
};
|
||||
|
||||
const makeControl = (text, handler) => {
|
||||
const button = createNode("div", "shuYing-character-dialog-button", text, controls);
|
||||
button.tabIndex = 0;
|
||||
button.addEventListener("click", event => {
|
||||
event.stopPropagation();
|
||||
handler();
|
||||
});
|
||||
button.addEventListener("keydown", event => {
|
||||
event.stopPropagation();
|
||||
if (event.key == "Enter" || event.key == " ") {
|
||||
event.preventDefault();
|
||||
handler();
|
||||
}
|
||||
});
|
||||
return button;
|
||||
};
|
||||
|
||||
mask.addEventListener("click", event => {
|
||||
event.stopPropagation();
|
||||
close(false);
|
||||
});
|
||||
dialog.addEventListener("click", event => event.stopPropagation());
|
||||
searchInput.addEventListener("click", event => event.stopPropagation());
|
||||
searchInput.addEventListener("input", renderGrid);
|
||||
searchInput.addEventListener("keydown", event => {
|
||||
event.stopPropagation();
|
||||
if (event.key == "Escape") close(false);
|
||||
if (event.key == "Enter") {
|
||||
event.preventDefault();
|
||||
renderGrid();
|
||||
}
|
||||
});
|
||||
|
||||
items.map(item => item.group).unique().forEach(group => {
|
||||
const label = createNode("div", "shuYing-character-dialog-group selected", null, groupBox);
|
||||
label.tabIndex = 0;
|
||||
label.dataset.group = group;
|
||||
createNode("span", "shuYing-character-dialog-check", "", label);
|
||||
createNode("span", "shuYing-character-dialog-group-text", getGroupText(group), label);
|
||||
label.addEventListener("click", event => {
|
||||
event.stopPropagation();
|
||||
const checked = !label.classList.contains("selected");
|
||||
label.classList.toggle("selected", checked);
|
||||
if (checked) activeGroups.add(group);
|
||||
else activeGroups.delete(group);
|
||||
renderGrid();
|
||||
});
|
||||
label.addEventListener("keydown", event => {
|
||||
event.stopPropagation();
|
||||
if (event.key == "Enter" || event.key == " ") {
|
||||
event.preventDefault();
|
||||
label.click();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
makeControl("全选", () => {
|
||||
visibleItems.forEach(item => selectedSet.add(item.key));
|
||||
grid.querySelectorAll(".shuYing-character-dialog-card").forEach(refreshCard);
|
||||
updateCount();
|
||||
});
|
||||
makeControl("清空", () => {
|
||||
visibleItems.forEach(item => selectedSet.delete(item.key));
|
||||
grid.querySelectorAll(".shuYing-character-dialog-card").forEach(refreshCard);
|
||||
updateCount();
|
||||
});
|
||||
makeControl("反选", () => {
|
||||
visibleItems.forEach(item => selectedSet.has(item.key) ? selectedSet.delete(item.key) : selectedSet.add(item.key));
|
||||
grid.querySelectorAll(".shuYing-character-dialog-card").forEach(refreshCard);
|
||||
updateCount();
|
||||
});
|
||||
const confirmNode = makeControl("确定", () => {
|
||||
if (!selectedSet.size) return;
|
||||
close(items.map(item => item.key).filter(key => selectedSet.has(key)));
|
||||
});
|
||||
makeControl("取消", () => close(false));
|
||||
renderGrid();
|
||||
});
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user