增加 #雷神伤害 功能

* 可计算圣遗物副词条置换带来的伤害变化,可用于圣遗物副词条侧重方向的参考
* 可以查看指定角色伤害计算的Buff列表
This commit is contained in:
yoimiya-kokomi 2022-05-01 05:06:17 +08:00
parent ec47c08bee
commit 9765c5af18
17 changed files with 462 additions and 140 deletions

View File

@ -1,13 +1,15 @@
# 1.2.3 # 1.3.0
* `#角色面板` 增加伤害计算功能 * 增加 `#雷神伤害` 功能
* 目前支持角色:雷神、胡桃、魈、神子、甘雨、宵宫、公子、绫人、绫华 * 可计算圣遗物副词条置换带来的伤害变化,可用于圣遗物副词条侧重方向的参考
* 可以查看指定角色伤害计算的Buff列表
* `#角色面板` 伤害计算新增部分角色
* 目前支持:雷神、胡桃、魈、神子、甘雨、宵宫、公子、绫人、绫华
* `#角色面板` 功能升级 * `#角色面板` 功能升级
* 优化无角色面板数据时的引导 * 优化无角色面板数据时的引导
* 优化返回的图像格式及分辨率,平衡响应速度及显示效果 * 优化返回的图像格式及分辨率,平衡响应速度及显示效果
* 增加 `#甘雨伤害` 命令可以查看伤害计算的具体Buff效果。后续会完善计算逻辑 * 增加 `#圣遗物列表` 功能,对已经获取面板的所有角色圣遗物进行评分,并展示高评分的圣遗物列表
* 增加 `#圣遗物列表` 命令,对已经获取面板的所有角色圣遗物进行评分,并展示高评分的圣遗物列表 * 增加 `#角色面板列表` / `#角色面板帮助` 命令
* 增加 `#角色面板列表` 命令,查看已经获取面板的角色列表
* 增加 `#更新胡桃面板` 命令获取单个角色面板数据每天可更新5次 * 增加 `#更新胡桃面板` 命令获取单个角色面板数据每天可更新5次
* 更改 `#更新全部面板` 命令获取角色展柜全部8个角色每天可更新3次 * 更改 `#更新全部面板` 命令获取角色展柜全部8个角色每天可更新3次

View File

