2022-11-20 20:45:27 +00:00
|
|
|
/**
|
|
|
|
* 面板属性计算
|
|
|
|
* @type {{}}
|
|
|
|
*/
|
2023-10-19 07:46:08 +00:00
|
|
|
import Base from '../Base.js'
|
2023-10-21 18:54:45 +00:00
|
|
|
import { Format, Meta } from '#miao'
|
2023-10-18 17:01:11 +00:00
|
|
|
import { Weapon, ArtifactSet } from '#miao.models'
|
|
|
|
import AttrData from './AttrData.js'
|
2022-11-20 20:45:27 +00:00
|
|
|
import lodash from 'lodash'
|
|
|
|
|
2023-10-19 07:46:08 +00:00
|
|
|
class Attr extends Base {
|
2022-11-20 20:45:27 +00:00
|
|
|
constructor (profile) {
|
2023-10-19 07:46:08 +00:00
|
|
|
super()
|
2022-11-20 20:45:27 +00:00
|
|
|
this.profile = profile
|
2023-10-19 07:46:08 +00:00
|
|
|
this.game = profile.game
|
2023-10-18 19:53:48 +00:00
|
|
|
}
|
|
|
|
|
2022-11-21 21:26:06 +00:00
|
|
|
/**
|
|
|
|
* 静态调用入口
|
|
|
|
* @param profile
|
2023-10-18 17:01:11 +00:00
|
|
|
* @returns {Attr}
|
2022-11-21 21:26:06 +00:00
|
|
|
*/
|
2022-11-24 16:31:36 +00:00
|
|
|
static create (profile) {
|
2023-10-18 17:01:11 +00:00
|
|
|
return new Attr(profile)
|
2022-11-20 20:45:27 +00:00
|
|
|
}
|
|
|
|
|
2024-05-21 16:56:21 +00:00
|
|
|
static calcPromote (lv, game = 'gs') {
|
|
|
|
let lvs = game === 'gs' ? [1, 20, 40, 50, 60, 70, 80, 90] : [1, 20, 30, 40, 50, 60, 70, 80]
|
2023-02-13 08:31:23 +00:00
|
|
|
let promote = 0
|
2024-05-21 16:56:21 +00:00
|
|
|
for (let idx = 0; idx <= lvs.length - 1; idx++) {
|
2023-02-13 08:31:23 +00:00
|
|
|
if (lv >= lvs[idx] && lv <= lvs[idx + 1]) {
|
|
|
|
return promote
|
|
|
|
}
|
|
|
|
promote++
|
|
|
|
}
|
|
|
|
return promote
|
|
|
|
}
|
|
|
|
|
2022-11-21 21:26:06 +00:00
|
|
|
/**
|
2022-11-24 16:31:36 +00:00
|
|
|
* 面板属性计算
|
|
|
|
* @returns {{}}
|
2022-11-21 21:26:06 +00:00
|
|
|
*/
|
2022-11-24 16:31:36 +00:00
|
|
|
calc () {
|
2023-10-19 07:46:08 +00:00
|
|
|
let profile = this.profile
|
|
|
|
this.attr = AttrData.create(profile.char, {})
|
2023-05-16 19:15:00 +00:00
|
|
|
if (this.isGs) {
|
2023-05-16 05:04:43 +00:00
|
|
|
this.addAttr('recharge', 100, true)
|
|
|
|
this.addAttr('cpct', 5, true)
|
|
|
|
this.addAttr('cdmg', 50, true)
|
|
|
|
}
|
2022-11-24 16:31:36 +00:00
|
|
|
this.setCharAttr()
|
2022-11-20 20:45:27 +00:00
|
|
|
this.setWeaponAttr()
|
|
|
|
this.setArtisAttr()
|
2022-11-22 20:25:36 +00:00
|
|
|
return this.attr.getAttr()
|
2022-11-20 20:45:27 +00:00
|
|
|
}
|
|
|
|
|
2023-03-05 07:21:44 +00:00
|
|
|
getBase () {
|
|
|
|
return this.attr.getBase()
|
|
|
|
}
|
|
|
|
|
|
|
|
addAttr (key, val, isBase = false) {
|
|
|
|
this.attr.addAttr(key, val, isBase)
|
2022-11-21 21:26:06 +00:00
|
|
|
}
|
|
|
|
|
2023-10-19 07:46:08 +00:00
|
|
|
// 计算角色属性
|
|
|
|
setCharAttr () {
|
2023-05-19 18:50:39 +00:00
|
|
|
let { char, level, promote, trees } = this.profile
|
2022-11-20 20:45:27 +00:00
|
|
|
let metaAttr = char.detail?.attr || {}
|
2023-05-18 20:23:19 +00:00
|
|
|
let self = this
|
|
|
|
if (this.isSr) {
|
|
|
|
// 星铁面板属性
|
|
|
|
let attr = char.getLvAttr(level, promote)
|
|
|
|
lodash.forEach(attr, (v, k) => {
|
2023-10-14 09:20:20 +00:00
|
|
|
k = k + (['hp', 'atk', 'def', 'speed'].includes(k) ? 'Base' : '')
|
2023-05-18 20:23:19 +00:00
|
|
|
self.addAttr(k, v, true)
|
|
|
|
})
|
2023-05-19 18:50:39 +00:00
|
|
|
|
|
|
|
let tree = char.detail?.tree || {}
|
|
|
|
lodash.forEach(trees || [], (tid) => {
|
|
|
|
let tCfg = tree[tid]
|
|
|
|
if (tCfg) {
|
2023-05-20 13:51:44 +00:00
|
|
|
let key = tCfg.key
|
|
|
|
if (['atk', 'hp', 'def'].includes(key)) {
|
|
|
|
key = key + 'Pct'
|
|
|
|
}
|
|
|
|
self.addAttr(key, tCfg.value)
|
2023-05-19 18:50:39 +00:00
|
|
|
}
|
|
|
|
})
|
2023-05-18 20:23:19 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-11-21 21:26:06 +00:00
|
|
|
let { keys = {}, details = {} } = metaAttr
|
2022-11-20 20:45:27 +00:00
|
|
|
let lvLeft = 0
|
|
|
|
let lvRight = 0
|
2022-11-22 20:25:36 +00:00
|
|
|
let lvStep = [1, 20, 40, 50, 60, 70, 80, 90]
|
|
|
|
let currPromote = 0
|
2022-11-20 20:45:27 +00:00
|
|
|
for (let idx = 0; idx < lvStep.length - 1; idx++) {
|
2022-11-22 20:25:36 +00:00
|
|
|
if (currPromote === promote) {
|
|
|
|
if (level >= lvStep[idx] && level <= lvStep[idx + 1]) {
|
|
|
|
lvLeft = lvStep[idx]
|
|
|
|
lvRight = lvStep[idx + 1]
|
|
|
|
break
|
|
|
|
}
|
2022-11-20 20:45:27 +00:00
|
|
|
}
|
2022-11-22 20:25:36 +00:00
|
|
|
currPromote++
|
2022-11-20 20:45:27 +00:00
|
|
|
}
|
2022-11-21 21:26:06 +00:00
|
|
|
let detailLeft = details[lvLeft + '+'] || details[lvLeft] || {}
|
|
|
|
let detailRight = details[lvRight] || {}
|
2022-11-20 20:45:27 +00:00
|
|
|
|
2022-11-22 20:25:36 +00:00
|
|
|
let getLvData = (idx, step = false) => {
|
2022-11-20 20:45:27 +00:00
|
|
|
let valueLeft = detailLeft[idx]
|
|
|
|
let valueRight = detailRight[idx]
|
2022-11-22 20:25:36 +00:00
|
|
|
if (!step) {
|
|
|
|
return valueLeft * 1 + ((valueRight - valueLeft) * (level - lvLeft) / (lvRight - lvLeft))
|
|
|
|
} else {
|
|
|
|
return valueLeft * 1 + ((valueRight - valueLeft) * Math.floor((level - lvLeft) / 5) / Math.round(((lvRight - lvLeft) / 5)))
|
|
|
|
}
|
2022-11-20 20:45:27 +00:00
|
|
|
}
|
2023-03-05 07:21:44 +00:00
|
|
|
this.addAttr('hpBase', getLvData(0), true)
|
|
|
|
this.addAttr('atkBase', getLvData(1), true)
|
|
|
|
this.addAttr('defBase', getLvData(2), true)
|
2023-03-25 20:22:35 +00:00
|
|
|
this.addAttr(keys[3], getLvData(3, true), !/(hp|atk|def)/.test(keys[3]))
|
2022-11-22 20:25:36 +00:00
|
|
|
|
2022-11-24 16:31:36 +00:00
|
|
|
let charBuffs = char.getCalcRule()
|
2022-11-22 20:25:36 +00:00
|
|
|
lodash.forEach(charBuffs.buffs, (buff) => {
|
|
|
|
if (!buff.isStatic) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if (buff) {
|
|
|
|
lodash.forEach(buff.data, (val, key) => {
|
|
|
|
this.addAttr(key, val)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
2022-11-20 20:45:27 +00:00
|
|
|
}
|
|
|
|
|
2022-11-21 21:26:06 +00:00
|
|
|
/**
|
|
|
|
* 计算武器属性
|
|
|
|
*/
|
2022-11-20 20:45:27 +00:00
|
|
|
setWeaponAttr () {
|
2023-02-08 20:55:54 +00:00
|
|
|
let wData = this.profile?.weapon || {}
|
2023-05-28 18:49:36 +00:00
|
|
|
if (!wData || !wData.name) {
|
|
|
|
return false
|
|
|
|
}
|
2023-05-16 05:04:43 +00:00
|
|
|
let weapon = Weapon.get(wData?.name || wData?.id, this.game)
|
2023-05-28 18:49:36 +00:00
|
|
|
if (!weapon) {
|
|
|
|
return false
|
|
|
|
}
|
2023-02-21 19:49:49 +00:00
|
|
|
let wCalcRet = weapon.calcAttr(wData.level, wData.promote)
|
2023-05-18 20:23:19 +00:00
|
|
|
let self = this
|
2023-10-19 07:46:08 +00:00
|
|
|
let char = this.profile.char
|
2023-05-18 20:23:19 +00:00
|
|
|
|
|
|
|
if (this.isSr) {
|
|
|
|
// 星铁面板属性
|
|
|
|
lodash.forEach(wCalcRet, (v, k) => {
|
|
|
|
k = k + (['hp', 'atk', 'def'].includes(k) ? 'Base' : '')
|
|
|
|
self.addAttr(k, v, true)
|
|
|
|
})
|
2023-05-20 13:51:44 +00:00
|
|
|
// 检查武器类型
|
2023-10-19 07:46:08 +00:00
|
|
|
if (weapon.type === char.weapon) {
|
2023-05-20 13:51:44 +00:00
|
|
|
// todo sr&gs 统一
|
2023-05-21 18:13:38 +00:00
|
|
|
let wBuffs = weapon.getWeaponAffixBuffs(wData.affix, true)
|
2023-05-20 13:51:44 +00:00
|
|
|
lodash.forEach(wBuffs, (buff) => {
|
|
|
|
lodash.forEach(buff.data || [], (v, k) => {
|
|
|
|
self.addAttr(k, v)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2023-05-18 20:23:19 +00:00
|
|
|
return
|
|
|
|
}
|
2023-02-21 19:49:49 +00:00
|
|
|
|
2023-05-20 13:51:44 +00:00
|
|
|
// 原神属性
|
2023-02-21 19:49:49 +00:00
|
|
|
if (wCalcRet) {
|
|
|
|
this.addAttr('atkBase', wCalcRet.atkBase)
|
2023-02-22 02:15:55 +00:00
|
|
|
this.addAttr(wCalcRet.attr?.key, wCalcRet.attr?.value)
|
2022-11-20 20:45:27 +00:00
|
|
|
}
|
2022-11-21 21:26:06 +00:00
|
|
|
|
2023-10-21 18:54:45 +00:00
|
|
|
let { weaponBuffs } = Meta.getMeta('gs', 'weapon')
|
|
|
|
|
2022-11-21 21:26:06 +00:00
|
|
|
let wBuffs = weaponBuffs[weapon.name] || []
|
|
|
|
if (lodash.isPlainObject(wBuffs)) {
|
|
|
|
wBuffs = [wBuffs]
|
|
|
|
}
|
|
|
|
let affix = wData.affix || 1
|
|
|
|
lodash.forEach(wBuffs, (buff) => {
|
|
|
|
if (!buff.isStatic) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if (buff) {
|
|
|
|
lodash.forEach(buff.refine, (r, key) => {
|
|
|
|
this.addAttr(key, r[affix - 1] * (buff.buffCount || 1))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
2022-11-20 20:45:27 +00:00
|
|
|
}
|
|
|
|
|
2022-11-21 21:26:06 +00:00
|
|
|
/**
|
|
|
|
* 计算圣遗物属性
|
|
|
|
*/
|
2022-11-20 20:45:27 +00:00
|
|
|
setArtisAttr () {
|
2023-10-19 07:46:08 +00:00
|
|
|
let profile = this.profile
|
|
|
|
let artis = profile?.artis
|
2022-11-21 21:26:06 +00:00
|
|
|
// 计算圣遗物词条
|
2022-11-20 20:45:27 +00:00
|
|
|
artis.forEach((arti) => {
|
2023-10-19 07:46:08 +00:00
|
|
|
this.calcArtisAttr(arti.main, profile.char)
|
2022-11-20 20:45:27 +00:00
|
|
|
lodash.forEach(arti.attrs, (ds) => {
|
2023-10-19 07:46:08 +00:00
|
|
|
this.calcArtisAttr(ds, profile.char)
|
2022-11-20 20:45:27 +00:00
|
|
|
})
|
|
|
|
})
|
2022-11-21 21:26:06 +00:00
|
|
|
// 计算圣遗物静态加成
|
|
|
|
artis.eachArtisSet((set, num) => {
|
2023-05-21 18:13:38 +00:00
|
|
|
let buffs = ArtifactSet.getArtisSetBuff(set.name, num, this.game)
|
|
|
|
if (!buffs) return true
|
|
|
|
|
|
|
|
lodash.forEach(buffs, (buff) => {
|
|
|
|
if (!buff.isStatic) {
|
|
|
|
return true
|
|
|
|
}
|
2023-10-19 07:46:08 +00:00
|
|
|
if (buff.elem && !profile.char.isElem(buff.elem)) {
|
2023-05-21 18:13:38 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
lodash.forEach(buff.data, (val, key) => {
|
|
|
|
this.addAttr(key, val)
|
|
|
|
})
|
2022-11-21 21:26:06 +00:00
|
|
|
})
|
|
|
|
})
|
2022-11-20 20:45:27 +00:00
|
|
|
}
|
|
|
|
|
2022-11-21 21:26:06 +00:00
|
|
|
/**
|
|
|
|
* 计算单条圣遗物词缀
|
|
|
|
* @param ds
|
2023-05-18 20:23:19 +00:00
|
|
|
* @param char
|
|
|
|
* @param autoPct
|
2022-11-21 21:26:06 +00:00
|
|
|
* @returns {boolean}
|
|
|
|
*/
|
2022-11-22 20:25:36 +00:00
|
|
|
calcArtisAttr (ds, char) {
|
2023-02-09 17:17:18 +00:00
|
|
|
if (!ds) {
|
|
|
|
return false
|
|
|
|
}
|
2022-11-23 20:26:07 +00:00
|
|
|
let key = ds.key
|
|
|
|
if (Format.isElem(key) && char.elem === key) {
|
2022-11-20 20:45:27 +00:00
|
|
|
key = 'dmg'
|
2022-11-22 20:25:36 +00:00
|
|
|
}
|
2022-11-20 20:45:27 +00:00
|
|
|
if (!key) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if (['atk', 'hp', 'def'].includes(key)) {
|
|
|
|
key = key + 'Pct'
|
|
|
|
}
|
2022-11-21 21:26:06 +00:00
|
|
|
this.attr.addAttr(key, ds.value * 1)
|
2022-11-20 20:45:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-18 17:01:11 +00:00
|
|
|
export default Attr
|