2022-07-30 20:20:10 +00:00
|
|
|
|
import fs from 'fs'
|
|
|
|
|
import lodash from 'lodash'
|
|
|
|
|
import Format from './Format.js'
|
|
|
|
|
import { Character } from './models.js'
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
import { eleBaseDmg, eleMap, attrMap } from './calc/calc-meta.js'
|
|
|
|
|
import { Mastery } from './calc/mastery.js'
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
2022-04-23 21:16:37 +00:00
|
|
|
|
let Calc = {
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
async getCharCalcRule (name) {
|
|
|
|
|
const _path = process.cwd()
|
|
|
|
|
const cfgPath = `${_path}/plugins/miao-plugin/resources/meta/character/${name}/calc.js`
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let details; let buffs = []; let defParams = {}; let defDmgIdx = -1; let mainAttr = 'atk,cpct,cdmg'; let enemyName = '小宝'
|
2022-04-23 21:16:37 +00:00
|
|
|
|
if (fs.existsSync(cfgPath)) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let fileData = await import(`file://${cfgPath}`)
|
|
|
|
|
details = fileData.details || false
|
|
|
|
|
buffs = fileData.buffs || []
|
|
|
|
|
defParams = fileData.defParams || {}
|
2022-04-30 21:06:17 +00:00
|
|
|
|
if (fileData.defDmgIdx) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
defDmgIdx = fileData.defDmgIdx
|
2022-04-30 21:06:17 +00:00
|
|
|
|
}
|
|
|
|
|
if (fileData.mainAttr) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
mainAttr = fileData.mainAttr
|
2022-04-30 21:06:17 +00:00
|
|
|
|
}
|
2022-05-19 02:34:21 +00:00
|
|
|
|
if (fileData.enemyName) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
enemyName = fileData.enemyName
|
2022-05-19 02:34:21 +00:00
|
|
|
|
}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (details) {
|
2022-05-19 02:34:21 +00:00
|
|
|
|
return { details, buffs, defParams, defDmgIdx, mainAttr, enemyName }
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return false
|
2022-04-23 21:16:37 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 获取基础属性
|
2022-07-30 20:20:10 +00:00
|
|
|
|
attr (profile) {
|
|
|
|
|
let ret = {}
|
|
|
|
|
let { attr } = profile
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
ret.dataSource = profile.dataSource || 'miao'
|
2022-06-02 10:25:09 +00:00
|
|
|
|
|
2022-04-23 21:16:37 +00:00
|
|
|
|
// 基础属性
|
2022-07-30 20:20:10 +00:00
|
|
|
|
lodash.forEach('atk,def,hp'.split(','), (key) => {
|
2022-04-23 21:16:37 +00:00
|
|
|
|
ret[key] = {
|
|
|
|
|
base: attr[`${key}Base`] * 1 || 0,
|
|
|
|
|
plus: attr[key] * 1 - attr[`${key}Base`] * 1 || 0,
|
|
|
|
|
pct: 0
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
lodash.forEach('mastery,recharge'.split(','), (key) => {
|
2022-04-23 21:16:37 +00:00
|
|
|
|
ret[key] = {
|
|
|
|
|
base: attr[key] * 1 || 0,
|
|
|
|
|
plus: 0,
|
|
|
|
|
pct: 0
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
lodash.forEach({ cRate: 'cpct', cDmg: 'cdmg', hInc: 'heal' }, (val, key) => {
|
2022-04-23 21:16:37 +00:00
|
|
|
|
ret[val] = {
|
|
|
|
|
base: attr[key] * 1 || 0,
|
|
|
|
|
plus: 0,
|
2022-05-02 08:32:31 +00:00
|
|
|
|
pct: 0,
|
2022-05-20 21:26:53 +00:00
|
|
|
|
inc: 0
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
lodash.forEach('dmg,phy'.split(','), (key) => {
|
2022-04-23 21:16:37 +00:00
|
|
|
|
ret[key] = {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
base: attr[key + 'Bonus'] * 1 || 0,
|
2022-04-23 21:16:37 +00:00
|
|
|
|
plus: 0,
|
|
|
|
|
pct: 0
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2022-05-02 22:32:36 +00:00
|
|
|
|
// 技能属性记录
|
2022-07-30 20:20:10 +00:00
|
|
|
|
lodash.forEach('a,a2,a3,e,q'.split(','), (key) => {
|
2022-04-23 21:16:37 +00:00
|
|
|
|
ret[key] = {
|
|
|
|
|
pct: 0, // 倍率加成
|
2022-04-27 18:41:08 +00:00
|
|
|
|
multi: 0, // 独立倍率乘区加成
|
|
|
|
|
|
2022-04-23 21:16:37 +00:00
|
|
|
|
plus: 0, // 伤害值提高
|
|
|
|
|
dmg: 0, // 伤害提高
|
2022-07-30 20:20:10 +00:00
|
|
|
|
cpct: 0, // 暴击提高
|
|
|
|
|
cdmg: 0, // 爆伤提高
|
2022-04-27 18:41:08 +00:00
|
|
|
|
|
|
|
|
|
def: 0, // 防御降低
|
2022-07-30 20:20:10 +00:00
|
|
|
|
ignore: 0 // 无视防御
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
ret.enemy = {
|
|
|
|
|
def: 0, // 降低防御
|
|
|
|
|
ignore: 0, // 无视防御
|
2022-07-30 20:20:10 +00:00
|
|
|
|
phy: 0 // 物理防御
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-02 22:32:36 +00:00
|
|
|
|
ret.shield = {
|
|
|
|
|
base: 100, // 基础
|
|
|
|
|
plus: 0, // 护盾强效
|
2022-07-30 20:20:10 +00:00
|
|
|
|
inc: 100 // 吸收倍率
|
2022-05-02 22:32:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let char = Character.get(profile)
|
|
|
|
|
ret.weapon = profile.weapon
|
|
|
|
|
ret.weaponType = char.weaponType
|
|
|
|
|
ret.element = eleMap[char.elem.toLowerCase()]
|
|
|
|
|
ret.refine = (profile.weapon.affix * 1 - 1) || 0
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
ret.multi = 0
|
2022-04-27 18:41:08 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
ret.zf = 0
|
|
|
|
|
ret.rh = 0
|
|
|
|
|
ret.gd = 0
|
|
|
|
|
ret.ks = 0
|
2022-04-24 18:50:17 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
ret.kx = 0
|
|
|
|
|
ret.fykx = 0
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return ret
|
2022-04-23 21:16:37 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 获取天赋数据
|
2022-07-30 20:20:10 +00:00
|
|
|
|
talent (profile, char) {
|
|
|
|
|
let ret = {}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let talentData = profile.talent || {}
|
2022-06-04 21:29:24 +00:00
|
|
|
|
|
2022-04-23 21:16:37 +00:00
|
|
|
|
lodash.forEach(['a', 'e', 'q'], (key) => {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let td = talentData[key] || {}
|
|
|
|
|
let lv = td.level_current * 1 || 1
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let map = {}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
|
|
|
|
lodash.forEach(char.talent[key].tables, (tr) => {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let val = tr.values[lv - 1]
|
|
|
|
|
val = val.replace(/[^\x00-\xff]/g, '').trim()
|
|
|
|
|
let valArr = []; let valArr2 = []
|
|
|
|
|
lodash.forEach(val.split('/'), (v, idx) => {
|
|
|
|
|
let valNum = 0
|
|
|
|
|
lodash.forEach(v.split('+'), (v) => {
|
|
|
|
|
v = v.split('*')
|
|
|
|
|
let v1 = v[0].replace('%', '').trim()
|
|
|
|
|
valNum += v1 * (v[1] || 1)
|
2022-05-01 21:58:48 +00:00
|
|
|
|
valArr2.push(v1)
|
2022-04-23 21:16:37 +00:00
|
|
|
|
})
|
2022-07-30 20:20:10 +00:00
|
|
|
|
valArr.push(valNum)
|
|
|
|
|
})
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
|
|
|
|
if (isNaN(valArr[0])) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
map[tr.name] = false
|
2022-04-23 21:16:37 +00:00
|
|
|
|
} else if (valArr.length === 1) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
map[tr.name] = valArr[0]
|
2022-04-23 21:16:37 +00:00
|
|
|
|
} else {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
map[tr.name] = valArr
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
2022-07-30 20:20:10 +00:00
|
|
|
|
map[tr.name + '2'] = valArr2
|
2022-04-23 21:16:37 +00:00
|
|
|
|
})
|
2022-07-30 20:20:10 +00:00
|
|
|
|
ret[key] = map
|
2022-04-23 21:16:37 +00:00
|
|
|
|
})
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return ret
|
2022-04-23 21:16:37 +00:00
|
|
|
|
},
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
getDs (attr, meta, params) {
|
2022-04-25 19:59:13 +00:00
|
|
|
|
return {
|
|
|
|
|
...meta,
|
|
|
|
|
attr,
|
|
|
|
|
params,
|
|
|
|
|
refine: attr.refine,
|
|
|
|
|
weaponType: attr.weaponType,
|
2022-05-19 02:34:21 +00:00
|
|
|
|
weapon: attr.weapon,
|
2022-04-25 19:59:13 +00:00
|
|
|
|
element: eleMap[attr.element] || attr.element,
|
2022-07-30 20:20:10 +00:00
|
|
|
|
calc (ds) {
|
2022-04-25 19:59:13 +00:00
|
|
|
|
return (ds.base || 0) + (ds.plus || 0) + ((ds.base || 0) * (ds.pct || 0) / 100)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
calcAttr ({ originalAttr, buffs, meta, params = {}, incAttr = '', reduceAttr = '', talent = '' }) {
|
|
|
|
|
let attr = lodash.merge({}, originalAttr)
|
|
|
|
|
let msg = []
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-04-30 21:06:17 +00:00
|
|
|
|
if (incAttr && attrMap[incAttr]) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let aCfg = attrMap[incAttr]
|
|
|
|
|
attr[incAttr][aCfg.type] += aCfg.val
|
2022-04-30 21:06:17 +00:00
|
|
|
|
}
|
|
|
|
|
if (reduceAttr && attrMap[reduceAttr]) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let aCfg = attrMap[reduceAttr]
|
|
|
|
|
attr[reduceAttr][aCfg.type] -= aCfg.val
|
2022-04-30 21:06:17 +00:00
|
|
|
|
}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
|
|
|
|
lodash.forEach(buffs, (buff) => {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let ds = Calc.getDs(attr, meta, params)
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
ds.currentTalent = talent
|
2022-05-02 22:32:36 +00:00
|
|
|
|
|
2022-04-23 21:16:37 +00:00
|
|
|
|
// 如果存在rule,则进行计算
|
2022-04-24 18:50:17 +00:00
|
|
|
|
if (buff.check && !buff.check(ds)) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
2022-04-25 19:59:13 +00:00
|
|
|
|
if (buff.cons) {
|
|
|
|
|
if (ds.cons * 1 < buff.cons * 1) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return
|
2022-04-25 19:59:13 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let title = buff.title
|
2022-04-24 18:50:17 +00:00
|
|
|
|
|
|
|
|
|
if (buff.mastery) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let mastery = Math.max(0, attr.mastery.base + attr.mastery.plus)
|
2022-06-20 22:55:08 +00:00
|
|
|
|
// let masteryNum = 2.78 * mastery / (mastery + 1400) * 100;
|
2022-07-30 20:20:10 +00:00
|
|
|
|
buff.data = buff.data || {}
|
|
|
|
|
lodash.forEach(buff.mastery.split(','), (key) => {
|
|
|
|
|
buff.data[key] = Mastery.getMultiple(key, mastery)
|
2022-06-20 22:55:08 +00:00
|
|
|
|
// buff.data[key] = masteryNum;
|
2022-04-24 18:50:17 +00:00
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-23 21:16:37 +00:00
|
|
|
|
lodash.forEach(buff.data, (val, key) => {
|
|
|
|
|
if (lodash.isFunction(val)) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
val = val(ds)
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
title = title.replace(`[${key}]`, Format.comma(val, 1))
|
2022-04-23 21:16:37 +00:00
|
|
|
|
// 技能提高
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let tRet = /^(a|a2|a3|e|q)(Def|Ignore|Dmg|Plus|Pct|Cpct|Cdmg|Multi)$/.exec(key)
|
2022-04-23 21:16:37 +00:00
|
|
|
|
if (tRet) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
attr[tRet[1]][tRet[2].toLowerCase()] += val * 1 || 0
|
|
|
|
|
return
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let aRet = /^(hp|def|atk|mastery|cpct|cdmg|heal|recharge|dmg|phy|shield)(Plus|Pct|Inc)?$/.exec(key)
|
2022-04-23 21:16:37 +00:00
|
|
|
|
if (aRet) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
attr[aRet[1]][aRet[2] ? aRet[2].toLowerCase() : 'plus'] += val * 1 || 0
|
|
|
|
|
return
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
2022-07-30 20:20:10 +00:00
|
|
|
|
if (key === 'enemyDef') {
|
|
|
|
|
attr.enemy.def += val * 1 || 0
|
|
|
|
|
return
|
2022-04-24 18:50:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
if (['zf', 'rh', 'kx', 'gd', 'ks', 'fykx'].includes(key)) {
|
|
|
|
|
attr[key] += val * 1 || 0
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
2022-07-30 20:20:10 +00:00
|
|
|
|
})
|
|
|
|
|
msg.push(title)
|
2022-04-23 21:16:37 +00:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
attr, msg
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
async weapon (weaponName) {
|
|
|
|
|
const _path = process.cwd()
|
|
|
|
|
const cfgPath = `${_path}/plugins/miao-plugin/resources/meta/weapons/calc.js`
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let weapons = {}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
if (fs.existsSync(cfgPath)) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let fileData = await import(`file://${cfgPath}`)
|
|
|
|
|
weapons = fileData.weapons || {}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let weaponCfg = weapons[weaponName] || []
|
2022-04-23 21:16:37 +00:00
|
|
|
|
if (lodash.isPlainObject(weaponCfg)) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
weaponCfg = [weaponCfg]
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lodash.forEach(weaponCfg, (ds) => {
|
2022-04-30 21:16:05 +00:00
|
|
|
|
if (!/:/.test(ds.title)) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
ds.title = `${weaponName}:${ds.title}`
|
2022-04-30 21:16:05 +00:00
|
|
|
|
}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
if (ds.refine) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
ds.data = ds.data || {}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
lodash.forEach(ds.refine, (r, key) => {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
ds.data[key] = ({ refine }) => r[refine] * (ds.buffCount || 1)
|
2022-04-23 21:16:37 +00:00
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return weaponCfg
|
2022-04-23 21:16:37 +00:00
|
|
|
|
},
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
async reliquaries (sets) {
|
|
|
|
|
const _path = process.cwd()
|
|
|
|
|
const cfgPath = `${_path}/plugins/miao-plugin/resources/meta/reliquaries/calc.js`
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let buffs = {}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
if (fs.existsSync(cfgPath)) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let fileData = await import(`file://${cfgPath}`)
|
|
|
|
|
buffs = fileData.buffs || {}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let setMap = {}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
|
|
|
|
lodash.forEach(sets, (set) => {
|
|
|
|
|
if (set && set.set) {
|
2022-06-04 21:29:24 +00:00
|
|
|
|
let name = set.set
|
2022-04-23 21:16:37 +00:00
|
|
|
|
setMap[name] = (setMap[name] || 0) + 1
|
|
|
|
|
}
|
2022-07-30 20:20:10 +00:00
|
|
|
|
})
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let retBuffs = []
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
|
|
|
|
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])
|
|
|
|
|
}
|
|
|
|
|
})
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return retBuffs
|
2022-04-23 21:16:37 +00:00
|
|
|
|
},
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
getDmgFn ({ ds, attr, profile, enemyLv, showDetail = false }) {
|
|
|
|
|
let { calc } = ds
|
2022-05-01 21:58:48 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let dmgFn = function (pctNum = 0, talent = false, ele = false, basicNum = 0, mode = 'talent') {
|
|
|
|
|
let { atk, dmg, phy, cdmg, cpct } = attr
|
2022-04-30 21:06:17 +00:00
|
|
|
|
// 攻击区
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let atkNum = calc(atk)
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
|
|
|
|
// 倍率独立乘区
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let multiNum = attr.multi / 100
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
|
|
|
|
// 增伤区
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let dmgNum = (1 + dmg.base / 100 + dmg.plus / 100)
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
if (ele === 'phy') {
|
|
|
|
|
dmgNum = (1 + phy.base / 100 + phy.plus / 100)
|
2022-05-19 02:34:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
// console.log({ base: Format.comma(dmg.base, 2), plus: Format.comma(dmg.plus, 2) })
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let cpctNum = cpct.base / 100 + cpct.plus / 100
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
|
|
|
|
// 爆伤区
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let cdmgNum = cdmg.base / 100 + cdmg.plus / 100
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let enemyDef = attr.enemy.def / 100
|
|
|
|
|
let enemyIgnore = attr.enemy.ignore / 100
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let plusNum = 0
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
|
|
|
|
if (talent && attr[talent]) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
pctNum = pctNum / 100
|
2022-06-20 22:55:08 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let ds = attr[talent]
|
2022-06-20 22:55:08 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
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
|
2022-04-30 21:06:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 防御区
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let lv = profile.lv
|
|
|
|
|
let defNum = (lv + 100) / ((lv + 100) + (enemyLv + 100) * (1 - enemyDef) * (1 - enemyIgnore))
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
|
|
|
|
// 抗性区
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let kx = attr.kx
|
|
|
|
|
if (talent === 'fy') {
|
|
|
|
|
kx = attr.fykx
|
2022-06-20 22:55:08 +00:00
|
|
|
|
}
|
2022-07-30 20:20:10 +00:00
|
|
|
|
kx = 10 - (kx || 0)
|
|
|
|
|
let kNum = 0.9
|
2022-04-30 21:06:17 +00:00
|
|
|
|
if (kx >= 0) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
kNum = (100 - kx) / 100
|
2022-04-30 21:06:17 +00:00
|
|
|
|
} else {
|
|
|
|
|
kNum = 1 - kx / 200
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 反应区
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let eleNum = 1; let eleBase = 0
|
2022-06-20 22:55:08 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
if (ele === 'ks' || ele === 'gd') {
|
|
|
|
|
eleBase = eleBaseDmg[lv] || 0
|
2022-06-20 22:55:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
if (ele === 'phy') {
|
|
|
|
|
// do nothing
|
2022-05-19 02:34:21 +00:00
|
|
|
|
} else if (ele) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
eleNum = Mastery.getBasePct(ele, attr.element)
|
2022-05-02 08:32:31 +00:00
|
|
|
|
|
2022-04-30 21:06:17 +00:00
|
|
|
|
if (attr[ele]) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
eleNum = eleNum * (1 + attr[ele] / 100)
|
2022-04-30 21:06:17 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
cpctNum = Math.max(0, Math.min(1, cpctNum))
|
2022-04-30 21:06:17 +00:00
|
|
|
|
if (cpctNum === 0) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
cdmgNum = 0
|
2022-04-30 21:06:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let ret = {}
|
|
|
|
|
if (mode === 'basic') {
|
2022-05-01 21:58:48 +00:00
|
|
|
|
ret = {
|
2022-05-05 22:56:04 +00:00
|
|
|
|
dmg: basicNum * dmgNum * (1 + cdmgNum) * defNum * kNum * eleNum,
|
|
|
|
|
avg: basicNum * dmgNum * (1 + cpctNum * cdmgNum) * defNum * kNum * eleNum
|
2022-05-01 21:58:48 +00:00
|
|
|
|
}
|
2022-06-20 22:55:08 +00:00
|
|
|
|
} else if (eleBase) {
|
|
|
|
|
ret = {
|
|
|
|
|
avg: eleBase * kNum * eleNum
|
|
|
|
|
}
|
2022-05-01 21:58:48 +00:00
|
|
|
|
} else {
|
|
|
|
|
// 计算最终伤害
|
|
|
|
|
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
|
|
|
|
|
}
|
2022-04-30 21:06:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-05-02 22:32:36 +00:00
|
|
|
|
if (showDetail) {
|
|
|
|
|
console.log(attr, { atkNum, pctNum, multiNum, plusNum, dmgNum, cpctNum, cdmgNum, defNum, eleNum, kNum }, ret)
|
|
|
|
|
}
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return ret
|
|
|
|
|
}
|
2022-05-02 22:32:36 +00:00
|
|
|
|
|
2022-05-05 22:56:04 +00:00
|
|
|
|
dmgFn.basic = function (basicNum = 0, talent = false, ele = false) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return dmgFn(0, talent, ele, basicNum, 'basic')
|
2022-05-02 22:32:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dmgFn.heal = function (num) {
|
2022-05-19 02:34:21 +00:00
|
|
|
|
if (showDetail) {
|
2022-05-13 19:31:49 +00:00
|
|
|
|
console.log(num, calc(attr.heal), attr.heal.inc)
|
|
|
|
|
}
|
2022-05-02 22:32:36 +00:00
|
|
|
|
return {
|
2022-05-20 21:26:53 +00:00
|
|
|
|
avg: num * (1 + calc(attr.heal) / 100 + attr.heal.inc / 100)
|
2022-05-02 22:32:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dmgFn.shield = function (num) {
|
|
|
|
|
return {
|
|
|
|
|
avg: num * (calc(attr.shield) / 100) * (attr.shield.inc / 100)
|
2022-07-30 20:20:10 +00:00
|
|
|
|
}
|
2022-05-02 22:32:36 +00:00
|
|
|
|
}
|
2022-06-20 22:55:08 +00:00
|
|
|
|
dmgFn.ks = function () {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return dmgFn(0, 'fy', 'ks')
|
2022-06-20 22:55:08 +00:00
|
|
|
|
}
|
2022-05-02 22:32:36 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return dmgFn
|
2022-04-30 21:06:17 +00:00
|
|
|
|
},
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
async calcData ({ profile, char, enemyLv = 91, mode = 'profile', dmgIdx = 0 }) {
|
|
|
|
|
let charCalcData = await Calc.getCharCalcRule(char.name)
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
|
|
|
|
if (!charCalcData) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return false
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let talent = Calc.talent(profile, char)
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
|
|
|
|
let meta = {
|
2022-06-04 21:29:24 +00:00
|
|
|
|
cons: profile.cons * 1,
|
2022-04-23 21:52:28 +00:00
|
|
|
|
talent
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let { buffs, details, defParams, mainAttr, defDmgIdx, enemyName } = charCalcData
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
defParams = defParams || {}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let originalAttr = Calc.attr(profile)
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let weaponBuffs = await Calc.weapon(profile.weapon.name)
|
|
|
|
|
let reliBuffs = await Calc.reliquaries(profile.artis)
|
|
|
|
|
buffs = lodash.concat(buffs, weaponBuffs, reliBuffs)
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
|
|
|
|
lodash.forEach(buffs, (buff) => {
|
|
|
|
|
buff.sort = lodash.isUndefined(buff.sort) ? 1 : buff.sort
|
2022-07-30 20:20:10 +00:00
|
|
|
|
})
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
buffs = lodash.sortBy(buffs, ['sort'])
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let { msg } = Calc.calcAttr({ originalAttr, buffs, meta, params: defParams || {} })
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let ret = []; let detailMap = []; let dmgRet = []; let dmgDetail = {}
|
2022-04-23 21:16:37 +00:00
|
|
|
|
|
2022-04-30 21:06:17 +00:00
|
|
|
|
lodash.forEach(details, (detail, detailSysIdx) => {
|
2022-05-19 02:34:21 +00:00
|
|
|
|
if (lodash.isFunction(detail)) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let { attr } = Calc.calcAttr({ originalAttr, buffs, meta })
|
|
|
|
|
let ds = lodash.merge({ talent }, Calc.getDs(attr, meta))
|
|
|
|
|
detail = detail({ ...ds, attr, profile })
|
2022-05-19 02:34:21 +00:00
|
|
|
|
}
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let params = lodash.merge({}, defParams, detail.params || {})
|
|
|
|
|
let { attr } = Calc.calcAttr({ originalAttr, buffs, meta, params, talent: detail.talent || '' })
|
2022-04-25 19:59:13 +00:00
|
|
|
|
if (detail.check && !detail.check(Calc.getDs(attr, meta, params))) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return
|
2022-04-25 19:59:13 +00:00
|
|
|
|
}
|
2022-05-02 08:32:31 +00:00
|
|
|
|
if (detail.cons && meta.cons * 1 < detail.cons * 1) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
return
|
2022-05-02 08:32:31 +00:00
|
|
|
|
}
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let ds = lodash.merge({ talent }, Calc.getDs(attr, meta, params))
|
2022-05-01 21:58:48 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let dmg = Calc.getDmgFn({ ds, attr, profile, enemyLv, showDetail: detail.showDetail })
|
|
|
|
|
let basicDmgRet
|
2022-05-02 22:32:36 +00:00
|
|
|
|
|
|
|
|
|
if (detail.dmg) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
basicDmgRet = detail.dmg(ds, dmg)
|
|
|
|
|
detail.userIdx = detailMap.length
|
|
|
|
|
detailMap.push(detail)
|
2022-04-23 21:16:37 +00:00
|
|
|
|
ret.push({
|
|
|
|
|
title: detail.title,
|
2022-04-30 21:06:17 +00:00
|
|
|
|
...basicDmgRet
|
2022-04-23 21:16:37 +00:00
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
if (mode === 'dmg') {
|
|
|
|
|
let detail
|
2022-04-30 21:06:17 +00:00
|
|
|
|
if (dmgIdx && detailMap[dmgIdx - 1]) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
detail = detailMap[dmgIdx - 1]
|
2022-04-30 21:06:17 +00:00
|
|
|
|
} else if (!lodash.isUndefined(defDmgIdx) && details[defDmgIdx]) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
detail = details[defDmgIdx]
|
2022-04-30 21:06:17 +00:00
|
|
|
|
} else {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
detail = detailMap[0]
|
2022-04-30 21:06:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dmgDetail = {
|
|
|
|
|
title: detail.title,
|
|
|
|
|
userIdx: detail.userIdx,
|
|
|
|
|
basicRet: lodash.merge({}, ret[detail.userIdx]),
|
|
|
|
|
attr: []
|
2022-07-30 20:20:10 +00:00
|
|
|
|
}
|
2022-04-30 21:06:17 +00:00
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
mainAttr = mainAttr.split(',')
|
|
|
|
|
let params = lodash.merge({}, defParams, detail.params || {})
|
|
|
|
|
let basicDmg = dmgDetail.basicRet
|
2022-04-30 21:06:17 +00:00
|
|
|
|
lodash.forEach(mainAttr, (reduceAttr) => {
|
|
|
|
|
dmgDetail.attr.push(attrMap[reduceAttr])
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let rowData = []
|
2022-04-30 21:06:17 +00:00
|
|
|
|
lodash.forEach(mainAttr, (incAttr) => {
|
|
|
|
|
if (incAttr === reduceAttr) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
rowData.push({ type: 'na' })
|
|
|
|
|
return
|
2022-04-30 21:06:17 +00:00
|
|
|
|
}
|
2022-05-02 22:32:36 +00:00
|
|
|
|
let { attr } = Calc.calcAttr({
|
|
|
|
|
originalAttr,
|
|
|
|
|
buffs,
|
|
|
|
|
meta,
|
|
|
|
|
params,
|
|
|
|
|
incAttr,
|
|
|
|
|
reduceAttr,
|
2022-07-30 20:20:10 +00:00
|
|
|
|
talent: detail.talent || ''
|
|
|
|
|
})
|
|
|
|
|
let ds = lodash.merge({ talent }, Calc.getDs(attr, meta, params))
|
|
|
|
|
let dmg = Calc.getDmgFn({ ds, attr, profile, enemyLv })
|
2022-05-02 22:32:36 +00:00
|
|
|
|
if (detail.dmg) {
|
2022-07-30 20:20:10 +00:00
|
|
|
|
let dmgCalcRet = detail.dmg(ds, dmg)
|
2022-04-30 21:06:17 +00:00
|
|
|
|
rowData.push({
|
2022-07-30 20:20:10 +00:00
|
|
|
|
type: dmgCalcRet.avg === basicDmg.avg ? 'avg' : (dmgCalcRet.avg > basicDmg.avg ? 'gt' : 'lt'),
|
2022-04-30 21:06:17 +00:00
|
|
|
|
...dmgCalcRet
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
2022-07-30 20:20:10 +00:00
|
|
|
|
dmgRet.push(rowData)
|
2022-04-30 21:06:17 +00:00
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-23 21:16:37 +00:00
|
|
|
|
return {
|
|
|
|
|
ret,
|
2022-04-30 21:06:17 +00:00
|
|
|
|
msg,
|
|
|
|
|
dmgRet,
|
2022-05-19 02:34:21 +00:00
|
|
|
|
enemyName,
|
2022-04-30 21:06:17 +00:00
|
|
|
|
dmgCfg: dmgDetail
|
2022-04-23 21:16:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-30 20:20:10 +00:00
|
|
|
|
export default Calc
|