@ -64,13 +64,17 @@ export async function character(e, { render, User }) {
let mode = 'card'; let mode = 'card';
let name = msg.replace(/#|老婆|老公|[1|2|5][0-9]{8}/g, "").trim(); let name = msg.replace(/#|老婆|老公|[1|2|5][0-9]{8}/g, "").trim();
let dmgRet = /伤害(\d?)$/.exec(msg), dmgIdx = 0;
if (/(详情|详细|面板|面版)$/.test(msg) && !/更新/.test(msg)) { if (/(详情|详细|面板|面版)$/.test(msg) && !/更新/.test(msg)) {
mode = 'profile'; mode = 'profile';
name = name.replace(/(详情|详细|面板|面版)/, "").trim(); name = name.replace(/(详情|详细|面板|面版)/, "").trim();
} else if (/伤害$/.test(msg)) { } else if (dmgRet) {
mode = 'dmg'; mode = 'dmg';
name = name.replace(/伤害/, "").trim(); name = name.replace(/伤害[0-5]?/, "").trim();
if (dmgRet[1]) {
dmgIdx = dmgRet[1] * 1;
}
} else if (/(详情|详细|面板|面版)更新$/.test(msg) || (/更新/.test(msg) && /(详情|详细|面板|面版)$/.test(msg))) { } else if (/(详情|详细|面板|面版)更新$/.test(msg) || (/更新/.test(msg) && /(详情|详细|面板|面版)$/.test(msg))) {
mode = "refresh"; mode = "refresh";
name = name.replace(/详情|详细|面板|面版|更新/g, "").trim(); name = name.replace(/详情|详细|面板|面版|更新/g, "").trim();
@ -84,7 +88,7 @@ export async function character(e, { render, User }) {
if (mode === "profile" || mode === "dmg") { if (mode === "profile" || mode === "dmg") {
return renderProfile(e, char, render, mode); return renderProfile(e, char, render, mode, { dmgIdx });
} else if (mode === "refresh") { } else if (mode === "refresh") {
e.avatar = char.id; e.avatar = char.id;
await getProfile(e); await getProfile(e);
@ -564,7 +568,7 @@ async function getAvatar(e, char, MysApi) {
} }
export async function renderProfile(e, char, render, mode = "profile") { export async function renderProfile(e, char, render, mode = "profile", params = {}) {
if (['荧', '空', '主角', '旅行者'].includes(char.name)) { if (['荧', '空', '主角', '旅行者'].includes(char.name)) {
e.reply("暂不支持主角的面板信息查看"); e.reply("暂不支持主角的面板信息查看");
@ -660,7 +664,15 @@ export async function renderProfile(e, char, render, mode = "profile") {
let enemyLv = await selfUser.getCfg(`char.enemyLv`, 91); let enemyLv = await selfUser.getCfg(`char.enemyLv`, 91);
let dmgMsg = [], dmgData = []; let dmgMsg = [], dmgData = [];
let dmgCalc = await Calc.calcData({ profile, char, avatar, talentData: talent, enemyLv }); let dmgCalc = await Calc.calcData({
profile,
char,
avatar,
talentData: talent,
enemyLv,
mode,
...params
});
if (dmgCalc && dmgCalc.ret) { if (dmgCalc && dmgCalc.ret) {
lodash.forEach(dmgCalc.ret, (ds) => { lodash.forEach(dmgCalc.ret, (ds) => {
ds.dmg = Format.comma(ds.dmg, 0); ds.dmg = Format.comma(ds.dmg, 0);
@ -673,6 +685,20 @@ export async function renderProfile(e, char, render, mode = "profile") {
}) })
} }
if (mode === "dmg") {
let basic = dmgCalc.dmgCfg.basicRet;
lodash.forEach(dmgCalc.dmgRet, (row) => {
lodash.forEach(row, (ds) => {
ds.val = (ds.avg > basic.avg ? "+" : "") + Format.comma(ds.avg - basic.avg);
ds.dmg = Format.comma(ds.dmg, 0);
ds.avg = Format.comma(ds.avg, 0);
})
});
basic.dmg = Format.comma(basic.dmg);
basic.avg = Format.comma(basic.avg);
}
let base64 = await render("character", "detail", { let base64 = await render("character", "detail", {
save_id: uid, save_id: uid,
uid: uid, uid: uid,
@ -685,6 +711,8 @@ export async function renderProfile(e, char, render, mode = "profile") {
elem: char.elem, elem: char.elem,
dmgData, dmgData,
dmgMsg, dmgMsg,
dmgRet: dmgCalc.dmgRet,
dmgCfg: dmgCalc.dmgCfg,
reliquaries, reliquaries,
enemyLv, enemyLv,
totalMark: c(totalMark, 1), totalMark: c(totalMark, 1),

View File

@ -11,6 +11,17 @@ const eleMap = {
Pyro: "火" Pyro: "火"
} }
const attrMap = {
atk: { type: "pct", val: 5.83, title: "大攻击", text: "5.8%" },
hp: { type: "pct", val: 5.83, title: "大生命", text: "5.8%" },
def: { type: "pct", val: 7.29, title: "大防御", text: "7.3%" },
recharge: { type: "plus", val: 6.48, title: "元素充能", text: "6.5%" },
mastery: { type: "plus", val: 23.31, title: "元素精通", text: "23.3" },
cpct: { type: "plus", val: 3.89, title: "暴击率", text: "3.9%" },
cdmg: { type: "plus", val: 7.77, title: "暴击伤害", text: "7.8%" },
}
let Calc = { let Calc = {
async getCharCalcRule(name) { async getCharCalcRule(name) {
@ -19,16 +30,22 @@ let Calc = {
const cfgPath = `${_path}/plugins/miao-plugin/resources/meta/character/${name}/calc.js`; const cfgPath = `${_path}/plugins/miao-plugin/resources/meta/character/${name}/calc.js`;
let details, buffs = [], defParams = {}; let details, buffs = [], defParams = {}, defDmgIdx = -1, mainAttr = "atk,cpct,cdmg";
if (fs.existsSync(cfgPath)) { if (fs.existsSync(cfgPath)) {
let fileData = await import (`file://${cfgPath}`); let fileData = await import (`file://${cfgPath}`);
details = fileData.details || false; details = fileData.details || false;
buffs = fileData.buffs || []; buffs = fileData.buffs || [];
defParams = fileData.defParams || {}; defParams = fileData.defParams || {};
if (fileData.defDmgIdx) {
defDmgIdx = fileData.defDmgIdx;
}
if (fileData.mainAttr) {
mainAttr = fileData.mainAttr;
}
} }
if (details) { if (details) {
return { details, buffs, defParams } return { details, buffs, defParams, defDmgIdx, mainAttr }
} }
return false; return false;
}, },
@ -159,11 +176,18 @@ let Calc = {
} }
}, },
calcAttr(originalAttr, buffs, meta, params = {}) { calcAttr(originalAttr, buffs, meta, params = {}, incAttr = '', reduceAttr = '') {
let attr = lodash.merge({}, originalAttr); let attr = lodash.merge({}, originalAttr);
let msg = []; let msg = [];
if (incAttr && attrMap[incAttr]) {
let aCfg = attrMap[incAttr];
attr[incAttr][aCfg.type] += aCfg.val;
}
if (reduceAttr && attrMap[reduceAttr]) {
let aCfg = attrMap[reduceAttr];
attr[reduceAttr][aCfg.type] -= aCfg.val;
}
lodash.forEach(buffs, (buff) => { lodash.forEach(buffs, (buff) => {
let ds = Calc.getDs(attr, meta, params); let ds = Calc.getDs(attr, meta, params);
@ -284,7 +308,89 @@ let Calc = {
}) })
return retBuffs; return retBuffs;
}, },
async calcData({ profile, char, avatar, talentData, enemyLv = 91 }) {
getDmgFn({ attr, avatar, enemyLv }) {
return function (pctNum = 0, talent = false, ele = false) {
let { atk, dmg, cdmg, cpct } = attr;
// 攻击区
let atkNum = (atk.base + atk.plus + atk.base * atk.pct / 100);
// 倍率独立乘区
let multiNum = attr.multi / 100;
// 增伤区
let dmgNum = (1 + dmg.base / 100 + dmg.plus / 100);
//console.log({ base: Format.comma(dmg.base, 2), plus: Format.comma(dmg.plus, 2) })
let cpctNum = cpct.base / 100 + cpct.plus / 100;
// 爆伤区
let cdmgNum = cdmg.base / 100 + cdmg.plus / 100;
let enemyDef = attr.enemy.def / 100;
let enemyIgnore = attr.enemy.ignore / 100;
pctNum = pctNum / 100;
let plusNum = 0;
if (talent && attr[talent]) {
let ds = attr[talent];
pctNum += ds.pct / 100;
dmgNum += ds.dmg / 100;
cpctNum += ds.cpct / 100;
cdmgNum += ds.cdmg / 100;
enemyDef += ds.def / 100;
enemyIgnore += ds.ignore / 100;
multiNum += ds.multi / 100;
plusNum += ds.plus;
}
// 防御区
let lv = avatar.level;
let defNum = (lv + 100) / ((lv + 100) + (enemyLv + 100) * (1 - enemyDef) * (1 - enemyIgnore));
// 抗性区
let kx = 10 - (attr.kx || 0);
let kNum = 0.9;
if (kx >= 0) {
kNum = (100 - kx) / 100;
} else {
kNum = 1 - kx / 200
}
// 反应区
let eleNum = 1;
if (ele) {
// todo 更详细
eleNum = (attr.element === "水" ? { zf: 2 } : { zf: 1.5, rh: 2 })[ele] || 1;
if (attr[ele]) {
eleNum = eleNum * (1 + attr[ele] / 100);
}
}
cpctNum = Math.max(0, Math.min(1, cpctNum));
if (cpctNum === 0) {
cdmgNum = 0;
}
// 计算最终伤害
let ret = {
dmg: (atkNum * pctNum * (1 + multiNum) + plusNum) * dmgNum * (1 + cdmgNum) * defNum * kNum * eleNum,
avg: (atkNum * pctNum * (1 + multiNum) + plusNum) * dmgNum * (1 + cpctNum * cdmgNum) * defNum * kNum * eleNum
}
// console.log(attr, { atkNum, pctNum, multiNum, plusNum, dmgNum, cpctNum, cdmgNum, defNum, eleNum, kNum }, ret)
return ret;
};
},
async calcData({ profile, char, avatar, talentData, enemyLv = 91, mode = 'profile', dmgIdx = 0 }) {
let charCalcData = await Calc.getCharCalcRule(char.name); let charCalcData = await Calc.getCharCalcRule(char.name);
//avatar.element; //avatar.element;
@ -299,7 +405,7 @@ let Calc = {
talent talent
} }
let { buffs, details, defParams } = charCalcData; let { buffs, details, defParams, mainAttr, defDmgIdx } = charCalcData;
defParams = defParams || {}; defParams = defParams || {};
@ -317,111 +423,79 @@ let Calc = {
let { msg } = Calc.calcAttr(originalAttr, buffs, meta, defParams || {}); let { msg } = Calc.calcAttr(originalAttr, buffs, meta, defParams || {});
let ret = []; let ret = [], detailMap = [], dmgRet = [], dmgDetail = {};
lodash.forEach(details, (detail) => {
lodash.forEach(details, (detail, detailSysIdx) => {
let params = lodash.merge({}, defParams, detail.params || {}); let params = lodash.merge({}, defParams, detail.params || {});
let { attr } = Calc.calcAttr(originalAttr, buffs, meta, params); let { attr } = Calc.calcAttr(originalAttr, buffs, meta, params);
if (detail.check && !detail.check(Calc.getDs(attr, meta, params))) { if (detail.check && !detail.check(Calc.getDs(attr, meta, params))) {
return; return;
} }
let dmg = Calc.getDmgFn({ attr, avatar, enemyLv }),
let dmg = function (pctNum = 0, talent = false, ele = false) { basicDmgRet;
let { atk, dmg, cdmg, cpct } = attr;
// 攻击区
let atkNum = (atk.base + atk.plus + atk.base * atk.pct / 100);
// 倍率独立乘区
let multiNum = attr.multi / 100;
// 增伤区
let dmgNum = (1 + dmg.base / 100 + dmg.plus / 100);
//console.log({ base: Format.comma(dmg.base, 2), plus: Format.comma(dmg.plus, 2) })
let cpctNum = cpct.base / 100 + cpct.plus / 100;
// 爆伤区
let cdmgNum = cdmg.base / 100 + cdmg.plus / 100;
let enemyDef = attr.enemy.def / 100;
let enemyIgnore = attr.enemy.ignore / 100;
pctNum = pctNum / 100;
let plusNum = 0;
if (talent && attr[talent]) {
let ds = attr[talent];
pctNum += ds.pct / 100;
dmgNum += ds.dmg / 100;
cpctNum += ds.cpct / 100;
cdmgNum += ds.cdmg / 100;
enemyDef += ds.def / 100;
enemyIgnore += ds.ignore / 100;
multiNum += ds.multi / 100;
plusNum += ds.plus;
}
// 防御区
let lv = avatar.level;
let defNum = (lv + 100) / ((lv + 100) + (enemyLv + 100) * (1 - enemyDef) * (1 - enemyIgnore));
// 抗性区
let kx = 10 - (attr.kx || 0);
let kNum = 0.9;
if (kx >= 0) {
kNum = (100 - kx) / 100;
} else {
kNum = 1 - kx / 200
}
// 反应区
let eleNum = 1;
if (ele) {
// todo 更详细
eleNum = (attr.element === "水" ? { zf: 2 } : { zf: 1.5, rh: 2 })[ele] || 1;
if (attr[ele]) {
eleNum = eleNum * (1 + attr[ele] / 100);
}
}
cpctNum = Math.max(0, Math.min(1, cpctNum));
if (cpctNum === 0) {
cdmgNum = 0;
}
// 计算最终伤害
let ret = {
dmg: (atkNum * pctNum * (1 + multiNum) + plusNum) * dmgNum * (1 + cdmgNum) * defNum * kNum * eleNum,
avg: (atkNum * pctNum * (1 + multiNum) + plusNum) * dmgNum * (1 + cpctNum * cdmgNum) * defNum * kNum * eleNum
}
// console.log(attr, { atkNum, pctNum, multiNum, plusNum, dmgNum, cpctNum, cdmgNum, defNum, eleNum, kNum }, ret)
return ret;
};
if (detail.dmg) { if (detail.dmg) {
let dmgRet = detail.dmg({ attr, talent }, dmg); basicDmgRet = detail.dmg({ attr, talent }, dmg);
detail.userIdx = detailMap.length;
detailMap.push(detail);
ret.push({ ret.push({
title: detail.title, title: detail.title,
...dmgRet ...basicDmgRet
}) })
} }
}) })
if (mode === "dmg") {
let detail;
if (dmgIdx && detailMap[dmgIdx - 1]) {
detail = detailMap[dmgIdx - 1];
} else if (!lodash.isUndefined(defDmgIdx) && details[defDmgIdx]) {
detail = details[defDmgIdx];
} else {
detail = detailMap[0];
}
dmgDetail = {
title: detail.title,
userIdx: detail.userIdx,
basicRet: lodash.merge({}, ret[detail.userIdx]),
attr: []
};
mainAttr = mainAttr.split(",");
let params = lodash.merge({}, defParams, detail.params || {});
let basicDmg = dmgDetail.basicRet;
lodash.forEach(mainAttr, (reduceAttr) => {
dmgDetail.attr.push(attrMap[reduceAttr])
let rowData = [];
lodash.forEach(mainAttr, (incAttr) => {
if (incAttr === reduceAttr) {
rowData.push({ type: 'na' });
return;
}
let { attr } = Calc.calcAttr(originalAttr, buffs, meta, params, incAttr, reduceAttr);
let dmg = Calc.getDmgFn({ attr, avatar, enemyLv });
if (detail.dmg) {
let dmgCalcRet = detail.dmg({ attr, talent }, dmg);
rowData.push({
type: dmgCalcRet.avg === basicDmg.avg ? "avg" : (dmgCalcRet.avg > basicDmg.avg ? "gt" : "lt"),
...dmgCalcRet
})
}
})
dmgRet.push(rowData);
})
}
return { return {
ret, ret,
msg msg,
dmgRet,
dmgCfg: dmgDetail
} }
} }
} }
export default Calc; export default Calc;

View File

@ -1,6 +1,6 @@
/* /*
* 请将此文件复制一份命名为 config.js 放置在miao-plugin的根目录 * 请将此文件复制一份命名为 config.js 放置在miao-plugin的根目录
* 申请API Token请在Bot群内联系 @喵喵 或者 @九章 * 由于服务侧压力过大目前已经暂停 #角色面板 token的发放请见谅~
* */ * */
export const config = { export const config = {

View File

@ -37,7 +37,7 @@ export {
let rule = { let rule = {
character: { character: {
reg: "^#(喵喵)?(更新)?(.*)(详情|详细|面板|面版|伤害)?(更新)?$", reg: "^#(喵喵)?(更新)?(.*)(详情|详细|面板|面版|伤害[1-7]?)?(更新)?$",
describe: "【#角色】角色详情", describe: "【#角色】角色详情",
}, },
getArtis: { getArtis: {
@ -95,7 +95,7 @@ lodash.forEach(rule, (r) => {
export { rule }; export { rule };
console.log("喵喵插件初始化~"); console.log(`喵喵插件${currentVersion}初始化~`);
setTimeout(async function () { setTimeout(async function () {
let msgStr = await redis.get("miao:restart-msg"); let msgStr = await redis.get("miao:restart-msg");

View File

@ -318,6 +318,41 @@ body {
.dmg-cont { .dmg-cont {
display: table; display: table;
width: calc(100% - 25px); width: calc(100% - 25px);
margin-top: 10px;
margin-bottom: 10px;
}
.dmg-mode .dmg-list .cont-footer {
display: none;
}
.cont-title {
background: rgba(0, 0, 0, .4);
color: #d3bc8e;
font-family: YS;
padding: 10px 20px;
text-align: left;
}
.cont-title span {
font-size: 12px;
color: #aaa;
margin-left: 10px;
font-family: Number, YS;
font-weight: normal;
}
.cont-footer {
padding: 10px 15px;
font-size: 12px;
background: rgba(0, 0, 0, 0.5);
font-family: YS;
font-weight: normal;
}
.cont-table {
display: table;
width: 100%;
} }
.dmg-cont .tr { .dmg-cont .tr {
@ -360,6 +395,30 @@ body {
min-width: 100px; min-width: 100px;
} }
.profile-mode .dmg-idx {
display: none !important;
}
.profile-mode .dmg-title {
width: 33.3333%;
}
.dmg-mode .dmg-idx {
display: table-cell;
width: 5%;
min-width: initial;
padding-right: 0;
text-align: center;
}
.dmg-mode .dmg-title {
width: 31%;
min-width: initial;
text-align: left;
padding-left: 10px;
padding-right: 0;
}
.dmg .value { .dmg .value {
text-align: center; text-align: center;
@ -369,7 +428,7 @@ body {
font-size: 18px; font-size: 18px;
font-family: Number; font-family: Number;
line-height: 40px; line-height: 40px;
width: 33.333% width: 32%
} }
.dmg-notice { .dmg-notice {
@ -651,11 +710,16 @@ body {
font-family: Number, YS; font-family: Number, YS;
font-size: 13px; font-size: 13px;
font-weight: normal; font-weight: normal;
margin-top: 15px; }
.dmg-msg .thead > div {
text-align: left;
padding-left: 10px;
} }
.dmg-msg .th { .dmg-msg .th {
width: 33%; text-align: left;
padding-left: 10px;
} }
.dmg-msg .tr .td { .dmg-msg .tr .td {
@ -670,6 +734,84 @@ body {
} }
.dmg-calc {
}
.dmg-calc .thead {
}
.dmg-calc .thead > div {
line-height: initial;
}
.dmg-calc .cont-table div {
vertical-align: middle;
text-align: center;
white-space: nowrap;
}
.dmg-calc .title {
text-align: center;
padding-right: 0;
min-width: 70px;
}
.dmg-calc .td {
padding: 5px 0;
}
.dmg-calc strong {
font-weight: normal;
display: block;
font-family: Number, YS;
}
.dmg-calc span {
font-size: 12px;
color: #aaa;
font-family: Number, YS;
}
.dmg-calc .na,
.dmg-calc .eq {
background: rgba(50, 50, 50, .5);
}
.dmg-calc .na {
color: #888;
}
.dmg-calc .lt {
background: rgba(23, 112, 41, 0.5);
}
.dmg-calc .gt {
background: rgba(112, 23, 23, 0.5);
}
.dmg-desc {
color: #aaa;
}
.dmg-desc ul {
padding-left: 10px;
}
.dmg-desc ul li {
color: #aaa;
}
.dmg-desc strong {
color: #d3bc8e;
display: inline;
padding: 0 3px;
font-weight: normal;
}
.artis .stat span { .artis .stat span {
font-size: 13px; font-size: 13px;
line-height: 20px; line-height: 20px;

View File

@ -6,7 +6,7 @@
<link rel="stylesheet" type="text/css" href="{{_res_path}}/common/common.css"/> <link rel="stylesheet" type="text/css" href="{{_res_path}}/common/common.css"/>
<link rel="stylesheet" type="text/css" href="{{_res_path}}/character/detail.css"/> <link rel="stylesheet" type="text/css" href="{{_res_path}}/character/detail.css"/>
</head> </head>
<body {{cfgScale}} class="elem_{{elem}} char-{{name}}"> <body {{cfgScale}} class="elem_{{elem}} char-{{name}} {{mode}}-mode">
<div class="container" id="container"> <div class="container" id="container">
<div class="basic"> <div class="basic">
<div class="main-pic" <div class="main-pic"
@ -49,21 +49,30 @@
</div> </div>
</div> </div>
{{if dmgData.length > 0}} {{if dmgData.length > 0}}
<div class="dmg-cont cont"> <div class="dmg-cont dmg-list cont">
<div class="tr thead"> <div class="cont-title">
<div class="title">伤害类型</div> 伤害计算<span>目标为{{enemyLv}}级小宝,如需调整等级可使用 #敌人等级{{enemyLv}} 来进行设置</span>
<div>暴击伤害</div>
<div>平均伤害(计算暴击率)</div>
</div> </div>
{{each dmgData dmg idx}} <div class="cont-table">
<div class="dmg tr"> <div class="tr thead">
<div class="title">{{dmg.title}}</div> <div class="title dmg-idx">#</div>
<div class="value">{{dmg.dmg}}</div> <div class="title dmg-title">伤害类型</div>
<div class="value">{{dmg.avg}}</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>
<div class="value">{{dmg.dmg}}</div>
<div class="value">{{dmg.avg}}</div>
</div>
{{/each}}
</div>
<div class="cont-footer dmg-desc">
使用命令<strong>#{{name}}伤害</strong>可以查看伤害详情,使用命令<strong>#角色面板帮助</strong>可查看帮助说明
</div> </div>
{{/each}}
</div> </div>
<div class="dmg-notice">目标为{{enemyLv}}级小宝,如需调整等级可使用 #敌人等级{{enemyLv}} 来进行设置</div>
{{/if}} {{/if}}
{{if mode === "profile"}} {{if mode === "profile"}}
@ -110,19 +119,66 @@
{{/if}} {{/if}}
{{if mode === "dmg"}} {{if mode === "dmg"}}
<div class="dmg-cont dmg-msg cont">
<div class="tr thead"> {{if dmgCfg && dmgCfg.attr && dmgCfg.attr.length>0}}
<div class="title"> <div class="dmg-calc dmg-cont cont">
Buff列表 <div class="cont-title">
词条伤害计算<span>#{{name}}伤害{{dmgCfg.userIdx+1}}: 当前计算为[{{dmgCfg.title}}]的 平均伤害</span>
</div>
<div class="cont-table">
<div class="tr thead ">
<div class="td">词条变化</div>
{{each dmgCfg.attr attr}}
<div class="td">
<strong>{{attr.title}}</strong>
<span>+{{attr.text}}</span>
</div>
{{/each}}
</div> </div>
<div class="info">部分Buff的触发条件以及层数可能影响实际伤害结果</div> {{each dmgRet row rowIdx}}
<div class="tr">
<div class="title">
<strong>{{dmgCfg.attr[rowIdx].title}}</strong>
<span>-{{dmgCfg.attr[rowIdx].text}}</span>
</div>
{{each row cell colIdx}}
{{if cell.type === "na"}}
<div class="td na">
<strong>-</strong>
<span>{{dmgCfg.basicRet.avg}}/{{dmgCfg.basicRet.dmg}}</span>
</div>
{{else}}
<div class="td {{cell.type}}">
<strong>{{cell.val}}</strong>
<span>{{cell.avg}}/{{cell.dmg}}</span>
</div>
{{/if}}
{{/each}}
</div>
{{/each}}
</div> </div>
{{each dmgMsg msg}} <div class="cont-footer dmg-desc">
<div class="tr"> <ul>
<div class="th">{{msg[0]}}</div> <li>大数字的含义为圣遗物副词条置换后<strong>平均伤害</strong>的变化,下方的详情数字为<strong>平均伤害</strong>/<strong>暴击伤害</strong></li>
<div class="td">{{msg[1]}}</div> <li><strong>平均伤害</strong>:是将暴击率计算在内的伤害期望,能反映综合的输出能力,不等于实际伤害数字。</li>
<li>可用于评估当前面板下圣遗物副词条的侧重方向。实际游戏情况更加复杂,结果供参考~</li>
<li>如需更换计算的伤害类型,可使用命令 <strong>#{{name}}伤害+序号</strong>来切换,序号参见伤害计算板块</li>
</ul>
</div>
</div>
{{/if}}
<div class="dmg-cont dmg-msg cont">
<div class="cont-title">Buff列表<span>部分Buff的触发条件以及层数可能影响实际伤害结果</span></div>
<div class="cont-table">
{{each dmgMsg msg}}
<div class="tr">
<div class="th">{{msg[0]}}</div>
<div class="td">{{msg[1]}}</div>
</div>
{{/each}}
</div> </div>
{{/each}}
</div> </div>
{{/if}} {{/if}}
<div class="copyright">Created By Yunzai-Bot & Miao-Plugin</div> <div class="copyright">Created By Yunzai-Bot & Miao-Plugin</div>

View File

@ -14,6 +14,8 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.q['技能伤害'] + talent.q['天狐霆雷伤害'] * 3, 'q') dmg: ({ talent }, dmg) => dmg(talent.q['技能伤害'] + talent.q['天狐霆雷伤害'] * 3, 'q')
}]; }];
export const mainAttr = "atk,cpct,cdmg,mastery";
export const buffs = [{ export const buffs = [{
title: `被动天赋:基于元素精通提高杀生樱伤害[eDmg]%`, title: `被动天赋:基于元素精通提高杀生樱伤害[eDmg]%`,
data: { data: {

View File

@ -1,6 +1,6 @@
export const details = [{ export const details = [{
title: "开E后首段普攻", title: "开E后首段普攻",
params: { num: 1}, params: { num: 1 },
dmg: ({ talent }, dmg) => dmg(talent.a['一段伤害'], 'a') dmg: ({ talent }, dmg) => dmg(talent.a['一段伤害'], 'a')
}, { }, {
title: "开E满Buff普攻尾箭", title: "开E满Buff普攻尾箭",
@ -8,10 +8,12 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.a['五段伤害'], 'a') dmg: ({ talent }, dmg) => dmg(talent.a['五段伤害'], 'a')
}, { }, {
title: "开E满Buff尾箭蒸发", title: "开E满Buff尾箭蒸发",
params: { num: 10}, params: { num: 10 },
dmg: ({ talent }, dmg) => dmg(talent.a['五段伤害'], 'a', 'zf') dmg: ({ talent }, dmg) => dmg(talent.a['五段伤害'], 'a', 'zf')
}]; }];
export const mainAttr = "atk,cpct,cdmg,mastery";
export const buffs = [{ export const buffs = [{
title: "焰硝庭火舞开启E后额外提升普通[aMulti]%伤害", title: "焰硝庭火舞开启E后额外提升普通[aMulti]%伤害",
data: { data: {

View File

@ -15,6 +15,9 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.q['冰棱伤害'], 'q') dmg: ({ talent }, dmg) => dmg(talent.q['冰棱伤害'], 'q')
}]; }];
export const defDmgIdx = 2;
export const mainAttr = "atk,cpct,cdmg,mastery";
export const buffs = [{ export const buffs = [{
cons: 1, cons: 1,
title: "甘雨1命霜华失命中减少敌人15%冰抗", title: "甘雨1命霜华失命中减少敌人15%冰抗",
@ -27,4 +30,7 @@ export const buffs = [{
data: { data: {
dmg: ({ params }) => params.q ? 25 : 0 dmg: ({ params }) => params.q ? 25 : 0
} }
}, {
title: "元素精通:融化伤害提高[rh]%",
mastery: "rh"
}]; }];

View File

@ -10,6 +10,8 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.q['水花剑伤害'], 'q') dmg: ({ talent }, dmg) => dmg(talent.q['水花剑伤害'], 'q')
}]; }];
export const defDmgIdx = 1;
export const mainAttr = "hp,atk,cpct,cdmg,mastery";
export const buffs = [{ export const buffs = [{
cons: 2, cons: 2,

View File

@ -9,6 +9,7 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.q['切割伤害'], 'q') dmg: ({ talent }, dmg) => dmg(talent.q['切割伤害'], 'q')
}]; }];
export const mainAttr = "atk,cpct,cdmg";
export const buffs = [{ export const buffs = [{
passive: 1, passive: 1,

View File

@ -9,6 +9,9 @@ export const details = [{
dmg: ({ talent, attr }, dmg) => dmg(talent.q["低血量时技能伤害"], "q") dmg: ({ talent, attr }, dmg) => dmg(talent.q["低血量时技能伤害"], "q")
}]; }];
export const defDmgIdx = 1;
export const mainAttr = "hp,atk,cpct,cdmg,mastery";
export const buffs = [{ export const buffs = [{
title: "蝶引来生开E获得[atkPlus]点攻击力加成", title: "蝶引来生开E获得[atkPlus]点攻击力加成",
data: { data: {

View File

@ -12,6 +12,8 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.q['技能伤害·近战'], 'q','zf') dmg: ({ talent }, dmg) => dmg(talent.q['技能伤害·近战'], 'q','zf')
}]; }];
export const mainAttr = "atk,cpct,cdmg,mastery";
export const buffs = [{ export const buffs = [{
title: "元素精通:蒸发伤害提高[zf]%", title: "元素精通:蒸发伤害提高[zf]%",
mastery: "zf" mastery: "zf"

View File

@ -26,6 +26,9 @@ export const defParams = {
type: 0 type: 0
}; };
export const defDmgIdx = 1;
export const mainAttr = "atk,cpct,cdmg,recharge";
export const buffs = [ export const buffs = [
{ {
title: `恶曜开眼开E元素爆发伤害提升[qDmg]%`, title: `恶曜开眼开E元素爆发伤害提升[qDmg]%`,
@ -39,7 +42,7 @@ export const buffs = [
} }
}, { }, {
check: ({ cons }) => cons >= 2, check: ({ cons }) => cons >= 2,
title: "雷神2命大招无视敌人[qDef]%防御力", title: "雷神2命大招无视敌人[qIgnore]%防御力",
data: { data: {
"qIgnore": 60 "qIgnore": 60
} }

View File

@ -19,6 +19,8 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.a["低空/高空坠地冲击伤害"][1], "a3") dmg: ({ talent }, dmg) => dmg(talent.a["低空/高空坠地冲击伤害"][1], "a3")
}]; }];
export const defDmgIdx = 3;
export const mainAttr = "atk,cpct,cdmg";
export const defParams = { export const defParams = {
layer: 0 layer: 0

View File

@ -543,10 +543,7 @@ let sword = {
"磐岩结绿": [{ "磐岩结绿": [{
title: "基于生命值上限提高攻击力[atkPlus]", title: "基于生命值上限提高攻击力[atkPlus]",
data: { data: {
atkPlus: ({ attr, calc, refine }) => { atkPlus: ({ attr, calc, refine }) => calc(attr.hp) * step(1.2)[refine] / 100
console.log('panyan', calc(attr.hp), step(1.2)[refine]);
return calc(attr.hp) * step(1.2)[refine] / 100
}
} }
}], }],
"斫峰之刃": [{ "斫峰之刃": [{