#更新面板 功能升级,可自动使用,支持国际服UID

`#面板`等命令不再需要cookie,支持查他人
一些其他的样式及功能调整
由于整体逻辑变化,喵喵1.6.0之前更新的面板数据无法查看,需要重新更新数据
This commit is contained in:
yoimiya-kokomi 2022-06-05 05:29:24 +08:00
parent cc93b5dc0e
commit 8dbcc30222
15 changed files with 292 additions and 224 deletions

View File

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

View File

@ -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], "");
}
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,37 +716,18 @@ 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);
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;
@ -696,25 +735,15 @@ export async function renderProfile(e, char, render, mode = "profile", params =
ds.markType = Reliquaries.getMarkScore(mark, maxMark);
ds.main = Profile.formatArti(arti.main);
ds.attrs = Profile.formatArti(arti.attrs);
}
posIdx[pos].data = ds;
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;

View File

@ -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({

View File

@ -248,7 +248,6 @@ let Cal = {
async get() {
moment.locale("zh-cn");
let now = moment();
let { listData, timeMap } = await Cal.reqCalData();

View File

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

View File

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

View File

@ -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群内联系 @喵喵 或者 @九章
}
}*/
}

View File

@ -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: {

View File

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

View File

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

View File

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

View File

@ -53,6 +53,7 @@ body {
text-align: right;
}
.char-lv .cons {
margin-left: 5px;
vertical-align: bottom;
}
.attr {

View File

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

View File

@ -62,6 +62,7 @@ body {
text-align: right;
.cons {
margin-left: 5px;
vertical-align: bottom;
}
}

View File

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