mirror of
https://github.com/ZZZure/ZZZ-Plugin.git
synced 2025-12-16 13:17:32 +00:00
feat: panel
This commit is contained in:
parent
35c8c95b80
commit
27171c5727
77 changed files with 2126 additions and 312 deletions
|
|
@ -96,10 +96,11 @@ export function getPanelList(uid) {
|
|||
* @returns {ZZZAvatarInfo | null}
|
||||
*/
|
||||
export function getPanel(uid, name) {
|
||||
logger.debug('获取面板数据', uid, name);
|
||||
const data = getPanelData(uid).map(item => new ZZZAvatarInfo(item));
|
||||
const _data = getPanelData(uid);
|
||||
const data = _data.map(item => new ZZZAvatarInfo(item));
|
||||
const id = char.atlasToID(name);
|
||||
logger.debug('获取角色ID', id);
|
||||
if (!id) return null;
|
||||
return data.find(item => item.id === id) || null;
|
||||
const result = data.find(item => item.id === id);
|
||||
if (!result) return null;
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,3 +3,9 @@ export * as element from './convert/element.js';
|
|||
export * as char from './convert/char.js';
|
||||
|
||||
export * as weapon from './convert/weapon.js';
|
||||
|
||||
export * as equip from './convert/equip.js';
|
||||
|
||||
export * as rank from './convert/rank.js';
|
||||
|
||||
export * as property from './convert/property.js';
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export const IDToCharName = (id, full = true, en = false) => {
|
|||
export const IDToCharSprite = id => {
|
||||
const data = PartnerId2SpriteId?.[id];
|
||||
if (!data) return null;
|
||||
return data?.['sprite'];
|
||||
return data?.['sprite_id'];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
19
lib/convert/equip.js
Normal file
19
lib/convert/equip.js
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import { getMapData } from '../../utils/file.js';
|
||||
|
||||
const equipData = getMapData('EquipId2Data');
|
||||
|
||||
/**
|
||||
* 获取驱动盘装备的图片
|
||||
* @param {string | number} equipId
|
||||
* @returns {string | null}
|
||||
*/
|
||||
export function equipIdToSprite(equipId) {
|
||||
equipId = equipId.toString();
|
||||
if (equipId.length === 5) {
|
||||
const suitId = equipId.slice(0, 3) + '00';
|
||||
if (equipData.hasOwnProperty(suitId)) {
|
||||
return equipData[suitId]['sprite_file'].replace('3D', '');
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
41
lib/convert/property.js
Normal file
41
lib/convert/property.js
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
const prop_id = {
|
||||
111: 'hpmax',
|
||||
121: 'attack',
|
||||
131: 'def',
|
||||
122: 'breakstun',
|
||||
201: 'crit',
|
||||
211: 'critdam',
|
||||
314: 'elementabnormalpower',
|
||||
312: 'elementmystery',
|
||||
231: 'penratio',
|
||||
232: 'penvalue',
|
||||
305: 'sprecover',
|
||||
310: 'spgetratio',
|
||||
115: 'spmax',
|
||||
315: 'physdmg',
|
||||
316: 'fire',
|
||||
317: 'ice',
|
||||
318: 'thunder',
|
||||
319: 'dungeonbuffether',
|
||||
};
|
||||
|
||||
const pro_id = {
|
||||
1: 'attack',
|
||||
2: 'stun',
|
||||
3: 'anomaly',
|
||||
4: 'support',
|
||||
5: 'defense',
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取属性css类名
|
||||
* @param {string} _id 属性id
|
||||
* @returns {string | null}
|
||||
*/
|
||||
export function idToClassName(_id) {
|
||||
let propId = _id.toString();
|
||||
propId = propId.slice(0, 3);
|
||||
const propIcon = prop_id[propId];
|
||||
if (!propIcon) return null;
|
||||
return propIcon;
|
||||
}
|
||||
14
lib/convert/rank.js
Normal file
14
lib/convert/rank.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
const RANK_MAP = {
|
||||
4: 'S',
|
||||
3: 'A',
|
||||
2: 'B',
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取星级对应的字母
|
||||
* @param {string | number} id
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getRankChar(id) {
|
||||
return RANK_MAP[id] || '';
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ import path from 'path';
|
|||
import fs from 'fs';
|
||||
import { ZZZ_SQUARE_AVATAR, ZZZ_SQUARE_BANGBOO } from './mysapi/api.js';
|
||||
import { imageResourcesPath } from './path.js';
|
||||
import { weapon } from './convert.js';
|
||||
import { char, equip, weapon } from './convert.js';
|
||||
import { getResourceRemotePath } from './assets.js';
|
||||
|
||||
const ZZZ_SQUARE_AVATAR_PATH = path.join(imageResourcesPath, 'square_avatar');
|
||||
|
|
@ -11,9 +11,18 @@ const ZZZ_SQUARE_BANGBOO_PATH = path.join(
|
|||
'bangboo_square_avatar'
|
||||
);
|
||||
const ZZZ_WEAPON_PATH = path.join(imageResourcesPath, 'weapon');
|
||||
const ZZZ_GUIDES_PATH = path.join(imageResourcesPath, 'guides');
|
||||
const ZZZ_ROLE_PATH = path.join(imageResourcesPath, 'role');
|
||||
const ZZZ_ROLE_CIRCLE_PATH = path.join(imageResourcesPath, 'role_circle');
|
||||
const ZZZ_SUIT_3D_PATH = path.join(imageResourcesPath, 'suit_3d');
|
||||
const ZZZ_SUIT_PATH = path.join(imageResourcesPath, 'suit');
|
||||
// const ZZZ_GUIDES_PATH = path.join(imageResourcesPath, 'guides');
|
||||
|
||||
// 将下面的下载封装起来,支持错误重试5次
|
||||
/**
|
||||
* 下载文件
|
||||
* @param {string} url 下载地址
|
||||
* @param {string} savePath 保存路径
|
||||
* @returns
|
||||
*/
|
||||
const downloadFile = async (url, savePath) => {
|
||||
const _download = async (url, savePath, retry = 0) => {
|
||||
if (retry > 5) {
|
||||
|
|
@ -36,7 +45,7 @@ const downloadFile = async (url, savePath) => {
|
|||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* 获取角色头像(方形)
|
||||
* @param {string | number} charID
|
||||
* @returns Promise<string>
|
||||
*/
|
||||
|
|
@ -51,7 +60,7 @@ export const getSquareAvatar = async charID => {
|
|||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* 获取邦布头像(方形)
|
||||
* @param {string | number} bangbooId
|
||||
* @returns Promise<string>
|
||||
*/
|
||||
|
|
@ -66,7 +75,7 @@ export const getSquareBangboo = async bangbooId => {
|
|||
};
|
||||
|
||||
/**
|
||||
* Get weapon image path
|
||||
* 获取武器图片
|
||||
* @param {string} id
|
||||
* @returns Promise<string>
|
||||
*/
|
||||
|
|
@ -80,6 +89,72 @@ export const getWeaponImage = async id => {
|
|||
const url = await getResourceRemotePath('weapon', filename);
|
||||
const savePath = weaponPath;
|
||||
const download = await downloadFile(url, savePath);
|
||||
logger.mark('getWeaponImage', download);
|
||||
logger.debug('getWeaponImage', download);
|
||||
return download;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取角色图片
|
||||
* @param {string | number} id
|
||||
* @returns Promise<string>
|
||||
*/
|
||||
export const getRoleImage = async id => {
|
||||
const sprite = char.IDToCharSprite(id);
|
||||
if (sprite === null) return null;
|
||||
const filename = `IconRole${sprite}.png`;
|
||||
const rolePath = path.join(ZZZ_ROLE_PATH, filename);
|
||||
if (fs.existsSync(rolePath)) return rolePath;
|
||||
const url = await getResourceRemotePath('role', filename);
|
||||
const savePath = rolePath;
|
||||
const download = await downloadFile(url, savePath);
|
||||
return download;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取角色圆形图片
|
||||
* @param {string | number} id
|
||||
* @returns Promise<string>
|
||||
*/
|
||||
export const getRoleCircleImage = async id => {
|
||||
const sprite = char.IDToCharSprite(id);
|
||||
if (sprite === null) return null;
|
||||
const filename = `IconRoleCircle${sprite}.png`;
|
||||
const roleCirclePath = path.join(ZZZ_ROLE_CIRCLE_PATH, filename);
|
||||
if (fs.existsSync(roleCirclePath)) return roleCirclePath;
|
||||
const url = await getResourceRemotePath('role_circle', filename);
|
||||
const savePath = roleCirclePath;
|
||||
const download = await downloadFile(url, savePath);
|
||||
return download;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取套装图片
|
||||
* @param {string | number} suitId
|
||||
* @returns Promise<string>
|
||||
*/
|
||||
export const getSuitImage = async suitId => {
|
||||
const suitName = equip.equipIdToSprite(suitId);
|
||||
const filename = `${suitName}.png`;
|
||||
const suitPath = path.join(ZZZ_SUIT_PATH, filename);
|
||||
if (fs.existsSync(suitPath)) return suitPath;
|
||||
const url = await getResourceRemotePath('suit', filename);
|
||||
const savePath = suitPath;
|
||||
const download = await downloadFile(url, savePath);
|
||||
return download;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取3D套装图片
|
||||
* @param {string | number} suitId
|
||||
* @returns Promise<string>
|
||||
*/
|
||||
export const getSuit3DImage = async suitId => {
|
||||
const suitName = equip.equipIdToSprite(suitId);
|
||||
const filename = `${suitName}_3d.png`;
|
||||
const suitPath = path.join(ZZZ_SUIT_3D_PATH, filename);
|
||||
if (fs.existsSync(suitPath)) return suitPath;
|
||||
const url = await getResourceRemotePath('suit_3d', filename);
|
||||
const savePath = suitPath;
|
||||
const download = await downloadFile(url, savePath);
|
||||
return download;
|
||||
};
|
||||
|
|
|
|||
65
lib/gacha.js
65
lib/gacha.js
|
|
@ -1,5 +1,6 @@
|
|||
import { SingleGachaLog, ZZZGachaLogResp } from '../model/gacha.js';
|
||||
import { sleep } from '../utils/time.js';
|
||||
import { rank } from './convert.js';
|
||||
import { getGachaLog, saveGachaLog } from './db.js';
|
||||
import { ZZZ_GET_GACHA_LOG_API } from './mysapi/api.js';
|
||||
|
||||
|
|
@ -96,7 +97,12 @@ export async function getZZZGachaLogByAuthkey(
|
|||
* @param {string} authKey
|
||||
* @param {string} uid
|
||||
* @returns {Promise<{
|
||||
* [x: string]: SingleGachaLog[];
|
||||
* data: {
|
||||
* [x: string]: SingleGachaLog[];
|
||||
* },
|
||||
* count: {
|
||||
* [x: string]: number;
|
||||
* }
|
||||
* }>}
|
||||
*/
|
||||
export async function updateGachaLog(authKey, uid) {
|
||||
|
|
@ -104,26 +110,13 @@ export async function updateGachaLog(authKey, uid) {
|
|||
if (!previousLog) {
|
||||
previousLog = {};
|
||||
}
|
||||
let newCount = {};
|
||||
for (const name in gacha_type_meta_data) {
|
||||
if (!previousLog[name]) {
|
||||
previousLog[name] = [];
|
||||
}
|
||||
previousLog[name] = previousLog[name].map(
|
||||
i =>
|
||||
new SingleGachaLog(
|
||||
i.uid,
|
||||
i.gacha_id,
|
||||
i.gacha_type,
|
||||
i.item_id,
|
||||
i.count,
|
||||
i.time,
|
||||
i.name,
|
||||
i.lang,
|
||||
i.item_type,
|
||||
i.rank_type,
|
||||
i.id
|
||||
)
|
||||
);
|
||||
newCount[name] = 0;
|
||||
previousLog[name] = previousLog[name].map(i => new SingleGachaLog(i));
|
||||
const lastSaved = previousLog[name]?.[0];
|
||||
let page = 1;
|
||||
let endId = '0';
|
||||
|
|
@ -145,6 +138,7 @@ export async function updateGachaLog(authKey, uid) {
|
|||
break queryLabel;
|
||||
}
|
||||
newData.push(item);
|
||||
newCount[name]++;
|
||||
}
|
||||
endId = log.list[log.list.length - 1]?.id || endId;
|
||||
page++;
|
||||
|
|
@ -154,14 +148,12 @@ export async function updateGachaLog(authKey, uid) {
|
|||
previousLog[name] = [...newData, ...previousLog[name]];
|
||||
}
|
||||
saveGachaLog(uid, previousLog);
|
||||
return previousLog;
|
||||
return {
|
||||
data: previousLog,
|
||||
count: newCount,
|
||||
};
|
||||
}
|
||||
|
||||
const RANK_MAP = {
|
||||
4: 'S',
|
||||
3: 'A',
|
||||
2: 'B',
|
||||
};
|
||||
const HOMO_TAG = ['非到极致', '运气不好', '平稳保底', '小欧一把', '欧狗在此'];
|
||||
const EMOJI = [
|
||||
[4, 8, 13],
|
||||
|
|
@ -186,10 +178,10 @@ const NORMAL_LIST = [
|
|||
];
|
||||
|
||||
const FLOORS_MAP = {
|
||||
'邦布频段': [50, 70],
|
||||
'音擎频段': [50, 70],
|
||||
'独家频段': [60, 80],
|
||||
'常驻频段': [60, 80],
|
||||
邦布频段: [50, 70],
|
||||
音擎频段: [50, 70],
|
||||
独家频段: [60, 80],
|
||||
常驻频段: [60, 80],
|
||||
};
|
||||
|
||||
function getLevelFromList(ast, lst) {
|
||||
|
|
@ -214,22 +206,7 @@ export async function anaylizeGachaLog(uid) {
|
|||
}
|
||||
const result = [];
|
||||
for (const name in savedData) {
|
||||
const data = savedData[name].map(
|
||||
item =>
|
||||
new SingleGachaLog(
|
||||
item.uid,
|
||||
item.gacha_id,
|
||||
item.gacha_type,
|
||||
item.item_id,
|
||||
item.count,
|
||||
item.time,
|
||||
item.name,
|
||||
item.lang,
|
||||
item.item_type,
|
||||
item.rank_type,
|
||||
item.id
|
||||
)
|
||||
);
|
||||
const data = savedData[name].map(item => new SingleGachaLog(item));
|
||||
const earliest = data[data.length - 1];
|
||||
const latest = data[0];
|
||||
const list = [];
|
||||
|
|
@ -256,7 +233,7 @@ export async function anaylizeGachaLog(uid) {
|
|||
}
|
||||
list.push({
|
||||
...item,
|
||||
rank_type_label: RANK_MAP[item.rank_type],
|
||||
rank_type_label: rank.getRankChar(item.rank_type),
|
||||
isUp: isUp,
|
||||
totalCount: '-',
|
||||
color: 'white',
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ function render(e, renderPath, renderData = {}, cfg = {}) {
|
|||
resourcesPath: resPath,
|
||||
currentPath: renderPathFull,
|
||||
playerInfo: path.join(layoutPathFull, 'playerinfo.html'),
|
||||
specialTitle: path.join(layoutPathFull, 'specialtitle.html'),
|
||||
copyright: `Created By ${version.name}<span class="version">${version.yunzai}</span> & ${pluginName}<span class="version">${version.version}</span>`,
|
||||
createdby: `Created By <span class="highlight">${pluginName}</span> & Powered By <span class="highlight">ZZZure</span>`,
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue