miao-plugin/models/Weapon.js

322 lines
7.8 KiB
JavaScript
Raw Normal View History

import Base from './Base.js'
import { Data, Format, Meta } from '#miao'
let weaponSet
2022-11-26 21:51:36 +00:00
import lodash from 'lodash'
class Weapon extends Base {
constructor (meta, game = 'gs') {
if (!meta || !meta.name) {
return false
}
super()
let cache = this._getCache(`weapon:${game}:${meta.name}`)
if (cache) {
return cache
}
this.id = meta.id
this.name = meta.name
this.meta = meta
this.type = meta.type
this.star = meta.star
this.game = game
return this._cache()
}
get title () {
return this.name
}
get img () {
2023-10-24 19:34:36 +00:00
return `${this.isGs ? 'meta-gs' : 'meta-sr'}/weapon/${this.type}/${this.name}/icon.webp`
}
2023-10-23 14:14:09 +00:00
get abbr () {
let name = this.name
let abbr = this.meta?.abbr
return name.length <= 4 ? name : (abbr || name)
}
2023-11-10 20:35:41 +00:00
get sName () {
let name = this.name
let abbr = this.meta?.abbr
name = name.replaceAll(/[「」]/g, '')
return name.length <= 8 ? name : (abbr || name)
}
2023-02-21 19:49:49 +00:00
get imgs () {
if (this.isGs) {
return {
2023-10-24 19:34:36 +00:00
icon: `meta-gs/weapon/${this.type}/${this.name}/icon.webp`,
icon2: `meta-gs/weapon/${this.type}/${this.name}/awaken.webp`,
gacha: `meta-gs/weapon/${this.type}/${this.name}/gacha.webp`
}
} else {
return {
2023-05-18 20:23:19 +00:00
icon: `meta-sr/weapon/${this.type}/${this.name}/icon.webp`,
icon2: `meta-sr/weapon/${this.type}/${this.name}/icon-s.webp`,
gacha: `meta-sr/weapon/${this.type}/${this.name}/splash.webp`
}
2023-02-21 19:49:49 +00:00
}
}
get icon () {
return this.img
}
2022-11-20 20:45:27 +00:00
get detail () {
return this.getDetail()
}
get maxLv () {
return this.star <= 2 ? 70 : 90
}
get maxPromote () {
return this.star <= 2 ? 4 : 6
}
get maxAffix () {
2023-10-14 13:17:27 +00:00
if (this.isSr) {
return 5
}
let data = this.detail?.affixData?.datas || {}
return (data['0'] && data['0'][4]) ? 5 : 1
}
2022-11-26 21:51:36 +00:00
static isWeaponSet (name) {
weaponSet = weaponSet || Meta.getMeta('gs', 'weapon', 'weaponSet')
2022-11-26 21:51:36 +00:00
return weaponSet.includes(name)
}
static get (name, game = 'gs', type = '') {
let data = Meta.getData(game, 'weapon', name)
if (data) {
return new Weapon(data, game)
2022-11-26 21:51:36 +00:00
}
if (type && game === 'gs') {
const { weaponType } = Meta.getMeta(game, 'weapon')
2022-11-26 21:51:36 +00:00
let name2 = name + (weaponType[type] || type)
let data = Meta.getData(game, 'weapon', name2)
if (data) {
return new Weapon(data, game)
2022-11-26 21:51:36 +00:00
}
2022-11-20 20:45:27 +00:00
}
return false
}
2023-02-21 19:49:49 +00:00
static async forEach (fn, type = '', game = 'gs') {
Meta.forEach(game, 'weapon', async (ds, id) => {
let w = Weapon.get(ds.name)
if (!w || (type && type !== w.type)) {
return true
}
return await fn(w)
})
}
2023-02-21 19:49:49 +00:00
getDetail () {
if (this._detail) {
return this._detail
}
2023-10-24 19:34:36 +00:00
const path = this.isGs ? 'resources/meta-gs/weapon' : 'resources/meta-sr/weapon'
2023-02-21 19:49:49 +00:00
try {
this._detail = Data.readJSON(`${path}/${this.type}/${this.name}/data.json`, 'miao')
2023-02-21 19:49:49 +00:00
} catch (e) {
console.log(e)
}
return this._detail
}
2023-10-23 14:14:09 +00:00
/**
* 计算武器主属性
* @param level 武器等级
* @param promote 武器突破
* @returns {{atkBase: number, attr: {value: *, key: *}}|{}|boolean}
*/
2023-02-21 19:49:49 +00:00
calcAttr (level, promote = -1) {
2023-05-18 20:23:19 +00:00
let metaAttr = this.detail?.attr
if (!metaAttr) {
return false
}
if (this.isSr) {
let lvAttr = metaAttr[promote]
let ret = {}
lodash.forEach(lvAttr.attrs, (v, k) => {
ret[k] = v * 1
})
lodash.forEach(this.detail?.growAttr, (v, k) => {
ret[k] = ret[k] * 1 + v * (level - 1)
})
return ret
}
2023-02-21 19:49:49 +00:00
let lvLeft = 1
let lvRight = 20
let lvStep = [1, 20, 40, 50, 60, 70, 80, 90]
let currPromote = 0
for (let idx = 0; idx < lvStep.length - 1; idx++) {
if (promote === -1 || (currPromote === promote)) {
if (level >= lvStep[idx] && level <= lvStep[idx + 1]) {
lvLeft = lvStep[idx]
lvRight = lvStep[idx + 1]
break
}
}
currPromote++
}
let wAttr = this?.detail?.attr || {}
let wAtk = wAttr.atk || {}
let valueLeft = wAtk[lvLeft + '+'] || wAtk[lvLeft] || {}
let valueRight = wAtk[lvRight] || {}
let atkBase = valueLeft * 1 + ((valueRight - valueLeft) * (level - lvLeft) / (lvRight - lvLeft))
let wBonus = wAttr.bonusData || {}
valueLeft = wBonus[lvLeft + '+'] || wBonus[lvLeft]
valueRight = wBonus[lvRight]
let stepCount = Math.ceil((lvRight - lvLeft) / 5)
let valueStep = (valueRight - valueLeft) / stepCount
let value = valueLeft + (stepCount - Math.ceil((lvRight - level) / 5)) * valueStep
return {
atkBase,
attr: {
key: wAttr.bonusKey,
value
}
}
}
2023-10-23 14:14:09 +00:00
/**
* 获取武器精炼描述
* @param affix 精炼
* @returns {{name, desc: *}|{}}
*/
getAffixDesc (affix = 1) {
2023-10-14 13:17:27 +00:00
if (this.isGs) {
2023-10-23 14:14:09 +00:00
let { text, datas } = this.detail?.affixData || {}
let { descFix } = Meta.getMeta('gs', 'weapon')
let reg = /\$\[(\d)\]/g
let ret
let desc = descFix[this.name] || text || ''
while ((ret = reg.exec(desc)) !== null) {
let idx = ret[1]
let value = datas?.[idx]?.[affix - 1]
desc = desc.replaceAll(ret[0], `<nobr>${value}</nobr>`)
}
return {
name: '',
desc
}
2023-10-14 13:17:27 +00:00
}
let skill = this.detail.skill
2023-10-23 14:14:09 +00:00
let { desc, tables } = skill
let reg = /\$(\d)\[(i|f1|f2)\](\%?)/g
let ret
while ((ret = reg.exec(desc)) !== null) {
let [txt, idx, format, pct] = ret
let value = tables?.[idx]?.[affix - 1]
if (pct === '%') {
value = Format.pct(value, format === 'f2' ? 2 : 1)
2023-05-20 17:14:07 +00:00
} else {
value = Format.comma(value)
}
desc = desc.replaceAll(txt, value)
}
return {
2023-10-23 14:14:09 +00:00
name: skill.name || '',
desc
}
}
2023-10-23 14:14:09 +00:00
/**
* 获取当前武器Buff配置
* @returns {*|boolean}
*/
2023-05-21 18:13:38 +00:00
getWeaponBuffs () {
let { game } = this
let { weaponBuffs } = Meta.getMeta(game, 'weapon')
let buffs = weaponBuffs[this.id] || weaponBuffs[this.name]
if (!buffs) {
return false
}
2023-05-21 18:13:38 +00:00
if (lodash.isPlainObject(buffs) || lodash.isFunction(buffs)) {
buffs = [buffs]
}
2023-05-21 18:13:38 +00:00
return buffs
}
2023-10-23 14:14:09 +00:00
/**
* 获取武器精炼 Buff
* @param affix
* @param isStatic
* @returns {*[]}
*/
2023-05-21 18:13:38 +00:00
getWeaponAffixBuffs (affix, isStatic = true) {
let buffs = this.getWeaponBuffs()
let ret = []
let self = this
let { detail } = this
let tables = {}
lodash.forEach(detail?.skill?.tables || {}, (ds, idx) => {
tables[idx] = ds[affix - 1]
})
lodash.forEach(buffs, (ds) => {
2023-05-21 18:13:38 +00:00
if (lodash.isFunction(ds)) {
ds = ds(tables)
}
if (!!ds.isStatic !== !!isStatic) {
return true
}
2023-05-21 18:13:38 +00:00
// 静态属性
if (ds.isStatic) {
let tmp = {}
2023-05-21 18:13:38 +00:00
// 星铁武器格式
if (ds.idx && ds.key) {
if (!ds.idx || !ds.key) return true
if (!tables[ds.idx]) return true
tmp[ds.key] = tables[ds.idx]
}
if (ds.refine) {
lodash.forEach(ds.refine, (r, key) => {
tmp[key] = r[affix - 1] * (ds.buffCount || 1)
})
}
if (!lodash.isEmpty(tmp)) {
ret.push({
isStatic: true,
data: tmp
})
}
return true
}
// 自动拼接标题
if (!//.test(ds.title)) {
ds.title = `${self.name}${ds.title}`
}
ds.data = ds.data || {}
// refine
if (ds.idx && ds.key) {
if (!ds.idx || !ds.key) return true
if (!tables[ds.idx]) return true
ds.data[ds.key] = tables[ds.idx]
} else if (ds.refine) {
lodash.forEach(ds.refine, (r, key) => {
ds.data[key] = ({ refine }) => r[refine] * (ds.buffCount || 1)
})
}
2023-05-21 18:13:38 +00:00
ret.push(ds)
})
2023-05-21 18:13:38 +00:00
return ret
}
}
export default Weapon