miao-plugin/models/ProfileDmg.js

276 lines
8.3 KiB
JavaScript
Raw Normal View History

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'
2023-05-21 18:13:38 +00:00
import { attrMap as attrMapGS } from '../resources/meta/artifact/index.js'
import { attrMap as attrMapSR } from '../resources/meta-sr/artifact/index.js'
import DmgBuffs from './profile/DmgBuffs.js'
import DmgAttr from './profile/DmgAttr.js'
import DmgCalc from './profile/DmgCalc.js'
2023-06-11 20:08:36 +00:00
import { Common, MiaoError } from '#miao'
2022-08-18 10:13:42 +00:00
export default class ProfileDmg extends Base {
2023-05-21 18:13:38 +00:00
constructor (profile = {}, game = 'gs') {
2022-08-18 10:13:42 +00:00
super()
this.profile = profile
2023-05-21 18:13:38 +00:00
this.game = game
2022-08-18 10:13:42 +00:00
if (profile && profile.id) {
let { id } = profile
this.char = Character.get(id)
}
2022-08-22 20:53:31 +00:00
}
2023-05-21 18:13:38 +00:00
static dmgRulePath (name, game = 'gs') {
const _path = process.cwd()
2023-05-21 18:13:38 +00:00
const meta = game === 'sr' ? 'meta-sr' : 'meta'
let path = `${_path}/plugins/miao-plugin/resources/${meta}/character/${name}/calc_user.js`
if (fs.existsSync(path)) {
return path
}
2023-05-21 18:13:38 +00:00
path = `${_path}/plugins/miao-plugin/resources/${meta}/character/${name}/calc_auto.js`
2023-02-21 19:49:49 +00:00
if (fs.existsSync(path) && Common.cfg('teamCalc')) {
return path
}
2023-05-21 18:13:38 +00:00
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 || {}
2022-11-20 20:45:27 +00:00
let detail = char.detail
2023-05-21 18:13:38 +00:00
let { isSr, isGs } = this
lodash.forEach((isSr ? 'a,a2,e,e2,q,t' : 'a,e,q').split(','), (key) => {
let level = lodash.isNumber(talentData[key]) ? talentData[key] : (talentData[key]?.level || 1)
if (key === 'a2' || key === 'e2') {
let tmpKey = key === 'a2' ? 'a' : 'e'
level = lodash.isNumber(talentData[tmpKey]) ? talentData[tmpKey] : (talentData[tmpKey]?.level || 1)
}
2022-08-22 20:53:31 +00:00
let map = {}
2023-05-21 18:13:38 +00:00
if (isGs && detail.talentData) {
lodash.forEach(detail.talentData[key], (ds, key) => {
2022-11-20 20:45:27 +00:00
map[key] = ds[level - 1]
2022-08-22 20:53:31 +00:00
})
} else if (isSr && detail.talent && detail.talent[key]) {
2023-05-21 18:13:38 +00:00
lodash.forEach(detail.talent[key].tables, (ds) => {
map[ds.name] = ds.values[level - 1]
2022-11-20 20:45:27 +00:00
})
}
2022-08-22 20:53:31 +00:00
ret[key] = map
})
return ret
}
2023-05-21 18:13:38 +00:00
trees () {
let ret = {}
let reg = /\d{4}(\d{3})/
lodash.forEach(this.profile.trees, (t) => {
let regRet = reg.exec(t)
if (regRet && regRet[1]) {
ret[regRet[1]] = true
}
})
return ret
}
2022-08-22 20:53:31 +00:00
// 获取buff列表
getBuffs (buffs) {
2023-05-21 18:13:38 +00:00
return DmgBuffs.getBuffs(this.profile, buffs, this.game)
2022-08-22 20:53:31 +00:00
}
async getCalcRule () {
2023-05-21 18:13:38 +00:00
const cfgPath = ProfileDmg.dmgRulePath(this.char?.name, this.char?.game)
2022-08-22 20:53:31 +00:00
let cfg = {}
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
defDmgKey: cfg.defDmgKey || '',
2022-08-22 20:53:31 +00:00
mainAttr: cfg.mainAttr || 'atk,cpct,cdmg', // 伤害属性
2023-05-21 18:13:38 +00:00
enemyName: cfg.enemyName || this.isGs ? '小宝' : '弱点敌人' // 敌人名称
2022-08-22 20:53:31 +00:00
}
}
return false
2022-08-18 10:13:42 +00:00
}
async calcData ({ enemyLv = 91, mode = 'profile', dmgIdx = 0, idxIsInput = false }) {
2022-08-18 10:13:42 +00:00
if (!this.char || !this.profile) {
return false
}
2022-08-22 20:53:31 +00:00
let { profile } = this
2023-05-21 18:13:38 +00:00
let { game } = this.char
2023-05-23 19:30:30 +00:00
let sp = this.detail?.sp
2022-08-22 20:53:31 +00:00
let charCalcData = await this.getCalcRule()
2022-08-18 10:13:42 +00:00
if (!charCalcData) {
return false
}
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 = {
level: profile.level,
2022-08-18 10:13:42 +00:00
cons: profile.cons * 1,
2023-05-21 18:13:38 +00:00
talent,
trees: this.trees()
2022-08-18 10:13:42 +00:00
}
2023-05-21 18:13:38 +00:00
2022-08-22 20:53:31 +00:00
let { id, weapon, attr } = profile
2022-08-18 10:13:42 +00:00
defParams = defParams || {}
2023-05-23 19:30:30 +00:00
let originalAttr = DmgAttr.getAttr({ id, weapon, attr, char: this.char, game, sp })
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 || {} })
let msgList = []
2022-08-18 10:13:42 +00:00
let ret = []
let detailMap = []
let dmgRet = []
let dmgDetail = {}
// 用户手动输入伤害序号
if (idxIsInput) {
// 从1开始所以需要 - 1
dmgIdx = --dmgIdx < 0 ? 0 : dmgIdx
}
if (mode === 'single') {
dmgIdx = defDmgIdx > -1 ? defDmgIdx : 0
}
2022-08-18 10:13:42 +00:00
lodash.forEach(details, (detail, detailSysIdx) => {
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 || {})
let { attr, msg } = DmgAttr.calcAttr({ originalAttr, buffs, meta, params, talent: detail.talent || '' })
if (detail.isStatic) {
return
}
2022-08-22 20:53:31 +00:00
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
2023-05-21 18:13:38 +00:00
let dmg = DmgCalc.getDmgFn({ ds, attr, level: profile.level, enemyLv, showDetail: detail.showDetail, game })
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
})
}
msgList.push(msg)
2022-08-18 10:13:42 +00:00
})
if (mode === 'dmg') {
let detail
if (idxIsInput && detailMap[dmgIdx]) {
detail = detailMap[dmgIdx]
} else if (idxIsInput) {
// 当用户输入的下标错误时,提示错误
throw new MiaoError(`序号输入错误:${this.char.name}最多只支持${detailMap.length}种伤害计算哦`)
2022-08-18 10:13:42 +00:00
} else if (!lodash.isUndefined(defDmgIdx) && details[defDmgIdx]) {
detail = details[defDmgIdx]
} else {
detail = detailMap[0]
}
if (lodash.isFunction(detail)) {
let { attr } = DmgAttr.calcAttr({ originalAttr, buffs, meta })
let ds = lodash.merge({ talent }, DmgAttr.getDs(attr, meta))
detail = detail({ ...ds, attr, profile })
}
2022-08-18 10:13:42 +00:00
dmgDetail = {
title: detail.title,
userIdx: detail.userIdx || defDmgIdx,
basicRet: lodash.merge({}, ret[detail.userIdx] || ret[defDmgIdx]),
2022-08-18 10:13:42 +00:00
attr: []
}
2023-05-21 18:13:38 +00:00
let attrMap = game === 'gs' ? attrMapGS : attrMapSR
2022-11-24 15:27:03 +00:00
// 计算角色属性增减
2022-08-18 10:13:42 +00:00
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,
2023-05-21 18:13:38 +00:00
talent: detail.talent || '',
game
2022-08-18 10:13:42 +00:00
})
2022-08-22 20:53:31 +00:00
let ds = lodash.merge({ talent }, DmgAttr.getDs(attr, meta, params))
2023-05-21 18:13:38 +00:00
let dmg = DmgCalc.getDmgFn({ ds, attr, level: profile.level, enemyLv, game })
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)
})
}
if (mode === 'single') {
return ret[0]
}
2022-08-18 10:13:42 +00:00
return {
ret,
// 根据当前计算的伤害显示对应的buff列表
msg: msgList[idxIsInput ? dmgIdx : (defDmgIdx > -1 ? defDmgIdx : dmgIdx)] || msg,
msgList,
2022-08-18 10:13:42 +00:00
dmgRet,
enemyName,
2023-02-21 19:49:49 +00:00
dmgCfg: dmgDetail,
enemyLv
2022-08-18 10:13:42 +00:00
}
}
}