mirror of
https://github.com/yoimiya-kokomi/miao-plugin.git
synced 2024-11-16 04:35:42 +00:00
#更新面板
功能升级,可自动使用,支持国际服UID
`#面板`等命令不再需要cookie,支持查他人 一些其他的样式及功能调整 由于整体逻辑变化,喵喵1.6.0之前更新的面板数据无法查看,需要重新更新数据
This commit is contained in:
parent
cc93b5dc0e
commit
8dbcc30222
41
CHANGELOG.md
41
CHANGELOG.md
@ -1,27 +1,24 @@
|
||||
# 1.6.6
|
||||
|
||||
* 修正`#更新全部面板` 一些角色攻击力可能获取错误的问题
|
||||
* 对2开头UID及B服角色更新失败增加提示
|
||||
|
||||
# 1.6.4 ~ 1.6.5
|
||||
|
||||
* `#更新全部面板` 一些已知问题修复
|
||||
* 目前可正确获取圣遗物名称了,`#圣遗物列表`如有错误重新获角色信息后即正常
|
||||
* 雷神、莫娜的元素伤害字段数据错误fix
|
||||
* 由于服务逻辑与之前数据不一致,部分角色的属性及伤害计算可能会不准确,如有发现请反馈给喵喵
|
||||
* `#更新全部面板` 功能暂时恢复
|
||||
* 目前可直接使用,无需token
|
||||
* 服务来自enka api,部分网络可能无法请求,请使用科学处理
|
||||
|
||||
# 1.6.1 ~ 1.6.3
|
||||
# 1.7.0
|
||||
|
||||
* `#更新面板` 功能升级
|
||||
* 该功能可直接使用,不再需要token
|
||||
* 在查询新用户时会自动使用,自动使用的CD 12小时
|
||||
* 支持国际服UID,目前暂不支持2及5开头的UID
|
||||
* 服务来自enka api,部分网络可能无法请求,请使用科学处理,后续会增加转发服务。
|
||||
* 由于服务逻辑与之前数据不一致,部分角色的属性及伤害计算可能会不准确,如有发现请反馈给喵喵。已知问题(夜兰)
|
||||
* `#面板`、`#更新面板`、`#角色面板`、`#角色伤害`、`#圣遗物列表`不再需要绑定cookie,支持查他人
|
||||
* 使用`#面板`命令可查看已获取面板数据的角色列表
|
||||
* 默认查询自己UID,同时也可通过命令+uid方式指定查询对象
|
||||
* 由于整体逻辑变化,喵喵1.6.0之前更新的面板数据无法查看,需要重新更新数据
|
||||
* 增加`#喵喵面板设置`命令,可更精细的设置是否允许好友/临时对话/群使用面板功能
|
||||
* 增加`#录入夜兰面板` 命令,可在更新服务不可用时手工录入角色面板信息
|
||||
* `#喵喵日历` 优化
|
||||
* 对角色、武器UP的日历展示做合并优化
|
||||
* 增强从活动详情解析日期的能力,使一些活动日期更加准确
|
||||
* `#角色面板` 部分细节样式调整
|
||||
* `#角色面板` 伤害计算增加 琴、莫娜、皇女、温迪、夜兰
|
||||
* 由`#录入xx面板` 录入的数据暂时屏蔽
|
||||
* `#角色面板`、`#喵喵日历` 部分细节样式调整
|
||||
* `#角色面板` 伤害计算增加部分角色,目前支持
|
||||
* 长柄武器:雷神、胡桃、魈、钟离、香菱
|
||||
* 法器:神子、心海、可莉、凝光、芭芭拉、莫娜ⁿᵉʷ
|
||||
* 弓:甘雨、宵宫、公子,九条,迪奥娜、安柏、皇女ⁿᵉʷ、温迪ⁿᵉʷ、夜兰ⁿᵉʷ
|
||||
* 单手剑:绫人、绫华、刻晴、阿贝多、行秋、班尼特、七七、凯亚、琴ⁿᵉʷ
|
||||
* 双手剑:一斗、优菈、迪卢克、诺艾尔、重云
|
||||
|
||||
# 1.6.0
|
||||
|
||||
|
@ -61,10 +61,14 @@ export async function character(e, { render, User }) {
|
||||
}
|
||||
|
||||
let mode = 'card';
|
||||
let name = msg.replace(/#|老婆|老公|[1|2|5][0-9]{8}/g, "").trim();
|
||||
let dmgRet = /伤害(\d?)$/.exec(msg), dmgIdx = 0;
|
||||
let uidRet = /[0-9]{9}/.exec(msg);
|
||||
if (uidRet) {
|
||||
e.uid = uidRet[0];
|
||||
msg = msg.replace(uidRet[0], "");
|
||||
}
|
||||
let name = msg.replace(/#|老婆|老公/g, "").trim();
|
||||
msg = msg.replace("面版", "面板")
|
||||
|
||||
let dmgRet = /伤害(\d?)$/.exec(msg), dmgIdx = 0;
|
||||
if (/(详情|详细|面板|面版)$/.test(msg) && !/更新|录入|输入/.test(msg)) {
|
||||
mode = 'profile';
|
||||
name = name.replace(/(详情|详细|面板)/, "").trim();
|
||||
@ -82,8 +86,8 @@ export async function character(e, { render, User }) {
|
||||
let nameRet = /(?:录入|输入)(.+)(?:面板|详细|详情|数据)+/.exec(name);
|
||||
if (nameRet) {
|
||||
name = nameRet[1];
|
||||
e.inputData = msg.replace(nameRet[0], "");
|
||||
}
|
||||
e.inputData = msg.replace(nameRet[0], "");
|
||||
name = name.replace(/录入|输入|详情|详细|面板|数据|[0-9]|\.|\+/g, "").trim()
|
||||
}
|
||||
|
||||
@ -371,7 +375,7 @@ async function renderCard(e, avatar, render, renderType = "card") {
|
||||
// 计算皇冠个数
|
||||
let crownNum = lodash.filter(lodash.map(talent, (d) => d.level_original), (d) => d >= 10).length;
|
||||
|
||||
let uid = e.targetUser.uid;
|
||||
let uid = e.uid || e.targetUser.uid;
|
||||
|
||||
let char = Character.get(avatar);
|
||||
|
||||
@ -452,30 +456,71 @@ async function getTalent(e, avatars) {
|
||||
return skill;
|
||||
}
|
||||
|
||||
|
||||
async function autoRefresh(e) {
|
||||
let MysApi = await e.getMysApi({
|
||||
auth: "all",
|
||||
targetType: "all",
|
||||
cookieType: "all",
|
||||
actionName: "更新角色信息"
|
||||
});
|
||||
let uid = e.uid || e.targetUser.uid;
|
||||
let refreshMark = await redis.get(`miao:profile-refresh-cd:${uid}`);
|
||||
let inCd = await redis.get(`miao:role-all:${uid}`);
|
||||
|
||||
if (refreshMark || inCd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await redis.set(`miao:profile-refresh-cd:${uid}`, "TRUE", { EX: 3600 * 12 });
|
||||
|
||||
// 数据更新
|
||||
let data = await Profile.request(e.uid || e.targetUser.uid, e);
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!data.chars) {
|
||||
e.reply("请确认角色已在【游戏内】橱窗展示并开放了查看详情。设置完毕后请5分钟后使用 #面板更新 重新获取");
|
||||
return false;
|
||||
} else {
|
||||
let ret = [];
|
||||
lodash.forEach(data.chars, (ds) => {
|
||||
let char = Character.get(ds.id);
|
||||
if (char) {
|
||||
ret.push(char.name);
|
||||
}
|
||||
})
|
||||
if (ret.length === 0) {
|
||||
e.reply("请确认角色已在【游戏内】橱窗展示并开放了查看详情。设置完毕后请5分钟后使用 #面板更新 重新获取")
|
||||
return false;
|
||||
} else {
|
||||
e.reply(`本次获取成功角色: ${ret.join(", ")} `)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
export async function getProfile(e, mode = "refresh") {
|
||||
let MysApi = await e.getMysApi({
|
||||
auth: "cookie",
|
||||
targetType: "self",
|
||||
cookieType: "self",
|
||||
auth: "all",
|
||||
targetType: "all",
|
||||
cookieType: "all",
|
||||
actionName: "更新角色信息"
|
||||
});
|
||||
|
||||
if (!MysApi) {
|
||||
return false;
|
||||
}
|
||||
let selfUser = e.selfUser;
|
||||
if (!selfUser.isCookieUser) {
|
||||
e.reply("此功能仅绑定cookie用户可用")
|
||||
return true;
|
||||
}
|
||||
if (mode === "input") {
|
||||
if (e.inputData.trim().length < 5) {
|
||||
e.reply(`【输入示例】\n#录入夜兰面板 生命14450+25469, 攻击652+444, 防御548+144, 元素精通84, 暴击76.3, 爆伤194.2, 治疗0,充能112.3,元素伤害61.6,物伤0
|
||||
`)
|
||||
e.reply(`【输入示例】\n#录入夜兰面板 生命14450+25469, 攻击652+444, 防御548+144, 元素精通84, 暴击76.3, 爆伤194.2, 治疗0,充能112.3,元素伤害61.6,物伤0`)
|
||||
return await profileHelp(e);
|
||||
}
|
||||
|
||||
let ret = Profile.inputProfile(selfUser.uid, e);
|
||||
let ret = Profile.inputProfile(e.selfUser.uid, e);
|
||||
let char = Character.get(e.avatar);
|
||||
if (ret) {
|
||||
e.reply(`${char.name}信息手工录入完成,你可以使用 #角色名+面板 / #角色名+伤害 来查看详细角色面板属性了`)
|
||||
@ -488,11 +533,10 @@ export async function getProfile(e, mode = "refresh") {
|
||||
}
|
||||
|
||||
// 数据更新
|
||||
let data = await Profile.request(selfUser.uid, e);
|
||||
let data = await Profile.request(e.uid || e.targetUser.uid, e);
|
||||
if (!data) {
|
||||
return true;
|
||||
}
|
||||
let leftMsg = "";
|
||||
|
||||
if (!data.chars) {
|
||||
e.reply("获取角色面板数据失败,请确认角色已在游戏内橱窗展示,并开放了查看详情。设置完毕后请5分钟后再进行请求~");
|
||||
@ -507,11 +551,9 @@ export async function getProfile(e, mode = "refresh") {
|
||||
if (ret.length === 0) {
|
||||
e.reply("获取角色面板数据失败,未能请求到角色数据。请确认角色已在游戏内橱窗展示,并开放了查看详情。设置完毕后请5分钟后再进行请求~")
|
||||
} else {
|
||||
e.reply(`获取角色面板数据成功!本次获取成功角色: ${ret.join(", ")} 。\n你可以使用 #角色名+面板 来查看详细角色面板属性了。${leftMsg}`)
|
||||
e.reply(`获取角色面板数据成功!本次获取成功角色: ${ret.join(", ")} 。\n你可以使用 #角色名+面板 来查看详细角色面板属性了。`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -613,7 +655,6 @@ async function getAvatar(e, char, MysApi) {
|
||||
return avatars[char.id];
|
||||
}
|
||||
|
||||
|
||||
export async function renderProfile(e, char, render, mode = "profile", params = {}) {
|
||||
|
||||
if (['荧', '空', '主角', '旅行者'].includes(char.name)) {
|
||||
@ -621,10 +662,18 @@ export async function renderProfile(e, char, render, mode = "profile", params =
|
||||
return true;
|
||||
}
|
||||
|
||||
let refresh = async () => {
|
||||
let refreshRet = await autoRefresh(e);
|
||||
if (refreshRet) {
|
||||
await renderProfile(e, char, render, mode, params);
|
||||
}
|
||||
return refreshRet;
|
||||
}
|
||||
|
||||
let MysApi = await e.getMysApi({
|
||||
auth: "cookie",
|
||||
targetType: "self",
|
||||
cookieType: "self",
|
||||
auth: "all",
|
||||
targetType: "all",
|
||||
cookieType: "all",
|
||||
actionName: "查询角色天赋命座等信息"
|
||||
});
|
||||
if (!MysApi) {
|
||||
@ -632,13 +681,22 @@ export async function renderProfile(e, char, render, mode = "profile", params =
|
||||
}
|
||||
|
||||
let selfUser = e.selfUser,
|
||||
uid = selfUser.uid;
|
||||
uid = e.uid || e.targetUser.uid;
|
||||
|
||||
let profile = Profile.get(uid, char.id);
|
||||
if (!profile) {
|
||||
e.reply(`请先发送 #更新${char.name}面板\n来获取${char.name}的面板详情`);
|
||||
if (await refresh()) {
|
||||
return true;
|
||||
} else {
|
||||
e.reply(`请使用 #更新面板\n来获取${char.name}的面板详情,请确认${char.name}已展示在【游戏内】的角色展柜中,并打开了“显示角色详情”。`);
|
||||
}
|
||||
await profileHelp(e);
|
||||
return true;
|
||||
} else if (profile.dataSource !== "enka") {
|
||||
if (!await refresh()) {
|
||||
e.reply(`由于数据格式升级,请重新获取面板信息后查看`);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
let a = profile.attr;
|
||||
@ -658,63 +716,34 @@ export async function renderProfile(e, char, render, mode = "profile", params =
|
||||
dmgBonus: p(Math.max(a.dmgBonus * 1 || 0, a.phyBonus * 1 || 0))
|
||||
};
|
||||
|
||||
/*
|
||||
let avatar = await getAvatar(e, char, MysApi);
|
||||
let talent = await getTalent(e, avatar);
|
||||
|
||||
|
||||
if (global.debugView === "web-debug") {
|
||||
let file = process.cwd() + "/tools/avatar.json";
|
||||
avatar._talent = talent;
|
||||
fs.writeFileSync(file, JSON.stringify(avatar));
|
||||
}
|
||||
|
||||
if (!talent.id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let posIdx = {
|
||||
"生之花": { idx: 1 },
|
||||
"死之羽": { idx: 2 },
|
||||
"时之沙": { idx: 3 },
|
||||
"空之杯": { idx: 4 },
|
||||
"理之冠": { idx: 5 }
|
||||
};
|
||||
*/
|
||||
|
||||
let reliquaries = [], totalMark = 0, totalMaxMark = 0;
|
||||
|
||||
let { titles: usefulTitles, mark: usefulMark } = Reliquaries.getUseful(avatar.name);
|
||||
let { titles: usefulTitles, mark: usefulMark } = Reliquaries.getUseful(char.name);
|
||||
|
||||
lodash.forEach(avatar.reliquaries, (ds) => {
|
||||
let pos = ds.pos_name;
|
||||
let arti = profile.artis && profile.artis[`arti${posIdx[pos].idx}`];
|
||||
if (arti) {
|
||||
let mark = Reliquaries.getMark(avatar.name, arti.attrs);
|
||||
let maxMark = Reliquaries.getMaxMark(char.name, arti.main[0] || "");
|
||||
totalMark += mark;
|
||||
totalMaxMark += maxMark;
|
||||
ds.mark = c(mark, 1);
|
||||
ds.markType = Reliquaries.getMarkScore(mark, maxMark);
|
||||
ds.main = Profile.formatArti(arti.main);
|
||||
ds.attrs = Profile.formatArti(arti.attrs);
|
||||
}
|
||||
posIdx[pos].data = ds;
|
||||
lodash.forEach(profile.artis, (arti) => {
|
||||
let ds = arti;
|
||||
let mark = Reliquaries.getMark(char.name, arti.attrs);
|
||||
let maxMark = Reliquaries.getMaxMark(char.name, arti.main[0] || "");
|
||||
totalMark += mark;
|
||||
totalMaxMark += maxMark;
|
||||
ds.mark = c(mark, 1);
|
||||
ds.markType = Reliquaries.getMarkScore(mark, maxMark);
|
||||
ds.main = Profile.formatArti(arti.main);
|
||||
ds.attrs = Profile.formatArti(arti.attrs);
|
||||
reliquaries.push(ds);
|
||||
});
|
||||
|
||||
lodash.forEach(posIdx, (ds) => {
|
||||
if (ds && ds.data) {
|
||||
reliquaries.push(ds.data);
|
||||
} else {
|
||||
reliquaries.push({});
|
||||
}
|
||||
});
|
||||
|
||||
let enemyLv = await selfUser.getCfg(`char.enemyLv`, 91);
|
||||
let dmgMsg = [], dmgData = [];
|
||||
let dmgCalc = await Calc.calcData({
|
||||
profile,
|
||||
char,
|
||||
avatar,
|
||||
talentData: talent,
|
||||
enemyLv,
|
||||
mode,
|
||||
...params
|
||||
@ -750,12 +779,9 @@ export async function renderProfile(e, char, render, mode = "profile", params =
|
||||
uid: uid,
|
||||
data: profile,
|
||||
attr,
|
||||
avatar,
|
||||
talent,
|
||||
cons: char.cons,
|
||||
name: char.name,
|
||||
elem: char.elem,
|
||||
dataSource: profile.dataSource,
|
||||
dmgData,
|
||||
dmgMsg,
|
||||
dmgRet: dmgCalc.dmgRet,
|
||||
@ -766,7 +792,6 @@ export async function renderProfile(e, char, render, mode = "profile", params =
|
||||
totalMark: c(totalMark, 1),
|
||||
totalMaxMark,
|
||||
markScore: Reliquaries.getMarkScore(totalMark, totalMaxMark),
|
||||
weapon: avatar.weapon,
|
||||
usefulTitles,
|
||||
usefulMark,
|
||||
talentMap: { a: "普攻", e: "战技", q: "爆发" },
|
||||
@ -800,17 +825,21 @@ export async function enemyLv(e) {
|
||||
|
||||
export async function getArtis(e, { render }) {
|
||||
let MysApi = await e.getMysApi({
|
||||
auth: "cookie",
|
||||
targetType: "self",
|
||||
cookieType: "self",
|
||||
auth: "all",
|
||||
targetType: "all",
|
||||
cookieType: "all",
|
||||
actionName: "查询角色天赋命座等信息"
|
||||
});
|
||||
if (!MysApi) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let selfUser = e.selfUser,
|
||||
uid = selfUser.uid;
|
||||
let uidRet = /[0-9]{9}/.exec(e.msg);
|
||||
if (uidRet) {
|
||||
e.uid = uidRet[0];
|
||||
}
|
||||
|
||||
let uid = e.uid || e.targetUser.uid;
|
||||
|
||||
let artis = [],
|
||||
profiles = Profile.getAll(uid) || {};
|
||||
@ -866,20 +895,23 @@ export async function getArtis(e, { render }) {
|
||||
|
||||
export async function getProfileAll(e) {
|
||||
let MysApi = await e.getMysApi({
|
||||
auth: "cookie",
|
||||
targetType: "self",
|
||||
cookieType: "self",
|
||||
auth: "all",
|
||||
targetType: "all",
|
||||
cookieType: "all",
|
||||
actionName: "查询角色天赋命座等信息"
|
||||
});
|
||||
if (!MysApi) {
|
||||
if (!MysApi && MysApi.targetUser) {
|
||||
return true;
|
||||
}
|
||||
let uid = MysApi.selfUser.uid;
|
||||
let uid = MysApi.targetUser.uid;
|
||||
|
||||
let profiles = Profile.getAll(uid) || {};
|
||||
|
||||
let chars = [];
|
||||
lodash.forEach(profiles || [], (ds) => {
|
||||
if (ds.dataSource !== "enka") {
|
||||
return;
|
||||
}
|
||||
ds.name && chars.push(ds.name)
|
||||
});
|
||||
|
||||
@ -888,6 +920,7 @@ export async function getProfileAll(e) {
|
||||
await profileHelp(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
e.reply("当前已获取面板角色: " + chars.join(", "));
|
||||
|
||||
return true;
|
||||
|
@ -1,14 +1,15 @@
|
||||
import fs from "fs";
|
||||
import lodash from "lodash";
|
||||
import Format from "./Format.js";
|
||||
import { Character } from "./models.js"
|
||||
|
||||
const eleMap = {
|
||||
Anemo: "风",
|
||||
Cryo: "冰",
|
||||
Electro: "雷",
|
||||
Geo: "岩",
|
||||
Hydro: "水",
|
||||
Pyro: "火"
|
||||
anemo: "风",
|
||||
cryo: "冰",
|
||||
electro: "雷",
|
||||
geo: "岩",
|
||||
hydro: "水",
|
||||
pyro: "火"
|
||||
}
|
||||
|
||||
const attrMap = {
|
||||
@ -54,7 +55,7 @@ let Calc = {
|
||||
},
|
||||
|
||||
// 获取基础属性
|
||||
attr(profile, avatar) {
|
||||
attr(profile) {
|
||||
let ret = {},
|
||||
{ attr } = profile;
|
||||
|
||||
@ -122,10 +123,12 @@ let Calc = {
|
||||
inc: 100, // 吸收倍率
|
||||
}
|
||||
|
||||
ret.weaponType = avatar.weapon.type_name;
|
||||
ret.weapon = avatar.weapon;
|
||||
ret.element = eleMap[avatar.element];
|
||||
ret.refine = (avatar.weapon.affix_level * 1 - 1) || 0;
|
||||
let char = Character.get(profile.id);
|
||||
//ret.weaponType = avatar.weapon.type_name;
|
||||
ret.weaponType = "";
|
||||
ret.weapon = profile.weapon;
|
||||
ret.element = eleMap[char.elem.toLowerCase()];
|
||||
ret.refine = (profile.weapon.affix * 1 - 1) || 0;
|
||||
|
||||
ret.multi = 0;
|
||||
|
||||
@ -139,9 +142,11 @@ let Calc = {
|
||||
},
|
||||
|
||||
// 获取天赋数据
|
||||
talent(talentData, char) {
|
||||
talent(profile, char) {
|
||||
let ret = {};
|
||||
|
||||
let talentData = profile.talent;
|
||||
|
||||
lodash.forEach(['a', 'e', 'q'], (key) => {
|
||||
let lv = talentData[key].level_current * 1 || 1,
|
||||
lvKey = `Lv${lv}`;
|
||||
@ -311,7 +316,7 @@ let Calc = {
|
||||
|
||||
lodash.forEach(sets, (set) => {
|
||||
if (set && set.set) {
|
||||
let name = set.set.name
|
||||
let name = set.set
|
||||
setMap[name] = (setMap[name] || 0) + 1
|
||||
}
|
||||
});
|
||||
@ -329,7 +334,7 @@ let Calc = {
|
||||
return retBuffs;
|
||||
},
|
||||
|
||||
getDmgFn({ ds, attr, avatar, enemyLv, showDetail = false }) {
|
||||
getDmgFn({ ds, attr, profile, enemyLv, showDetail = false }) {
|
||||
|
||||
let { calc } = ds;
|
||||
|
||||
@ -378,7 +383,7 @@ let Calc = {
|
||||
}
|
||||
|
||||
// 防御区
|
||||
let lv = avatar.level;
|
||||
let lv = profile.lv;
|
||||
let defNum = (lv + 100) / ((lv + 100) + (enemyLv + 100) * (1 - enemyDef) * (1 - enemyIgnore));
|
||||
|
||||
// 抗性区
|
||||
@ -457,18 +462,16 @@ let Calc = {
|
||||
},
|
||||
|
||||
|
||||
async calcData({ profile, char, avatar, talentData, enemyLv = 91, mode = 'profile', dmgIdx = 0 }) {
|
||||
async calcData({ profile, char, enemyLv = 91, mode = 'profile', dmgIdx = 0 }) {
|
||||
let charCalcData = await Calc.getCharCalcRule(char.name);
|
||||
|
||||
//avatar.element;
|
||||
|
||||
if (!charCalcData) {
|
||||
return false;
|
||||
}
|
||||
let talent = Calc.talent(talentData, char);
|
||||
let talent = Calc.talent(profile, char);
|
||||
|
||||
let meta = {
|
||||
cons: avatar.actived_constellation_num * 1,
|
||||
cons: profile.cons * 1,
|
||||
talent
|
||||
}
|
||||
|
||||
@ -476,10 +479,10 @@ let Calc = {
|
||||
|
||||
defParams = defParams || {};
|
||||
|
||||
let originalAttr = Calc.attr(profile, avatar);
|
||||
let originalAttr = Calc.attr(profile);
|
||||
|
||||
let weaponBuffs = await Calc.weapon(avatar.weapon.name);
|
||||
let reliBuffs = await Calc.reliquaries(avatar.reliquaries);
|
||||
let weaponBuffs = await Calc.weapon(profile.weapon.name);
|
||||
let reliBuffs = await Calc.reliquaries(profile.artis);
|
||||
buffs = lodash.concat(buffs, weaponBuffs, reliBuffs);
|
||||
|
||||
lodash.forEach(buffs, (buff) => {
|
||||
@ -497,7 +500,7 @@ let Calc = {
|
||||
if (lodash.isFunction(detail)) {
|
||||
let { attr } = Calc.calcAttr({ originalAttr, buffs, meta });
|
||||
let ds = lodash.merge({ talent }, Calc.getDs(attr, meta));
|
||||
detail = detail({ ...ds, attr, avatar });
|
||||
detail = detail({ ...ds, attr, profile });
|
||||
}
|
||||
let params = lodash.merge({}, defParams, detail.params || {});
|
||||
let { attr } = Calc.calcAttr({ originalAttr, buffs, meta, params, talent: detail.talent || "" });
|
||||
@ -509,7 +512,7 @@ let Calc = {
|
||||
}
|
||||
let ds = lodash.merge({ talent }, Calc.getDs(attr, meta, params));
|
||||
|
||||
let dmg = Calc.getDmgFn({ ds, attr, avatar, enemyLv, showDetail: detail.showDetail }),
|
||||
let dmg = Calc.getDmgFn({ ds, attr, profile, enemyLv, showDetail: detail.showDetail }),
|
||||
basicDmgRet;
|
||||
|
||||
if (detail.dmg) {
|
||||
@ -562,7 +565,7 @@ let Calc = {
|
||||
talent: detail.talent || ""
|
||||
});
|
||||
let ds = lodash.merge({ talent }, Calc.getDs(attr, meta, params));
|
||||
let dmg = Calc.getDmgFn({ ds, attr, avatar, enemyLv });
|
||||
let dmg = Calc.getDmgFn({ ds, attr, profile, enemyLv });
|
||||
if (detail.dmg) {
|
||||
let dmgCalcRet = detail.dmg(ds, dmg);
|
||||
rowData.push({
|
||||
|
@ -248,7 +248,6 @@ let Cal = {
|
||||
async get() {
|
||||
|
||||
moment.locale("zh-cn");
|
||||
|
||||
let now = moment();
|
||||
|
||||
let { listData, timeMap } = await Cal.reqCalData();
|
||||
|
@ -24,14 +24,16 @@ if (!fs.existsSync(userPath)) {
|
||||
fs.mkdirSync(userPath);
|
||||
}
|
||||
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
let Profile = {
|
||||
async request(uid, e) {
|
||||
let api = `https://enka.shinshin.moe/u/${uid}/__data.json`;
|
||||
let profileApi = config.profileApi || function (uid) {
|
||||
return `https://enka.shinshin.moe/u/${uid}/__data.json`
|
||||
};
|
||||
let api = profileApi(uid);
|
||||
let inCd = await redis.get(`miao:role-all:${uid}`);
|
||||
if (inCd === 'loading') {
|
||||
e.reply("请求过快,请稍后重试..");
|
||||
@ -161,43 +163,6 @@ let Profile = {
|
||||
return total;
|
||||
},
|
||||
|
||||
getArtiDetail(profile, avatar) {
|
||||
|
||||
let reliquaries = [],
|
||||
totalMark = 0,
|
||||
totalMaxMark = 0;
|
||||
|
||||
lodash.forEach(avatar.reliquaries, (ds) => {
|
||||
let pos = ds.pos_name;
|
||||
let arti = profile.artis[`arti${posIdx[pos].idx}`];
|
||||
if (arti) {
|
||||
let mark = Reliquaries.getMark(avatar.name, arti.attrs);
|
||||
let maxMark = Reliquaries.getMaxMark(avatar.name, arti.main[0] || "");
|
||||
totalMark += mark;
|
||||
totalMaxMark += maxMark;
|
||||
ds.mark = Format.comma(mark, 1);
|
||||
ds.markType = Reliquaries.getMarkScore(mark, maxMark);
|
||||
ds.main = Profile.formatArti(arti.main);
|
||||
ds.attrs = Profile.formatArti(arti.attrs);
|
||||
}
|
||||
posIdx[pos].data = ds;
|
||||
})
|
||||
lodash.forEach(posIdx, (ds) => {
|
||||
if (ds && ds.data) {
|
||||
reliquaries.push(ds.data);
|
||||
} else {
|
||||
reliquaries.push({});
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
reliquaries,
|
||||
totalMark,
|
||||
totalMaxMark,
|
||||
markScore: Reliquaries.getMarkScore(totalMark * 1.05, totalMaxMark)
|
||||
}
|
||||
},
|
||||
|
||||
inputProfile(uid, e) {
|
||||
let { avatar, inputData } = e;
|
||||
inputData = inputData.replace("#", "");
|
||||
@ -226,16 +191,39 @@ let Profile = {
|
||||
}
|
||||
let name = dRet[1].trim(),
|
||||
data = dRet[2].trim();
|
||||
let range = (src, min = 0, max = 1200) => Math.max(min, Math.min(max, src * 1 || 0));
|
||||
|
||||
lodash.forEach(attrMap, (reg, key) => {
|
||||
if (reg.test(name)) {
|
||||
if (['hp', 'def', 'atk'].includes(key)) {
|
||||
let tmp = data.split("+");
|
||||
attr[key] = Math.max(0, Math.min(60000, tmp[0].trim() * 1 + tmp[1].trim() * 1 || 0));
|
||||
attr[key + "Base"] = Math.max(0, Math.min(40000, tmp[0].trim() * 1 || 0));
|
||||
} else {
|
||||
attr[key] = Math.max(0, Math.min(400, data * 1 || 0));
|
||||
let tmp = data.split("+");
|
||||
switch (key) {
|
||||
case "hp":
|
||||
attr[key + "Base"] = range(tmp[0].trim(), 0, 16000);
|
||||
attr[key] = range(tmp[0].trim() * 1 + tmp[1].trim() * 1, attr[key + "Base"], 50000);
|
||||
break;
|
||||
case "def":
|
||||
case "atk":
|
||||
attr[key + "Base"] = range(tmp[0].trim(), 0, 1100);
|
||||
attr[key] = range(tmp[0].trim() * 1 + tmp[1].trim() * 1, attr[key + "Base"], 4500);
|
||||
break;
|
||||
case "mastery":
|
||||
attr[key] = range(data, 0, 1200);
|
||||
break;
|
||||
case "cRate":
|
||||
attr[key] = range(data, -95, 120);
|
||||
break;
|
||||
case "cDmg":
|
||||
attr[key] = range(data, 0, 320);
|
||||
break;
|
||||
case "recharge":
|
||||
case "hInc":
|
||||
attr[key] = range(data, 0, 400);
|
||||
break;
|
||||
case "dmgBonus":
|
||||
case "phyBonus":
|
||||
attr[key] = range(data, 0, 200);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -3,6 +3,10 @@ import Character from "../models/Character.js";
|
||||
import meta from "./enka_meta.js";
|
||||
import cmeta from "./enka_char.js";
|
||||
import _Data from "../Data.js";
|
||||
import moment from "moment";
|
||||
|
||||
moment.locale("zh-cn");
|
||||
|
||||
|
||||
let _path = process.cwd();
|
||||
let relis = _Data.readJSON(`${_path}/plugins/miao-plugin/resources/meta/reliquaries/`, "data.json") || {};
|
||||
@ -68,10 +72,12 @@ let Data = {
|
||||
},
|
||||
getAvatar(data) {
|
||||
let char = Character.get(data.avatarId);
|
||||
let now = moment();
|
||||
let ret = {
|
||||
id: data["avatarId"],
|
||||
name: char ? char.name : "",
|
||||
dataSource: "enka",
|
||||
updateTime: now.format("YYYY-MM-DD HH:mm:ss"),
|
||||
lv: data.propMap['4001'].val * 1,
|
||||
fetter: data.fetterInfo.expLevel,
|
||||
attr: Data.getAttr(data.fightPropMap),
|
||||
@ -186,7 +192,7 @@ let Data = {
|
||||
return {
|
||||
name: meta[flat.nameTextMapHash],
|
||||
star: flat.rankLevel,
|
||||
leve: weapon.level,
|
||||
level: weapon.level,
|
||||
promote: weapon.promoteLevel,
|
||||
affix: (lodash.values(weapon.affixMap)[0] || 0) + 1
|
||||
}
|
||||
@ -222,7 +228,9 @@ let Data = {
|
||||
return ret;
|
||||
},
|
||||
dataFix(ret) {
|
||||
|
||||
if (ret._fix) {
|
||||
return ret;
|
||||
}
|
||||
let { attr, id } = ret;
|
||||
id = id * 1;
|
||||
switch (id) {
|
||||
@ -234,7 +242,15 @@ let Data = {
|
||||
// 莫娜被动fix
|
||||
attr.dmgBonus = Math.min(0, attr.dmgBonus - attr.recharge * 0.2)
|
||||
break;
|
||||
/*
|
||||
case 10000060:
|
||||
// 夜兰被动fix
|
||||
attr.hp = attr.hp - attr.hpBase * 0.3
|
||||
break;
|
||||
*/
|
||||
|
||||
}
|
||||
ret._fix = true;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
@ -4,9 +4,9 @@
|
||||
* */
|
||||
|
||||
export const config = {
|
||||
miaoApi: {
|
||||
/*miaoApi: {
|
||||
api: "http://49.232.91.210:88/miaoPlugin/getRoleAll", // Miao APi 地址
|
||||
qq: "", // 申请的主人qq
|
||||
token: "" // 申请的token,申请API Token请在Bot群内联系 @喵喵 或者 @九章
|
||||
}
|
||||
}*/
|
||||
}
|
6
index.js
6
index.js
@ -45,11 +45,11 @@ let rule = {
|
||||
describe: "【#角色】角色详情",
|
||||
},
|
||||
getArtis: {
|
||||
reg: "^#圣遗物列表$",
|
||||
reg: "^#圣遗物列表\\s*(\\d{9})?$",
|
||||
describe: "【#角色】圣遗物列表",
|
||||
},
|
||||
getProfileAll: {
|
||||
reg: "^#(面板角色|角色面板)列表$",
|
||||
reg: "^#(面板角色|角色面板|面板)(列表)?\\s*(\\d{9})?$",
|
||||
describe: "【#角色】查看当前已获取面板数据的角色列表",
|
||||
},
|
||||
profileHelp: {
|
||||
@ -81,7 +81,7 @@ let rule = {
|
||||
describe: "【#帮助】 #喵喵帮助",
|
||||
},
|
||||
getProfile: {
|
||||
reg: "^#(全部面板更新|更新全部面板|获取游戏角色详情)$",
|
||||
reg: "^#(全部面板更新|更新全部面板|获取游戏角色详情|更新面板|面板更新)\\s*(\\d{9})?$",
|
||||
describe: "【#角色】 获取游戏橱窗详情数据",
|
||||
},
|
||||
enemyLv: {
|
||||
|
@ -1,6 +1,13 @@
|
||||
.container {
|
||||
width: 790px;
|
||||
}
|
||||
.uid {
|
||||
font-family: Number;
|
||||
margin: 20px 10px 10px;
|
||||
text-shadow: 0 0 3px #000, 2px 2px 4px rgba(0, 0, 0, 0.7);
|
||||
text-align: right;
|
||||
color: #fff;
|
||||
}
|
||||
.artis {
|
||||
width: 790px;
|
||||
}
|
||||
|
@ -6,7 +6,10 @@
|
||||
{{/block}}
|
||||
|
||||
{{block 'main'}}
|
||||
<div class="uid">UID {{uid}}</div>
|
||||
|
||||
<div class="artis">
|
||||
|
||||
{{each artis ds}}
|
||||
<div class="item arti">
|
||||
{{if ds.name && ds.main && ds.main[0] && ds.main[0]!="undefined"}}
|
||||
|
@ -2,6 +2,15 @@
|
||||
width: 790px;
|
||||
}
|
||||
|
||||
.uid {
|
||||
font-family: Number;
|
||||
margin: 20px 10px 10px;
|
||||
text-shadow: 0 0 3px #000, 2px 2px 4px rgba(0, 0, 0, .7);
|
||||
text-align: right;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
||||
.artis {
|
||||
width: 790px;
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ body {
|
||||
text-align: right;
|
||||
}
|
||||
.char-lv .cons {
|
||||
margin-left: 5px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.attr {
|
||||
|
@ -1,8 +1,14 @@
|
||||
{{extend elemLayout}}
|
||||
|
||||
{{block 'css'}}
|
||||
<link rel="stylesheet" type="text/css" href="{{_res_path}}/character/detail.css"/>
|
||||
{{/block}}
|
||||
|
||||
{{set weapon = data.weapon}}
|
||||
{{set talent = data.talent}}
|
||||
{{set dataSrouce = data.dataSource}}
|
||||
|
||||
|
||||
{{block 'main'}}
|
||||
<div class="basic">
|
||||
<div class="main-pic"
|
||||
@ -10,7 +16,7 @@
|
||||
<div class="detail">
|
||||
<div class="char-name">{{name}}</div>
|
||||
<div class="char-lv">UID {{uid}} - Lv.{{data.lv}}
|
||||
<span class="cons cons-{{avatar.actived_constellation_num}}">{{avatar.actived_constellation_num}}命</span></div>
|
||||
<span class="cons cons-{{data.cons}}">{{data.cons}}命</span></div>
|
||||
<div class="char-talents">
|
||||
{{each talentMap tName key}}
|
||||
<div class="talent-item">
|
||||
@ -38,44 +44,13 @@
|
||||
<div class="char-cons">
|
||||
{{each cons con idx}}
|
||||
<div class="cons-item">
|
||||
<div class="talent-icon {{idx * 1 > avatar.actived_constellation_num * 1 ? 'off' : '' }}">
|
||||
<div class="talent-icon {{idx * 1 > data.cons * 1 ? 'off' : '' }}">
|
||||
<img src="{{_res_path}}/meta/character/{{name}}/cons_{{idx}}.png"/>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
{{if dmgData.length > 0}}
|
||||
<div class="dmg-cont dmg-list cont">
|
||||
<div class="cont-title">
|
||||
伤害计算<span>目标为{{enemyLv}}级{{enemyName}},如需调整等级可使用 #敌人等级{{enemyLv}} 来进行设置</span>
|
||||
</div>
|
||||
<div class="cont-table">
|
||||
<div class="tr thead">
|
||||
<div class="title dmg-idx">#</div>
|
||||
<div class="title dmg-title">伤害类型</div>
|
||||
<div>暴击伤害</div>
|
||||
<div>平均伤害(计算暴击率)</div>
|
||||
</div>
|
||||
{{each dmgData dmg idx}}
|
||||
<div class="dmg tr">
|
||||
<div class="title dmg-idx">{{idx+1}}</div>
|
||||
<div class="title dmg-title">{{dmg.title}}</div>
|
||||
{{if dmg.dmg === "NaN"}}
|
||||
<div class="value value-full">{{dmg.avg}}</div>
|
||||
<div class="value value-none"></div>
|
||||
{{else}}
|
||||
<div class="value">{{dmg.dmg}}</div>
|
||||
<div class="value">{{dmg.avg}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="cont-footer dmg-desc">
|
||||
使用命令<strong>#{{name}}伤害</strong>可以查看伤害详情,使用命令<strong>#角色面板帮助</strong>可查看帮助说明
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{if mode === "profile" && dataSource !== "input"}}
|
||||
<div class="artis">
|
||||
@ -84,9 +59,9 @@
|
||||
<img src="{{_sys_res_path}}/genshin/logo/weapon/{{weapon.name}}.png"/>
|
||||
<div class="head">
|
||||
<strong>{{weapon.name}}</strong>
|
||||
<div class="star star-{{weapon.rarity}}"></div>
|
||||
<span>Lv.{{weapon.level}} <span
|
||||
class="affix affix-{{weapon.affix_level}}">精{{weapon.affix_level}}</span></span>
|
||||
<div class="star star-{{weapon.star}}"></div>
|
||||
<span>Lv.{{weapon.leve || weapon.level}} <span
|
||||
class="affix affix-{{weapon.affix}}">精{{weapon.affix}}</span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item stat">
|
||||
@ -155,6 +130,39 @@
|
||||
|
||||
{{/if}}
|
||||
|
||||
{{if dmgData.length > 0}}
|
||||
<div class="dmg-cont dmg-list cont">
|
||||
<div class="cont-title">
|
||||
伤害计算<span>目标为{{enemyLv}}级{{enemyName}},如需调整等级可使用 #敌人等级{{enemyLv}} 来进行设置</span>
|
||||
</div>
|
||||
<div class="cont-table">
|
||||
<div class="tr thead">
|
||||
<div class="title dmg-idx">#</div>
|
||||
<div class="title dmg-title">伤害类型</div>
|
||||
<div>暴击伤害</div>
|
||||
<div>平均伤害(计算暴击率)</div>
|
||||
</div>
|
||||
{{each dmgData dmg idx}}
|
||||
<div class="dmg tr">
|
||||
<div class="title dmg-idx">{{idx+1}}</div>
|
||||
<div class="title dmg-title">{{dmg.title}}</div>
|
||||
{{if dmg.dmg === "NaN"}}
|
||||
<div class="value value-full">{{dmg.avg}}</div>
|
||||
<div class="value value-none"></div>
|
||||
{{else}}
|
||||
<div class="value">{{dmg.dmg}}</div>
|
||||
<div class="value">{{dmg.avg}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="cont-footer dmg-desc">
|
||||
使用命令<strong>#{{name}}伤害</strong>可以查看伤害详情,使用命令<strong>#角色面板帮助</strong>可查看帮助说明
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
|
||||
{{if mode === "dmg"}}
|
||||
|
||||
{{if dmgCfg && dmgCfg.attr && dmgCfg.attr.length>0}}
|
||||
|
@ -62,6 +62,7 @@ body {
|
||||
text-align: right;
|
||||
|
||||
.cons {
|
||||
margin-left: 5px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,11 @@ export const details = [{
|
||||
|
||||
}, {
|
||||
title: "Q协同单段伤害",
|
||||
dmg: ({ talent, attr, calc, cons }, { basic }) =>
|
||||
basic(calc(attr.hp) * (talent.q['玄掷玲珑伤害'] / 3 / 100), 'q')
|
||||
shwoDetail: true,
|
||||
dmg: ({ talent, attr, calc, cons }, { basic }) => {
|
||||
console.log('hp', attr.hp, calc(attr.hp), talent.q['玄掷玲珑伤害'] / 3)
|
||||
return basic(calc(attr.hp) * (talent.q['玄掷玲珑伤害'] / 3 / 100), 'q')
|
||||
}
|
||||
}];
|
||||
|
||||
export const mainAttr = "hp,cpct,cdmg";
|
||||
|
Loading…
Reference in New Issue
Block a user