2022-08-22 20:53:31 +00:00
|
|
|
import fs from 'fs'
|
|
|
|
import lodash from 'lodash'
|
2022-08-18 10:13:42 +00:00
|
|
|
import Base from './Base.js'
|
|
|
|
import { Character } from './index.js'
|
2022-10-06 22:20:46 +00:00
|
|
|
import { attrMap } from './profile-lib/DmgCalcMeta.js'
|
2022-08-22 20:53:31 +00:00
|
|
|
import DmgBuffs from './profile-lib/DmgBuffs.js'
|
|
|
|
import DmgAttr from './profile-lib/DmgAttr.js'
|
|
|
|
import DmgCalc from './profile-lib/DmgCalc.js'
|
2022-08-18 10:13:42 +00:00
|
|
|
|
|
|
|
export default class ProfileDmg extends Base {
|
2022-08-22 20:53:31 +00:00
|
|
|
constructor (profile = {}) {
|
2022-08-18 10:13:42 +00:00
|
|
|
super()
|
|
|
|
this.profile = profile
|
|
|
|
if (profile && profile.id) {
|
|
|
|
let { id } = profile
|
|
|
|
this.char = Character.get(id)
|
|
|
|
}
|
2022-08-22 20:53:31 +00:00
|
|
|
}
|
|
|
|
|
2022-11-08 22:04:08 +00:00
|
|
|
static dmgRulePath (name) {
|
|
|
|
const _path = process.cwd()
|
|
|
|
let path = `${_path}/plugins/miao-plugin/resources/meta/character/${name}/calc.js`
|
|
|
|
if (fs.existsSync(path)) {
|
|
|
|
return path
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2022-08-22 20:53:31 +00:00
|
|
|
// 获取天赋数据
|
|
|
|
talent () {
|
|
|
|
let char = this.char
|
|
|
|
let profile = this.profile
|
|
|
|
let ret = {}
|
|
|
|
let talentData = profile.talent || {}
|
|
|
|
lodash.forEach(['a', 'e', 'q'], (key) => {
|
|
|
|
let level = lodash.isNumber(talentData[key]) ? talentData[key] : (talentData[key].level || 1)
|
|
|
|
let map = {}
|
2022-09-03 21:08:57 +00:00
|
|
|
lodash.forEach(char.detail.talent[key].tables, (tr) => {
|
2022-08-22 20:53:31 +00:00
|
|
|
let val = tr.values[level - 1]
|
|
|
|
// eslint-disable-next-line no-control-regex
|
|
|
|
val = val.replace(/[^\x00-\xff]/g, '').trim()
|
2022-09-04 21:03:23 +00:00
|
|
|
val = val.replace(/[a-zA-Z]/g, '').trim()
|
2022-08-22 20:53:31 +00:00
|
|
|
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-09-26 19:47:52 +00:00
|
|
|
valArr2.push(v1 * 1)
|
2022-08-22 20:53:31 +00:00
|
|
|
})
|
|
|
|
valArr.push(valNum)
|
|
|
|
})
|
|
|
|
|
2022-11-03 19:29:57 +00:00
|
|
|
let name = tr.name2 || tr.name
|
2022-08-22 20:53:31 +00:00
|
|
|
if (isNaN(valArr[0])) {
|
2022-11-03 19:29:57 +00:00
|
|
|
map[name] = false
|
2022-08-22 20:53:31 +00:00
|
|
|
} else if (valArr.length === 1) {
|
2022-11-03 19:29:57 +00:00
|
|
|
map[name] = valArr[0]
|
2022-08-22 20:53:31 +00:00
|
|
|
} else {
|
2022-11-03 19:29:57 +00:00
|
|
|
map[name] = valArr
|
2022-08-22 20:53:31 +00:00
|
|
|
}
|
2022-11-03 19:29:57 +00:00
|
|
|
map[name + '2'] = valArr2
|
2022-08-22 20:53:31 +00:00
|
|
|
})
|
|
|
|
ret[key] = map
|
|
|
|
})
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取buff列表
|
|
|
|
getBuffs (buffs) {
|
|
|
|
return DmgBuffs.getBuffs(this.profile, buffs)
|
|
|
|
}
|
|
|
|
|
|
|
|
async getCalcRule () {
|
2022-11-08 22:04:08 +00:00
|
|
|
const cfgPath = ProfileDmg.dmgRulePath(this.char?.name)
|
2022-08-22 20:53:31 +00:00
|
|
|
let cfg = {}
|
2022-11-08 22:04:08 +00:00
|
|
|
if (cfgPath) {
|
2022-08-22 20:53:31 +00:00
|
|
|
cfg = await import(`file://${cfgPath}`)
|
|
|
|
return {
|
|
|
|
details: cfg.details || false, // 计算详情
|
|
|
|
buffs: cfg.buffs || [], // 角色buff
|
|
|
|
defParams: cfg.defParams || {}, // 默认参数,一般为空
|
|
|
|
defDmgIdx: cfg.defDmgIdx || -1, // 默认详情index
|
2022-11-08 22:04:08 +00:00
|
|
|
defDmgKey: cfg.defDmgKey || '',
|
2022-08-22 20:53:31 +00:00
|
|
|
mainAttr: cfg.mainAttr || 'atk,cpct,cdmg', // 伤害属性
|
|
|
|
enemyName: cfg.enemyName || '小宝' // 敌人名称
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
2022-08-18 10:13:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async calcData ({ enemyLv = 91, mode = 'profile', dmgIdx = 0 }) {
|
|
|
|
if (!this.char || !this.profile) {
|
|
|
|
return false
|
|
|
|
}
|
2022-08-22 20:53:31 +00:00
|
|
|
let { profile } = this
|
|
|
|
let charCalcData = await this.getCalcRule()
|
2022-08-18 10:13:42 +00:00
|
|
|
|
|
|
|
if (!charCalcData) {
|
|
|
|
return false
|
|
|
|
}
|
2022-11-08 22:04:08 +00:00
|
|
|
let { buffs, details, defParams, mainAttr, defDmgIdx, defDmgKey, enemyName } = charCalcData
|
2022-08-22 20:53:31 +00:00
|
|
|
|
|
|
|
let talent = this.talent()
|
2022-08-18 10:13:42 +00:00
|
|
|
|
|
|
|
let meta = {
|
|
|
|
cons: profile.cons * 1,
|
|
|
|
talent
|
|
|
|
}
|
2022-08-22 20:53:31 +00:00
|
|
|
let { id, weapon, attr } = profile
|
2022-08-18 10:13:42 +00:00
|
|
|
|
|
|
|
defParams = defParams || {}
|
|
|
|
|
2022-08-22 20:53:31 +00:00
|
|
|
let originalAttr = DmgAttr.getAttr({ id, weapon, attr, char: this.char })
|
2022-08-18 10:13:42 +00:00
|
|
|
|
2022-08-22 20:53:31 +00:00
|
|
|
buffs = this.getBuffs(buffs)
|
2022-08-18 10:13:42 +00:00
|
|
|
|
2022-08-22 20:53:31 +00:00
|
|
|
let { msg } = DmgAttr.calcAttr({ originalAttr, buffs, meta, params: defParams || {} })
|
2022-08-18 10:13:42 +00:00
|
|
|
|
|
|
|
let ret = []
|
|
|
|
let detailMap = []
|
|
|
|
let dmgRet = []
|
|
|
|
let dmgDetail = {}
|
|
|
|
|
2022-11-08 22:04:08 +00:00
|
|
|
if (mode === 'single') {
|
|
|
|
dmgIdx = defDmgIdx > -1 ? defDmgIdx : 0
|
|
|
|
}
|
|
|
|
|
2022-08-18 10:13:42 +00:00
|
|
|
lodash.forEach(details, (detail, detailSysIdx) => {
|
2022-11-08 22:04:08 +00:00
|
|
|
if (mode === 'single') {
|
|
|
|
if (defDmgKey) {
|
|
|
|
if (detail.dmgKey !== defDmgKey) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
} else if (detailSysIdx !== dmgIdx) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-18 10:13:42 +00:00
|
|
|
if (lodash.isFunction(detail)) {
|
2022-08-22 20:53:31 +00:00
|
|
|
let { attr } = DmgAttr.calcAttr({ originalAttr, buffs, meta })
|
|
|
|
let ds = lodash.merge({ talent }, DmgAttr.getDs(attr, meta))
|
2022-08-18 10:13:42 +00:00
|
|
|
detail = detail({ ...ds, attr, profile })
|
|
|
|
}
|
|
|
|
let params = lodash.merge({}, defParams, detail.params || {})
|
2022-08-22 20:53:31 +00:00
|
|
|
let { attr } = DmgAttr.calcAttr({ originalAttr, buffs, meta, params, talent: detail.talent || '' })
|
|
|
|
if (detail.check && !detail.check(DmgAttr.getDs(attr, meta, params))) {
|
2022-08-18 10:13:42 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
if (detail.cons && meta.cons < detail.cons * 1) {
|
|
|
|
return
|
|
|
|
}
|
2022-08-22 20:53:31 +00:00
|
|
|
let ds = lodash.merge({ talent }, DmgAttr.getDs(attr, meta, params))
|
2022-08-18 10:13:42 +00:00
|
|
|
|
2022-08-22 20:53:31 +00:00
|
|
|
let dmg = DmgCalc.getDmgFn({ ds, attr, level: profile.level, enemyLv, showDetail: detail.showDetail })
|
2022-08-18 10:13:42 +00:00
|
|
|
let basicDmgRet
|
|
|
|
|
|
|
|
if (detail.dmg) {
|
|
|
|
basicDmgRet = detail.dmg(ds, dmg)
|
|
|
|
detail.userIdx = detailMap.length
|
|
|
|
detailMap.push(detail)
|
|
|
|
ret.push({
|
|
|
|
title: detail.title,
|
|
|
|
...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
|
|
|
|
}
|
2022-08-22 20:53:31 +00:00
|
|
|
let { attr } = DmgAttr.calcAttr({
|
2022-08-18 10:13:42 +00:00
|
|
|
originalAttr,
|
|
|
|
buffs,
|
|
|
|
meta,
|
|
|
|
params,
|
|
|
|
incAttr,
|
|
|
|
reduceAttr,
|
|
|
|
talent: detail.talent || ''
|
|
|
|
})
|
2022-08-22 20:53:31 +00:00
|
|
|
let ds = lodash.merge({ talent }, DmgAttr.getDs(attr, meta, params))
|
|
|
|
let dmg = DmgCalc.getDmgFn({ ds, attr, level: profile.level, enemyLv })
|
2022-08-18 10:13:42 +00:00
|
|
|
if (detail.dmg) {
|
|
|
|
let dmgCalcRet = detail.dmg(ds, dmg)
|
|
|
|
rowData.push({
|
|
|
|
type: dmgCalcRet.avg === basicDmg.avg ? 'avg' : (dmgCalcRet.avg > basicDmg.avg ? 'gt' : 'lt'),
|
|
|
|
...dmgCalcRet
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
dmgRet.push(rowData)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-08 22:04:08 +00:00
|
|
|
if (mode === 'single') {
|
|
|
|
return ret[0]
|
|
|
|
}
|
|
|
|
|
2022-08-18 10:13:42 +00:00
|
|
|
return {
|
|
|
|
ret,
|
|
|
|
msg,
|
|
|
|
dmgRet,
|
|
|
|
enemyName,
|
|
|
|
dmgCfg: dmgDetail
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|