diff --git a/apps/admin.js b/apps/admin.js index d184124a..116f0196 100644 --- a/apps/admin.js +++ b/apps/admin.js @@ -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) { diff --git a/apps/character.js b/apps/character.js index 43b60958..122d376c 100644 --- a/apps/character.js +++ b/apps/character.js @@ -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, diff --git a/components/Calc.js b/components/Calc.js new file mode 100644 index 00000000..55717350 --- /dev/null +++ b/components/Calc.js @@ -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; \ No newline at end of file diff --git a/components/Profile.js b/components/Profile.js index d41c9c5a..f9ca5238 100644 --- a/components/Profile.js +++ b/components/Profile.js @@ -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; diff --git a/resources/character/detail.css b/resources/character/detail.css index 977770cb..426a0ac4 100644 --- a/resources/character/detail.css +++ b/resources/character/detail.css @@ -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; } \ No newline at end of file diff --git a/resources/character/detail.html b/resources/character/detail.html index a6da6932..13c7acce 100644 --- a/resources/character/detail.html +++ b/resources/character/detail.html @@ -48,6 +48,23 @@ {{/each}} + {{if dmgData.length > 0}} +
+
+
伤害类型
+
暴击伤害
+
平均伤害(计算暴击率)
+
+ {{each dmgData dmg idx}} +
+
{{dmg.title}}
+
{{dmg.dmg}}
+
{{dmg.avg}}
+
+ {{/each}} +
+
伤害计算功能完善中,结果可能不准确,计算数据仅供参考
+ {{/if}}
@@ -61,7 +78,7 @@
-
{{markScore}}圣遗物评级
+
{{markScore}}圣遗物评级
{{totalMark}}圣遗物总分
diff --git a/resources/common/common.css b/resources/common/common.css index 5535de15..ab33e645 100644 --- a/resources/common/common.css +++ b/resources/common/common.css @@ -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; } diff --git a/resources/common/font/HYWH-85W.ttf b/resources/common/font/HYWH-85W.ttf new file mode 100644 index 00000000..cc6adb12 Binary files /dev/null and b/resources/common/font/HYWH-85W.ttf differ diff --git a/resources/meta/character/雷电将军/calc.js b/resources/meta/character/雷电将军/calc.js new file mode 100644 index 00000000..4a670238 --- /dev/null +++ b/resources/meta/character/雷电将军/calc.js @@ -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 + } + }]; \ No newline at end of file diff --git a/resources/meta/reliquaries/calc.js b/resources/meta/reliquaries/calc.js new file mode 100644 index 00000000..26c8aa61 --- /dev/null +++ b/resources/meta/reliquaries/calc.js @@ -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 + } + } +} \ No newline at end of file diff --git a/resources/meta/weapons/calc.js b/resources/meta/weapons/calc.js new file mode 100644 index 00000000..c78ce534 --- /dev/null +++ b/resources/meta/weapons/calc.js @@ -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 }; \ No newline at end of file