mirror of
https://github.com/yoimiya-kokomi/miao-plugin.git
synced 2024-11-24 17:19:25 +00:00
1. #角色面板初步增加伤害计算功能,目前支持:雷电将军
This commit is contained in:
parent
5ea9e5b7f8
commit
1ae6546099
@ -131,7 +131,7 @@ export async function updateRes(e) {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
command = `git clone https://gitee.com/yoimiya-kokomi/miao-res-plus.git ${resPath}/miao-res-plus/`;
|
||||
command = `git clone https://gitee.com/yoimiya-kokomi/miao-res-plus.git '${resPath}/miao-res-plus/'`;
|
||||
e.reply("开始尝试安装图片加量包,可能会需要一段时间,请耐心等待~");
|
||||
exec(command, function (error, stdout, stderr) {
|
||||
if (error) {
|
||||
|
@ -5,8 +5,9 @@ import { Cfg } from "../components/index.js";
|
||||
import Profile from "../components/Profile.js";
|
||||
import Format from "../components/Format.js"
|
||||
import Reliquaries from "../components/models/Reliquaries.js";
|
||||
import Calc from "../components/Calc.js";
|
||||
import fs from "fs";
|
||||
import sizeOf from "image-size";
|
||||
|
||||
|
||||
|
||||
//角色昵称
|
||||
@ -603,7 +604,6 @@ export async function renderProfile(e, char, render) {
|
||||
|
||||
let reliquaries = [], totalMark = 0, totalMaxMark = 0;
|
||||
|
||||
const maxMark = Reliquaries.getMaxMark(char.name);
|
||||
let { titles: usefulTitles, mark: usefulMark } = Reliquaries.getUseful(avatar.name);
|
||||
|
||||
lodash.forEach(avatar.reliquaries, (ds) => {
|
||||
@ -620,7 +620,8 @@ export async function renderProfile(e, char, render) {
|
||||
ds.attrs = Profile.formatArti(arti.attrs);
|
||||
}
|
||||
posIdx[pos].data = ds;
|
||||
})
|
||||
});
|
||||
|
||||
lodash.forEach(posIdx, (ds) => {
|
||||
if (ds && ds.data) {
|
||||
reliquaries.push(ds.data);
|
||||
@ -629,6 +630,16 @@ export async function renderProfile(e, char, render) {
|
||||
}
|
||||
});
|
||||
|
||||
let dmgMsg = [], dmgData = [];
|
||||
let dmgCalc = await Calc.calcData(profile, char, avatar);
|
||||
if (dmgCalc && dmgCalc.ret) {
|
||||
lodash.forEach(dmgCalc.ret, (ds) => {
|
||||
ds.dmg = Format.comma(ds.dmg, 1);
|
||||
ds.avg = Format.comma(ds.avg, 1);
|
||||
dmgData.push(ds);
|
||||
})
|
||||
dmgMsg = dmgCalc.msg;
|
||||
}
|
||||
|
||||
let base64 = await render("character", "detail", {
|
||||
save_id: uid,
|
||||
@ -640,6 +651,8 @@ export async function renderProfile(e, char, render) {
|
||||
cons: char.cons,
|
||||
name: char.name,
|
||||
elem: char.elem,
|
||||
dmgData,
|
||||
dmgMsg,
|
||||
reliquaries,
|
||||
totalMark: c(totalMark, 1),
|
||||
totalMaxMark,
|
||||
|
344
components/Calc.js
Normal file
344
components/Calc.js
Normal file
@ -0,0 +1,344 @@
|
||||
import fs from "fs";
|
||||
import lodash from "lodash";
|
||||
import Format from "./Format.js";
|
||||
import { buffs } from "../resources/meta/reliquaries/calc.js";
|
||||
|
||||
let Calc = {
|
||||
|
||||
async getCharCalcRule(name) {
|
||||
|
||||
const _path = process.cwd();
|
||||
const cfgPath = `${_path}/plugins/miao-plugin/resources/meta/character/${name}/calc.js`;
|
||||
|
||||
|
||||
let details, buffs = [], defParams = {};
|
||||
if (fs.existsSync(cfgPath)) {
|
||||
let fileData = await import (`file://${cfgPath}`);
|
||||
details = fileData.details || false;
|
||||
buffs = fileData.buffs || [];
|
||||
defParams = fileData.defParams || {};
|
||||
}
|
||||
|
||||
if (details) {
|
||||
return { details, buffs, defParams }
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// 获取基础属性
|
||||
attr(profile, avatar) {
|
||||
let ret = {},
|
||||
{ attr } = profile;
|
||||
|
||||
// 基础属性
|
||||
lodash.forEach("atk,def,hp".split(","), (key) => {
|
||||
ret[key] = {
|
||||
base: attr[`${key}Base`] * 1 || 0,
|
||||
plus: attr[key] * 1 - attr[`${key}Base`] * 1 || 0,
|
||||
pct: 0
|
||||
}
|
||||
})
|
||||
|
||||
lodash.forEach("mastery,recharge".split(","), (key) => {
|
||||
ret[key] = {
|
||||
base: attr[key] * 1 || 0,
|
||||
plus: 0,
|
||||
pct: 0
|
||||
}
|
||||
})
|
||||
|
||||
lodash.forEach({ cRate: "cpct", cDmg: "cdmg", hInc: "heal" }, (val, key) => {
|
||||
ret[val] = {
|
||||
base: attr[key] * 1 || 0,
|
||||
plus: 0,
|
||||
pct: 0
|
||||
}
|
||||
})
|
||||
|
||||
lodash.forEach("dmg,phy".split(","), (key) => {
|
||||
ret[key] = {
|
||||
base: attr[key + "Bonus"] * 1 || 0,
|
||||
plus: 0,
|
||||
pct: 0
|
||||
}
|
||||
})
|
||||
|
||||
// a
|
||||
lodash.forEach("a,a2,a3,e,q".split(","), (key) => {
|
||||
ret[key] = {
|
||||
pct: 0, // 倍率加成
|
||||
def: 0, // 防御降低
|
||||
ignore: 0, // 无视防御
|
||||
plus: 0, // 伤害值提高
|
||||
dmg: 0, // 伤害提高
|
||||
cpct: 0,// 暴击提高
|
||||
cdmg: 0 //爆伤提高
|
||||
}
|
||||
})
|
||||
|
||||
ret.enemy = {
|
||||
def: 0, // 降低防御
|
||||
ignore: 0, // 无视防御
|
||||
phy: 0 // 物理防御
|
||||
}
|
||||
|
||||
ret.weaponType = avatar.weapon.type_name;
|
||||
ret.element = avatar.element;
|
||||
ret.refine = (profile.weapon.refine * 1 - 1) || 0;
|
||||
|
||||
return ret;
|
||||
|
||||
},
|
||||
|
||||
// 获取天赋数据
|
||||
talent(profile, char) {
|
||||
let ret = {};
|
||||
|
||||
lodash.forEach(['a', 'e', 'q'], (key) => {
|
||||
let lv = profile.talent[key] * 1 || 1,
|
||||
lvKey = `Lv${lv}`;
|
||||
|
||||
let map = {};
|
||||
|
||||
lodash.forEach(char.talent[key].tables, (tr) => {
|
||||
let val = tr.values[lv - 1];
|
||||
val = val.replace(/[^\x00-\xff]/g, "").trim();
|
||||
|
||||
let valArr = [];
|
||||
lodash.forEach(val.split("/"), (v, idx) => {
|
||||
let valNum = 0;
|
||||
lodash.forEach(v.split("+"), (v) => {
|
||||
valNum += v.replace("%", "").trim() * 1;
|
||||
})
|
||||
valArr.push(valNum);
|
||||
});
|
||||
|
||||
if (isNaN(valArr[0])) {
|
||||
map[tr.name] = false;
|
||||
} else if (valArr.length === 1) {
|
||||
map[tr.name] = valArr[0];
|
||||
} else {
|
||||
map[tr.name] = valArr;
|
||||
}
|
||||
})
|
||||
ret[key] = map;
|
||||
})
|
||||
return ret;
|
||||
},
|
||||
|
||||
calcAttr(originalAttr, buffs, meta, params = {}) {
|
||||
let attr = lodash.merge({}, originalAttr);
|
||||
|
||||
let msg = [];
|
||||
|
||||
|
||||
lodash.forEach(buffs, (buff) => {
|
||||
let ds = {
|
||||
...meta,
|
||||
attr,
|
||||
params,
|
||||
refine: attr.refine
|
||||
};
|
||||
|
||||
// 如果存在rule,则进行计算
|
||||
if (buff.rule && !buff.rule(ds)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let title = buff.title;
|
||||
lodash.forEach(buff.data, (val, key) => {
|
||||
|
||||
if (lodash.isFunction(val)) {
|
||||
val = val(ds);
|
||||
}
|
||||
|
||||
title = title.replace(`[${key}]`, Format.comma(val, 1));
|
||||
// 技能提高
|
||||
let tRet = /^(a|a2|a3|e|q)(Def|Ignore|Dmg|Plus|Pct|Cpct|Cdmg)$/.exec(key);
|
||||
if (tRet) {
|
||||
attr[tRet[1]][tRet[2].toLowerCase()] += val * 1 || 0;
|
||||
return;
|
||||
}
|
||||
let aRet = /^(hp|def|atk|mastery|cpct|cdmg|heal|recharge|dmg|phy)(Plus|Pct)?$/.exec(key);
|
||||
if (aRet) {
|
||||
attr[aRet[1]][aRet[2] ? aRet[2].toLowerCase() : "plus"] += val * 1 || 0;
|
||||
return;
|
||||
}
|
||||
if (key === "enemyDef") {
|
||||
attr.enemy.def += val * 1 || 0;
|
||||
}
|
||||
});
|
||||
msg.push(title);
|
||||
})
|
||||
|
||||
return {
|
||||
attr, msg
|
||||
}
|
||||
},
|
||||
|
||||
async weapon(weaponName) {
|
||||
const _path = process.cwd();
|
||||
const cfgPath = `${_path}/plugins/miao-plugin/resources/meta/weapons/calc.js`;
|
||||
|
||||
|
||||
let weapons = {};
|
||||
if (fs.existsSync(cfgPath)) {
|
||||
let fileData = await import (`file://${cfgPath}`);
|
||||
weapons = fileData.weapons || {};
|
||||
}
|
||||
|
||||
let weaponCfg = weapons[weaponName] || [];
|
||||
if (lodash.isPlainObject(weaponCfg)) {
|
||||
weaponCfg = [weaponCfg];
|
||||
}
|
||||
|
||||
lodash.forEach(weaponCfg, (ds) => {
|
||||
ds.title = `${weaponName}:${ds.title}`;
|
||||
if (ds.refine) {
|
||||
ds.data = ds.data || {};
|
||||
lodash.forEach(ds.refine, (r, key) => {
|
||||
ds.data[key] = ({ refine }) => r[refine] * (ds.buffCount || 1);
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return weaponCfg;
|
||||
},
|
||||
|
||||
async reliquaries(sets) {
|
||||
const _path = process.cwd();
|
||||
const cfgPath = `${_path}/plugins/miao-plugin/resources/meta/reliquaries/calc.js`;
|
||||
|
||||
let buffs = {};
|
||||
if (fs.existsSync(cfgPath)) {
|
||||
let fileData = await import (`file://${cfgPath}`);
|
||||
buffs = fileData.buffs || {};
|
||||
}
|
||||
|
||||
let setMap = {};
|
||||
|
||||
lodash.forEach(sets, (set) => {
|
||||
if (set && set.set) {
|
||||
let name = set.set.name
|
||||
setMap[name] = (setMap[name] || 0) + 1
|
||||
}
|
||||
});
|
||||
|
||||
let retBuffs = [];
|
||||
|
||||
lodash.forEach(setMap, (count, setName) => {
|
||||
if (count >= 2 && buffs[setName + 2]) {
|
||||
retBuffs.push(buffs[setName + 2])
|
||||
}
|
||||
if (count >= 4 && buffs[setName + 4]) {
|
||||
retBuffs.push(buffs[setName + 4])
|
||||
}
|
||||
})
|
||||
return retBuffs;
|
||||
},
|
||||
async calcData(profile, char, avatar) {
|
||||
let charCalcData = await Calc.getCharCalcRule(char.name);
|
||||
|
||||
//avatar.element;
|
||||
|
||||
if (!charCalcData) {
|
||||
return false;
|
||||
}
|
||||
let talent = Calc.talent(profile, char);
|
||||
|
||||
let meta = {
|
||||
cons: profile.cons * 1,
|
||||
...profile.talent,
|
||||
talent,
|
||||
}
|
||||
|
||||
let { buffs, details, defParams } = charCalcData;
|
||||
|
||||
defParams = defParams || {};
|
||||
|
||||
let originalAttr = Calc.attr(profile, avatar);
|
||||
|
||||
let weaponBuffs = await Calc.weapon(profile.weapon.name);
|
||||
let reliBuffs = await Calc.reliquaries(avatar.reliquaries);
|
||||
buffs = lodash.concat(buffs, weaponBuffs, reliBuffs);
|
||||
|
||||
lodash.forEach(buffs, (buff) => {
|
||||
buff.sort = lodash.isUndefined(buff.sort) ? 1 : buff.sort
|
||||
});
|
||||
|
||||
buffs = lodash.sortBy(buffs, ["sort"]);
|
||||
|
||||
let { msg } = Calc.calcAttr(originalAttr, buffs, meta, defParams || {});
|
||||
|
||||
let ret = [];
|
||||
|
||||
lodash.forEach(details, (detail) => {
|
||||
|
||||
let params = lodash.merge({}, defParams, detail.params || {});
|
||||
|
||||
let { attr } = Calc.calcAttr(originalAttr, buffs, meta, params);
|
||||
|
||||
let dmg = function (pctNum = 0, talent = false) {
|
||||
let { atk, dmg, cdmg, cpct } = attr;
|
||||
// 攻击区
|
||||
let atkNum = (atk.base + atk.plus + atk.base * atk.pct / 100);
|
||||
|
||||
// 增伤区
|
||||
let dmgNum = (1 + dmg.base + 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 防御区
|
||||
let enemyLv = 86, lv = 90;
|
||||
let defNum = (lv + 100) / ((lv + 100) + (enemyLv + 100) * (1 - enemyDef) * (1 - enemyIgnore));
|
||||
|
||||
// 抗性区
|
||||
let kNum = 0.9;
|
||||
|
||||
// 计算最终伤害
|
||||
return {
|
||||
dmg: atkNum * pctNum * dmgNum * (1 + cdmgNum) * defNum * kNum,
|
||||
avg: atkNum * pctNum * dmgNum * (1 + cpctNum * cdmgNum) * defNum * kNum
|
||||
}
|
||||
};
|
||||
|
||||
if (detail.dmg) {
|
||||
let dmgRet = detail.dmg({ attr, talent }, dmg);
|
||||
ret.push({
|
||||
title: detail.title,
|
||||
...dmgRet
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
ret,
|
||||
msg
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default Calc;
|
@ -69,6 +69,24 @@ const artifactMap = {
|
||||
}
|
||||
|
||||
|
||||
let posIdx = {
|
||||
"生之花": {
|
||||
idx: 1
|
||||
},
|
||||
"死之羽": {
|
||||
idx: 2
|
||||
},
|
||||
"时之沙": {
|
||||
idx: 3
|
||||
},
|
||||
"空之杯": {
|
||||
idx: 4
|
||||
},
|
||||
"理之冠": {
|
||||
idx: 5
|
||||
}
|
||||
};
|
||||
|
||||
let Data = {
|
||||
getData(uid, data) {
|
||||
let ret = {
|
||||
@ -238,6 +256,8 @@ let Profile = {
|
||||
e.reply(`请求失败:${data.msg || "未知错误"}`);
|
||||
return false;
|
||||
}
|
||||
// 请求成功Bot侧对该uid冷却10分钟
|
||||
// 请勿将时间改短,10分钟之内若发起请求会命中服务侧的uid缓存,返回之前的数据,并导致服务侧重新计时
|
||||
await redis.set(`miao:role-all:${uid}`, 'pending', { EX: 600 });
|
||||
data = data.data;
|
||||
let userData = {};
|
||||
@ -262,6 +282,7 @@ let Profile = {
|
||||
fs.writeFileSync(userFile, JSON.stringify(userData), "", " ");
|
||||
return data;
|
||||
},
|
||||
|
||||
get(uid, charId) {
|
||||
const userFile = `${userPath}/${uid}.json`;
|
||||
let userData = {};
|
||||
@ -273,6 +294,19 @@ let Profile = {
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
getAll(uid) {
|
||||
const userFile = `${userPath}/${uid}.json`;
|
||||
let userData = {};
|
||||
if (fs.existsSync(userFile)) {
|
||||
userData = JSON.parse(fs.readFileSync(userFile, "utf8")) || {};
|
||||
}
|
||||
if (userData && userData.chars) {
|
||||
return userData.chars;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
formatArti(ds) {
|
||||
if (lodash.isArray(ds[0])) {
|
||||
let ret = [];
|
||||
@ -301,6 +335,7 @@ let Profile = {
|
||||
}
|
||||
return [title, val];
|
||||
},
|
||||
|
||||
getArtiMark(data, ds) {
|
||||
Reliquaries.getMark(data)
|
||||
let total = 0;
|
||||
@ -313,6 +348,43 @@ let Profile = {
|
||||
total += 20;
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
};
|
||||
export default Profile;
|
||||
|
@ -10,13 +10,19 @@ body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.container:after {
|
||||
|
||||
.basic {
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.basic:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
top: 115px;
|
||||
height: 410px;
|
||||
bottom: 0;
|
||||
right: 8px;
|
||||
box-shadow: 0 0 2px 0 #fff;
|
||||
border-radius: 5px;
|
||||
@ -63,11 +69,13 @@ body {
|
||||
|
||||
.detail li {
|
||||
width: 300px;
|
||||
font-size: 18px;
|
||||
font-size: 17px;
|
||||
list-style: none;
|
||||
padding: 5px 100px 5px 35px;
|
||||
padding: 0 100px 0 35px;
|
||||
position: relative;
|
||||
font-family: YS;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
font-weight: 400;
|
||||
text-shadow: 0 0 1px rgba(0, 0, 0, .5);
|
||||
}
|
||||
@ -213,14 +221,14 @@ body {
|
||||
.char-talents {
|
||||
display: flex;
|
||||
width: 300px;
|
||||
margin-bottom: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.char-cons {
|
||||
display: flex;
|
||||
width: 250px;
|
||||
position: absolute;
|
||||
top: 465px;
|
||||
bottom: 5px;
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
@ -295,13 +303,87 @@ body {
|
||||
}
|
||||
|
||||
|
||||
/*** dmg ***/
|
||||
|
||||
.dmg-cont {
|
||||
border-radius: 10px;
|
||||
background: url("../common/cont/card-bg.png") top left repeat-x;
|
||||
background-size: auto 100%;
|
||||
margin: 5px 15px 5px 10px;
|
||||
position: relative;
|
||||
box-shadow: 0 0 1px 0 #ccc, 2px 2px 4px 0 rgba(50, 50, 50, .8);
|
||||
overflow: hidden;
|
||||
display: table;
|
||||
width: calc(100% - 25px);
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dmg-cont .tr {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.dmg-cont .tr:nth-child(even) {
|
||||
background: rgba(0, 0, 0, .4);
|
||||
}
|
||||
|
||||
.dmg-cont .tr:nth-child(odd) {
|
||||
background: rgba(50, 50, 50, .4);
|
||||
}
|
||||
|
||||
.dmg-cont .tr > div {
|
||||
display: table-cell;
|
||||
box-shadow: 0 0 1px 0 #fff;
|
||||
}
|
||||
|
||||
.dmg-cont .th {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dmg-cont .th > div {
|
||||
font-family: YS;
|
||||
color: #d3bc8e;
|
||||
background: rgba(0, 0, 0, .4);
|
||||
line-height: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
|
||||
.dmg-cont .title {
|
||||
font-family: YS;
|
||||
color: #d3bc8e;
|
||||
padding-right: 15px;
|
||||
text-align: right;
|
||||
background: rgba(0, 0, 0, .4);
|
||||
}
|
||||
|
||||
|
||||
.dmg .value {
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
display: block;
|
||||
height: 40px;
|
||||
font-size: 18px;
|
||||
font-family: Number;
|
||||
line-height: 40px;
|
||||
width: 33.333%
|
||||
}
|
||||
|
||||
.dmg-notice {
|
||||
font-size: 12px;
|
||||
text-align: right;
|
||||
color: #eee;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
|
||||
/*** artis***/
|
||||
.artis {
|
||||
display: flex;
|
||||
width: 600px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 5px;
|
||||
padding: 5px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.artis .item {
|
||||
@ -365,7 +447,7 @@ body {
|
||||
}
|
||||
|
||||
.mark-ACE,
|
||||
.mark-ACE²{
|
||||
.mark-ACE² {
|
||||
color: #e85656;
|
||||
font-weight: bold;
|
||||
}
|
||||
@ -396,11 +478,13 @@ body {
|
||||
}
|
||||
|
||||
.artis ul.detail li {
|
||||
padding: 3px;
|
||||
padding: 0 3px;
|
||||
font-size: 14px;
|
||||
position: initial;
|
||||
width: 100%;
|
||||
display: table;
|
||||
line-height: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
|
||||
@ -410,7 +494,7 @@ body {
|
||||
|
||||
.artis ul.detail li.arti-main {
|
||||
font-size: 16px;
|
||||
padding: 8px 3px;
|
||||
padding: 3px 3px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@ -479,7 +563,8 @@ body {
|
||||
right: 0;
|
||||
left: 0;
|
||||
text-align: right;
|
||||
padding: 8px 12px 10px 0;
|
||||
padding: 13px 12px 13px 0;
|
||||
z-index: 3;
|
||||
background-image: linear-gradient(to right, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.7));
|
||||
}
|
||||
|
||||
@ -566,9 +651,11 @@ body {
|
||||
.char-优菈 .main-pic {
|
||||
margin-left: -175px;
|
||||
}
|
||||
|
||||
.char-烟绯 .main-pic {
|
||||
margin-left: -135px;
|
||||
}
|
||||
|
||||
.char-香菱 .main-pic {
|
||||
margin-left: -195px;
|
||||
}
|
@ -48,6 +48,23 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
{{if dmgData.length > 0}}
|
||||
<div class="dmg-cont cont">
|
||||
<div class="tr th">
|
||||
<div class="title">伤害类型</div>
|
||||
<div>暴击伤害</div>
|
||||
<div>平均伤害(计算暴击率)</div>
|
||||
</div>
|
||||
{{each dmgData dmg idx}}
|
||||
<div class="dmg tr">
|
||||
<div class="title">{{dmg.title}}</div>
|
||||
<div class="value">{{dmg.dmg}}</div>
|
||||
<div class="value">{{dmg.avg}}</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="dmg-notice">伤害计算功能完善中,结果可能不准确,计算数据仅供参考</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="artis">
|
||||
<div>
|
||||
@ -61,7 +78,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="item stat">
|
||||
<div ><strong class="mark-{{markScore}}">{{markScore}}</strong><span>圣遗物评级</span></div>
|
||||
<div><strong class="mark-{{markScore}}">{{markScore}}</strong><span>圣遗物评级</span></div>
|
||||
<div><strong>{{totalMark}}</strong><span>圣遗物总分</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
@font-face {
|
||||
font-family: "YS";
|
||||
src: url("../common/font/HYWenHei-55W.ttf");
|
||||
src: url("../common/font/HYWH-85W.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
BIN
resources/common/font/HYWH-85W.ttf
Normal file
BIN
resources/common/font/HYWH-85W.ttf
Normal file
Binary file not shown.
51
resources/meta/character/雷电将军/calc.js
Normal file
51
resources/meta/character/雷电将军/calc.js
Normal file
@ -0,0 +1,51 @@
|
||||
export const details = [{
|
||||
title: "零愿力Q首刀",
|
||||
params: {
|
||||
type: 1,
|
||||
num: 0
|
||||
},
|
||||
dmg: ({ talent, attr }, dmg) => dmg(talent.q["梦想一刀基础伤害"], "q")
|
||||
}, {
|
||||
title: "满愿力Q首刀",
|
||||
params: {
|
||||
type: 0,
|
||||
num: 60
|
||||
},
|
||||
dmg: ({ talent, attr }, dmg) => dmg(talent.q["梦想一刀基础伤害"], "q")
|
||||
}, {
|
||||
title: "满愿力Q后重击",
|
||||
params: {
|
||||
type: 1,
|
||||
num: 60
|
||||
},
|
||||
dmg: ({ talent, attr }, dmg) => dmg(talent.q["重击伤害"], "q")
|
||||
}]
|
||||
|
||||
export const defParams = {
|
||||
num: 60,
|
||||
type: 0
|
||||
};
|
||||
|
||||
export const buffs = [
|
||||
{
|
||||
title: `E被动:元素爆发伤害提升[qDmg]%`,
|
||||
data: {
|
||||
"qDmg": ({ talent }) => talent.e["元素爆发伤害提高"] * 90
|
||||
}
|
||||
}, {
|
||||
rule: ({ cons }) => cons >= 2,
|
||||
title: "2命效果:大招无视敌人[qDef]%防御力",
|
||||
data: {
|
||||
"qIgnore": 60
|
||||
}
|
||||
}, {
|
||||
title: "Q被动:满愿力获得[qPct]%大招倍率加成",
|
||||
data: {
|
||||
"qPct": ({ talent, params }) => talent.q["愿力加成"][params.type || 0] * params.num
|
||||
}
|
||||
}, {
|
||||
title: "基于元素充能获得[dmg]%雷伤加成",
|
||||
data: {
|
||||
dmg: ({ attr }) => Math.max(attr.recharge.base + attr.recharge.plus - 100, 0) * 0.4
|
||||
}
|
||||
}];
|
183
resources/meta/reliquaries/calc.js
Normal file
183
resources/meta/reliquaries/calc.js
Normal file
@ -0,0 +1,183 @@
|
||||
export const buffs = {
|
||||
"行者之心4": {
|
||||
title: "行者4:重击的暴击率提高30%",
|
||||
data: {
|
||||
a2Cpct: 30
|
||||
}
|
||||
},
|
||||
"勇士之心4": {
|
||||
title: "勇士4:对生命值高于50%的敌人,造成的伤害增加30%",
|
||||
data: {
|
||||
dmg: 30
|
||||
}
|
||||
},
|
||||
"武人2": {
|
||||
title: "武人2: 普攻与重击造成的伤害提高15%",
|
||||
data: {
|
||||
aDmg: 15,
|
||||
a2Dmg: 15
|
||||
}
|
||||
},
|
||||
"武人4": {
|
||||
title: "武人4:施放元素战技后的8秒内,普攻和重击伤害提升25%",
|
||||
data: {
|
||||
aDmg: 25,
|
||||
a2Dmg: 25
|
||||
}
|
||||
},
|
||||
"战狂4": {
|
||||
title: "战狂4:生命值低于70%时,暴击率提升24%",
|
||||
data: {
|
||||
cpct: 24
|
||||
}
|
||||
},
|
||||
"染血的骑士道4": {
|
||||
title: "染血4:击败敌人后的10秒内,重击造成的伤害提升50%",
|
||||
data: {
|
||||
a2Dmg: 50
|
||||
}
|
||||
},
|
||||
"角斗士的终幕礼4": {
|
||||
check: ({ weaponType }) => ['单手剑', '双手剑', '长柄武器'].includes(weaponType),
|
||||
title: "角斗4:角色普通攻击造成的伤害提高35%",
|
||||
data: {
|
||||
aDmg: 35
|
||||
}
|
||||
},
|
||||
"流浪大地的乐团4": {
|
||||
check: ({ weaponType }) => ['法器', '弓箭'].includes(weaponType),
|
||||
title: "乐团4:角色重击造成的伤害提高35%",
|
||||
data: {
|
||||
a2Dmg: 35
|
||||
}
|
||||
},
|
||||
"苍白之火4": {
|
||||
title: "苍白4:2层提高18%攻击力,物理伤害额外提高25%",
|
||||
data: {
|
||||
atkPct: 18,
|
||||
phy: 25
|
||||
}
|
||||
},
|
||||
"赌徒2": {
|
||||
title: "赌徒2:元素战技造成的伤害提升20%",
|
||||
data: {
|
||||
eDmg: 20
|
||||
}
|
||||
},
|
||||
"悠古的磐岩4": {
|
||||
title: "磐岩4:获得元素反应晶片,对应元素伤害提高35%",
|
||||
data: {
|
||||
dmg: 35
|
||||
}
|
||||
},
|
||||
"炽烈的炎之魔女4": {
|
||||
title: "魔女4:蒸发、融化伤害提高15%,2层获得15%火元素伤害加成",
|
||||
data: {
|
||||
zf: 15,
|
||||
rh: 15,
|
||||
dmg: 15
|
||||
}
|
||||
},
|
||||
"昔日宗室之仪2": {
|
||||
title: "宗室2:元素爆发造成的伤害提升20%",
|
||||
data: {
|
||||
qDmg: 20
|
||||
}
|
||||
},
|
||||
"昔日宗室之仪4": {
|
||||
title: "宗室4:施放元素爆发后,攻击力提升20%",
|
||||
data: {
|
||||
atkPct: 20
|
||||
}
|
||||
},
|
||||
"冰风迷途的勇士4": {
|
||||
title: "冰套4:攻击处于冰元素影响下的敌人时,暴击率提高20%",
|
||||
data: {
|
||||
cpct: 20
|
||||
}
|
||||
},
|
||||
"沉沦之心4": {
|
||||
title: "水套4:施放元素战技后,普攻与重击伤害提高30%",
|
||||
data: {
|
||||
aDmg: 30,
|
||||
a2Dmg: 30
|
||||
}
|
||||
},
|
||||
"冰之川与雪之砂4": {
|
||||
title: "冰雪4:融化加成提高15%,释放元素爆发后,冰伤提高30%",
|
||||
data: {
|
||||
rh: 15,
|
||||
dmg: 30
|
||||
}
|
||||
},
|
||||
"追忆之注连4": {
|
||||
title: "追忆4:施放元素战技后,普通攻击、重击、下落攻击造成的伤害提高50%",
|
||||
data: {
|
||||
aDmg: 50,
|
||||
a2Dmg: 50,
|
||||
a3Dmg: 50
|
||||
}
|
||||
},
|
||||
"逆飞的流星4": {
|
||||
title: "逆飞4:处于护盾庇护下时,获得40%普攻和重击伤害加成",
|
||||
data: {
|
||||
aDmg: 40,
|
||||
a2Dmg: 40
|
||||
}
|
||||
},
|
||||
"平息鸣雷的尊者4": {
|
||||
title: "平雷4:对处于雷元素影响下的敌人造成的伤害提升35%",
|
||||
data: {
|
||||
dmg: 35
|
||||
}
|
||||
},
|
||||
"渡过烈火的贤人4": {
|
||||
title: "渡火4:对处于火元素影响下的敌人造成的伤害提升35%",
|
||||
data: {
|
||||
dmg: 35
|
||||
}
|
||||
},
|
||||
"教官4": {
|
||||
title: "教官4:触发元素反应后,队伍中所有角色的元素精通提高120点",
|
||||
data: {
|
||||
mastery: 120
|
||||
}
|
||||
},
|
||||
"少女4": {
|
||||
title: "少女4:施放元素战技或元素爆发,受治疗效果加成提高20%",
|
||||
data: {
|
||||
heal: 20
|
||||
}
|
||||
},
|
||||
"千岩牢固4": {
|
||||
title: "千岩4:元素战技命中敌人后,攻击力提升20%",
|
||||
data: {
|
||||
atkPct: 20
|
||||
}
|
||||
},
|
||||
"绝缘之旗印4": {
|
||||
title: "绝缘4:基于元素充能效率提高元素爆发[qDmg]%伤害",
|
||||
data: {
|
||||
qDmg: ({ attr }) => Math.min(75, (attr.recharge.base + attr.recharge.plus) * 0.25)
|
||||
}
|
||||
},
|
||||
"华馆梦醒形骸记4": {
|
||||
title: "华馆4:满层获得24%防御及24%岩伤加成",
|
||||
data: {
|
||||
defPct: 24,
|
||||
dmg: 24
|
||||
}
|
||||
},
|
||||
"辰砂往生录4": {
|
||||
title: "辰砂4:满层提高48%攻击力",
|
||||
data: {
|
||||
atkPct: 48
|
||||
}
|
||||
},
|
||||
"来歆余响4": {
|
||||
title: "余响4:触发提高普攻[aPlus]伤害",
|
||||
data: {
|
||||
aPlus: ({ attr }) => (attr.atk.base + attr.atk.plus + attr.atk.pct * attr.atk.base / 100) * 0.7
|
||||
}
|
||||
}
|
||||
}
|
111
resources/meta/weapons/calc.js
Normal file
111
resources/meta/weapons/calc.js
Normal file
@ -0,0 +1,111 @@
|
||||
let polearm = {
|
||||
"白缨枪": {
|
||||
title: "白缨枪普通攻击伤害提高[aDmg]%",
|
||||
refine: { aDmg: [24, 30, 36, 42, 48] }
|
||||
},
|
||||
"黑岩刺枪": {
|
||||
title: "黑岩刺枪满层攻击力加成[atkPct]%",
|
||||
data: {
|
||||
atkPct: ({ refine }) => [12, 15, 18, 21, 24][refine] * 3
|
||||
}
|
||||
},
|
||||
"决斗之枪": {
|
||||
title: "身边敌人少于2个时,获得[atkPct]%的攻击力提升",
|
||||
refine: {
|
||||
atkPct: [24, 30, 36, 42, 48]
|
||||
}
|
||||
},
|
||||
"匣里灭辰": {
|
||||
title: "对于水或或元素影响的敌人造成伤害提高[dmgPct]%",
|
||||
refine: {
|
||||
dmgPct: [20, 24, 28, 32, 36]
|
||||
}
|
||||
},
|
||||
"千岩长枪": {
|
||||
title: "四璃月队伍提高[atkPct]%攻击力及[cpct]%的暴击率提高",
|
||||
refine: {
|
||||
atkPct: [7, 8, 9, 10, 11],
|
||||
cpct: [3, 4, 5, 6, 7]
|
||||
}
|
||||
},
|
||||
"试作星镰": {
|
||||
title: "释放元素战技后,2层Buff普攻与重击造成伤害提高[aDmg]%",
|
||||
buffCount: 2,
|
||||
refine: {
|
||||
aDmg: [8, 10, 12, 14, 16],
|
||||
a2Dmg: [8, 10, 12, 14, 16]
|
||||
}
|
||||
},
|
||||
"宗室猎枪": {
|
||||
title: "3层Buff暴击提高[cpct]%",
|
||||
buffCount: 3,
|
||||
refine: {
|
||||
cpct: [8, 10, 12, 14, 16]
|
||||
}
|
||||
},
|
||||
"喜多院十文字": {
|
||||
title: "元素战技伤害提升[eDmg]%",
|
||||
refine: {
|
||||
eDmg: [6, 7.5, 9, 10.5, 12]
|
||||
}
|
||||
},
|
||||
"渔获": {
|
||||
title: "元素爆发造成伤害提高[qDmg]%,元素爆发的暴击率提高[qCpct]%",
|
||||
refine: {
|
||||
qDmg: [16, 20, 24, 28, 32],
|
||||
qCpct: [6, 7.5, 9, 10.5, 12]
|
||||
}
|
||||
},
|
||||
"断浪长鳍": {
|
||||
title: "满层元素爆发伤害提高[qDmg]%",
|
||||
refine: { qDmg: [40, 50, 60, 70, 80] }
|
||||
},
|
||||
"贯虹之槊": {
|
||||
title: "护盾满层状态提高攻击力[atkPct]%",
|
||||
buffCount: 10,
|
||||
refine: {
|
||||
atkPct: [4, 5, 6, 7, 8]
|
||||
}
|
||||
},
|
||||
"和璞鸢": {
|
||||
title: "满层攻击力提高[atkPct]%,伤害提升[dmgPct]%",
|
||||
refine: {
|
||||
atkPct: [3.2 * 7, 3.9 * 7, 4.6 * 7, 5.3 * 7, 6 * 7],
|
||||
dmgPct: [12, 15, 18, 21, 24]
|
||||
}
|
||||
},
|
||||
"天空之脊": {
|
||||
title: "暴击率提升[cpct]%",
|
||||
refine: {
|
||||
cpct: [8, 10, 12, 14, 16]
|
||||
}
|
||||
},
|
||||
"护摩之杖": {
|
||||
title: "角色生命低于50%时获得攻击力提升[atkPlus]",
|
||||
data: {
|
||||
atkPlus: ({ attr, refine }) => {
|
||||
let { hp } = attr,
|
||||
totalHp = hp.base + hp.plus + hp.pct * hp.base / 100;
|
||||
return totalHp * [1, 1.2, 1.4, 1.6, 1.8][refine] / 100
|
||||
}
|
||||
}
|
||||
},
|
||||
"薙草之稻光": [{
|
||||
title: "元素爆发12秒内元素充能提高[rechargePlus]%",
|
||||
sort: 0,
|
||||
refine: {
|
||||
rechargePlus: [30, 35, 40, 45, 50]
|
||||
}
|
||||
}, {
|
||||
title: "攻击力基于元素充能提升[atkPct]%",
|
||||
sort: 10,
|
||||
data: {
|
||||
atkPct: ({ attr, refine }) => {
|
||||
let recharge = attr.recharge.base + attr.recharge.plus - 100
|
||||
return Math.min(recharge * [28, 35, 42, 49, 56][refine] / 100, [80, 90, 100, 110, 120][refine])
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
export const weapons = { ...polearm };
|
Loading…
Reference in New Issue
Block a user