增加希儿的伤害计算

This commit is contained in:
Kokomi 2023-05-22 02:13:38 +08:00
parent 37e5d6c21a
commit e490426fd8
24 changed files with 545 additions and 236 deletions

View File

@ -132,18 +132,19 @@ let ProfileDetail = {
let base = profile.base
let attr = {}
let game = char.game
let isGs = game === 'gs'
lodash.forEach((game === 'gs' ? 'hp,def,atk,mastery' : 'hp,def,atk,speed').split(','), (key) => {
lodash.forEach((isGs ? 'hp,def,atk,mastery' : 'hp,def,atk,speed').split(','), (key) => {
let fn = (n) => Format.comma(n, key === 'hp' ? 0 : 1)
attr[key] = fn(a[key])
attr[`${key}Base`] = fn(base[key])
attr[`${key}Plus`] = fn(a[key] - base[key])
})
lodash.forEach((game === 'gs' ? 'cpct,cdmg,recharge,dmg' : 'cpct,cdmg,recharge,dmg,effPct,stance').split(','), (key) => {
lodash.forEach((isGs ? 'cpct,cdmg,recharge,dmg' : 'cpct,cdmg,recharge,dmg,effPct,stance').split(','), (key) => {
let fn = Format.pct
let key2 = key
if (key === 'dmg') {
if (game === 'gs') {
if (isGs) {
if (a.phy > a.dmg) {
key2 = 'phy'
}
@ -162,7 +163,7 @@ let ProfileDetail = {
wCfg.weapons = await ProfileWeapon.calc(profile)
}
let enemyLv = await selfUser.getCfg('char.enemyLv', 91)
let enemyLv = isGs ? (await selfUser.getCfg('char.enemyLv', 91)) : profile.level
let dmgCalc = await ProfileDetail.getProfileDmgCalc({ profile, enemyLv, mode, params })
let rank = false

View File

@ -55,14 +55,14 @@ export async function groupRank (e) {
e.uid = uid
return await ProfileDetail.render(e, char)
} else {
if (mode === 'dmg' && !ProfileDmg.dmgRulePath(char.name)) {
if (mode === 'dmg' && !ProfileDmg.dmgRulePath(char.name, char.game)) {
e.reply(`暂无排名:${char.name}暂不支持伤害计算,无法进行排名..`)
} else {
e.reply('暂无排名:请通过【#面板】查看角色面板以更新排名信息...')
}
}
} else if (type === 'list') {
if (mode === 'dmg' && char && !ProfileDmg.dmgRulePath(char.name)) {
if (mode === 'dmg' && char && !ProfileDmg.dmgRulePath(char.name, char.game)) {
e.reply(`暂无排名:${char.name}暂不支持伤害计算,无法进行排名..`)
} else {
let uids = []

View File

@ -5,7 +5,7 @@ import Base from './Base.js'
import { Format } from '#miao'
import { ArtifactSet } from './index.js'
import { artiMap, attrMap, mainIdMap, attrIdMap } from '../resources/meta/artifact/index.js'
import { idMap as idMapSR, artiMap as artiMapSR, metaData as metaDataSR } from '../resources/meta-sr/artifact/index.js'
import { idMap as idMapSR, artiMap as artiMapSR, metaData as metaDataSR, abbr as abbrSR } from '../resources/meta-sr/artifact/index.js'
import lodash from 'lodash'
class Artifact extends Base {
@ -36,6 +36,10 @@ class Artifact extends Base {
return this.set
}
get abbr () {
return (abbrSR && abbrSR[this.name]) || this.name
}
get img () {
return this.isGs ? `meta/artifact/imgs/${this.setName}/${this.idx}.webp` : `meta-sr/artifact/${this.setName}/arti-${this.idx}.webp`
}

View File

@ -1,9 +1,10 @@
/*
* 圣遗物套装
* */
import lodash from 'lodash'
import Base from './Base.js'
import { abbr, artiMap, artiSetMap } from '../resources/meta/artifact/index.js'
import { artiMap as artiMapSR, artiSetMap as artiSetMapSR } from '../resources/meta-sr/artifact/index.js'
import { abbr, artiMap, artiSetMap, calc as artisBuffs } from '../resources/meta/artifact/index.js'
import { artiMap as artiMapSR, artisBuffs as artisBuffsSR, artiSetMap as artiSetMapSR } from '../resources/meta-sr/artifact/index.js'
import { Artifact } from './index.js'
@ -65,6 +66,14 @@ class ArtifactSet extends Base {
return ''
}
static getArtisSetBuff (name, num, game = 'gs') {
let artiBuffsMap = game === 'sr' ? artisBuffsSR : artisBuffs
let ret = (artiBuffsMap[name] && artiBuffsMap[name][num]) || artiBuffsMap[name + num]
if (!ret) return false
if (lodash.isPlainObject(ret)) return [ret]
return ret
}
getArtiName (idx = 1) {
return this.sets[idx]
}

View File

@ -88,6 +88,7 @@ export default class ProfileArtis extends AvatarArtis {
let artifact = Artifact.get(arti.name, this.game)
artis[idx] = {
name: artifact.name,
abbr: artifact.abbr,
set: artifact.setName,
img: artifact.img,
level: arti.level,

View File

@ -50,7 +50,7 @@ export default class ProfileData extends AvatarData {
}
get hasDmg () {
return this.hasData && !!ProfileDmg.dmgRulePath(this.name)
return this.hasData && !!ProfileDmg.dmgRulePath(this.name, this.game)
}
static create (ds, game = 'gs') {
@ -96,10 +96,10 @@ export default class ProfileData extends AvatarData {
// 计算当前profileData的伤害信息
async calcDmg ({ enemyLv = 91, mode = 'profile', dmgIdx = 0 }) {
if (!this.dmg) {
let ds = this.getData('id,level,attr,cons,artis:artis.sets')
let ds = this.getData('id,level,attr,cons,artis:artis.sets,trees')
ds.talent = lodash.mapValues(this.talent, 'level')
ds.weapon = Data.getData(this.weapon, 'name,affix')
this.dmg = new ProfileDmg(ds)
this.dmg = new ProfileDmg(ds, this.game)
}
return await this.dmg.calcData({ enemyLv, mode, dmgIdx })
}

View File

@ -2,33 +2,36 @@ import fs from 'fs'
import lodash from 'lodash'
import Base from './Base.js'
import { Character } from './index.js'
import { attrMap } from '../resources/meta/artifact/index.js'
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'
import { Common } from '#miao'
export default class ProfileDmg extends Base {
constructor (profile = {}) {
constructor (profile = {}, game = 'gs') {
super()
this.profile = profile
this.game = game
if (profile && profile.id) {
let { id } = profile
this.char = Character.get(id)
}
}
static dmgRulePath (name) {
static dmgRulePath (name, game = 'gs') {
const _path = process.cwd()
let path = `${_path}/plugins/miao-plugin/resources/meta/character/${name}/calc_user.js`
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
}
path = `${_path}/plugins/miao-plugin/resources/meta/character/${name}/calc_auto.js`
path = `${_path}/plugins/miao-plugin/resources/${meta}/character/${name}/calc_auto.js`
if (fs.existsSync(path) && Common.cfg('teamCalc')) {
return path
}
path = `${_path}/plugins/miao-plugin/resources/meta/character/${name}/calc.js`
path = `${_path}/plugins/miao-plugin/resources/${meta}/character/${name}/calc.js`
if (fs.existsSync(path)) {
return path
}
@ -42,41 +45,17 @@ export default class ProfileDmg extends Base {
let ret = {}
let talentData = profile.talent || {}
let detail = char.detail
lodash.forEach(['a', 'e', 'q'], (key) => {
let { isSr, isGs } = this
lodash.forEach((isSr ? 'a,e,q,t' : 'a,e,q').split(','), (key) => {
let level = lodash.isNumber(talentData[key]) ? talentData[key] : (talentData[key]?.level || 1)
let map = {}
if (detail.talentData) {
lodash.forEach(char.detail.talentData[key], (ds, key) => {
if (isGs && detail.talentData) {
lodash.forEach(detail.talentData[key], (ds, key) => {
map[key] = ds[level - 1]
})
} else {
lodash.forEach(char.detail.talent[key].tables, (tr) => {
let val = tr.values[level - 1]
// eslint-disable-next-line no-control-regex
val = val.replace(/[^\x00-\xff]/g, '').trim()
val = val.replace(/[a-zA-Z]/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)
valArr2.push(v1 * 1)
})
valArr.push(valNum)
})
let name = tr.name2 || tr.name
if (isNaN(valArr[0])) {
map[name] = false
} else if (valArr.length === 1) {
map[name] = valArr[0]
} else {
map[name] = valArr
}
map[name + '2'] = valArr2
} else if (isSr && detail.talent) {
lodash.forEach(detail.talent[key].tables, (ds) => {
map[ds.name] = ds.values[level - 1]
})
}
ret[key] = map
@ -84,13 +63,25 @@ export default class ProfileDmg extends Base {
return ret
}
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
}
// 获取buff列表
getBuffs (buffs) {
return DmgBuffs.getBuffs(this.profile, buffs)
return DmgBuffs.getBuffs(this.profile, buffs, this.game)
}
async getCalcRule () {
const cfgPath = ProfileDmg.dmgRulePath(this.char?.name)
const cfgPath = ProfileDmg.dmgRulePath(this.char?.name, this.char?.game)
let cfg = {}
if (cfgPath) {
cfg = await import(`file://${cfgPath}`)
@ -101,7 +92,7 @@ export default class ProfileDmg extends Base {
defDmgIdx: cfg.defDmgIdx || -1, // 默认详情index
defDmgKey: cfg.defDmgKey || '',
mainAttr: cfg.mainAttr || 'atk,cpct,cdmg', // 伤害属性
enemyName: cfg.enemyName || '小宝' // 敌人名称
enemyName: cfg.enemyName || this.isGs ? '小宝' : '弱点敌人' // 敌人名称
}
}
return false
@ -112,6 +103,7 @@ export default class ProfileDmg extends Base {
return false
}
let { profile } = this
let { game } = this.char
let charCalcData = await this.getCalcRule()
if (!charCalcData) {
@ -123,13 +115,15 @@ export default class ProfileDmg extends Base {
let meta = {
cons: profile.cons * 1,
talent
talent,
trees: this.trees()
}
let { id, weapon, attr } = profile
defParams = defParams || {}
let originalAttr = DmgAttr.getAttr({ id, weapon, attr, char: this.char })
let originalAttr = DmgAttr.getAttr({ id, weapon, attr, char: this.char, game })
buffs = this.getBuffs(buffs)
@ -173,7 +167,7 @@ export default class ProfileDmg extends Base {
}
let ds = lodash.merge({ talent }, DmgAttr.getDs(attr, meta, params))
let dmg = DmgCalc.getDmgFn({ ds, attr, level: profile.level, enemyLv, showDetail: detail.showDetail })
let dmg = DmgCalc.getDmgFn({ ds, attr, level: profile.level, enemyLv, showDetail: detail.showDetail, game })
let basicDmgRet
if (detail.dmg) {
@ -209,6 +203,8 @@ export default class ProfileDmg extends Base {
attr: []
}
let attrMap = game === 'gs' ? attrMapGS : attrMapSR
// 计算角色属性增减
mainAttr = mainAttr.split(',')
let params = lodash.merge({}, defParams, detail.params || {})
@ -228,10 +224,11 @@ export default class ProfileDmg extends Base {
params,
incAttr,
reduceAttr,
talent: detail.talent || ''
talent: detail.talent || '',
game
})
let ds = lodash.merge({ talent }, DmgAttr.getDs(attr, meta, params))
let dmg = DmgCalc.getDmgFn({ ds, attr, level: profile.level, enemyLv })
let dmg = DmgCalc.getDmgFn({ ds, attr, level: profile.level, enemyLv, game })
if (detail.dmg) {
let dmgCalcRet = detail.dmg(ds, dmg)
rowData.push({

View File

@ -66,7 +66,6 @@ export default class ProfileReq extends Base {
async requestProfile (player, serv) {
let self = this
console.log('self.game', self.game)
this.serv = serv
let uid = this.uid
let reqParam = await serv.getReqParam(uid, self.game)

View File

@ -195,35 +195,81 @@ class Weapon extends Base {
}
}
getWeaponBuffs (affix, isStatic = true) {
let { isSr, detail } = this
getWeaponBuffs () {
let { isSr } = this
let wBuffs = (isSr ? weaponBuffsSR : weaponBuffs)
let buffs = wBuffs[this.id] || wBuffs[this.name]
if (!buffs) {
return false
}
let ret = []
if (lodash.isPlainObject(buffs)) {
if (lodash.isPlainObject(buffs) || lodash.isFunction(buffs)) {
buffs = [buffs]
}
return buffs
}
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) => {
if (lodash.isFunction(ds)) {
ds = ds(tables)
}
if (!!ds.isStatic !== !!isStatic) {
return true
}
if (isSr) {
if (!ds.idx || !ds.key) return true
let value = detail?.skill?.tables?.[ds.idx]
if (!value) return true
if (!value[affix - 1]) return true
// 静态属性
if (ds.isStatic) {
let tmp = {}
tmp[ds.key] = value[affix - 1]
ret.push({
isStatic: true,
data: tmp
// 星铁武器格式
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)
})
}
ret.push(ds)
})
return ret
}
}

View File

@ -6,9 +6,13 @@ import lodash from 'lodash'
const CharTalent = {
// 处理获取天赋数据
getAvatarTalent (char, talent, cons, mode) {
let { id, talentCons, game } = char
let { id, talentCons, game, isGs } = char
let ret = {}
lodash.forEach(game === 'gs' ? ['a', 'e', 'q'] : ['a', 'e', 'q', 't'], (key) => {
let addTalent = {
gs: { a: 0, e: 3, q: 3 },
sr: { a: 1, e: 2, q: 2, t: 2 }
}
lodash.forEach(addTalent[game], (addNum, key) => {
let ds = talent[key]
if (!ds) {
return false
@ -23,14 +27,14 @@ const CharTalent = {
if (mode !== 'level') {
// 基于original计算level
value = value || ds.original || ds.level_original || ds.level || ds.level_current
if (value > 10) {
if (value > 10 && isGs) {
mode = 'level'
} else {
original = value
if (key === 'a' && char.isGs) {
if (key === 'a' && isGs) {
level = aPlus ? value + 1 : value
} else {
level = cons >= talentCons[key] ? (value + 3) : value
level = cons >= talentCons[key] ? (value + addNum) : value
}
}
}
@ -38,10 +42,10 @@ const CharTalent = {
// 基于level计算original
value = value || ds.level || ds.level_current || ds.original || ds.level_original
level = value
if (key === 'a' && char.isGs) {
if (key === 'a' && isGs) {
original = aPlus ? value - 1 : value
} else {
original = cons >= talentCons[key] ? (value - 3) : value
original = cons >= talentCons[key] ? (value - addNum) : value
}
}
ret[key] = { level, original }

View File

@ -40,7 +40,6 @@ const MysAvatar = {
/**
* 更新米游社角色信息
* @param player
* @param mys
* @param force
* @returns {Promise<boolean>}
*/

View File

@ -46,7 +46,6 @@ const Profile = {
servCfg = servCfg[servIdx] || servCfg[0] || '0'
if (game === 'sr') {
console.log(servCfg, hasToken)
if ((servCfg === '0' || servCfg === '1') && hasToken) {
return Profile.serv('miao')
}
@ -77,7 +76,6 @@ const Profile = {
return false
}
player._update = []
console.log('player game', player.game)
let { uid, e } = player
if (uid.toString().length !== 9 || !e) {
return false
@ -109,7 +107,6 @@ const Profile = {
if (!avatar._source || !['enka', 'change', 'miao', 'mgg', 'hutao', 'homo'].includes(avatar._source)) {
return false
}
// 检查武器及天赋
if (!avatar.weapon || lodash.isUndefined(avatar.weapon.promote) || !avatar.talent) {
return false

View File

@ -3,10 +3,8 @@
* @type {{}}
*/
import { Weapon, ProfileAttr } from '../index.js'
import { Weapon, ProfileAttr, ArtifactSet } from '../index.js'
import { Format } from '#miao'
import { calc as artisBuffs } from '../../resources/meta/artifact/index.js'
import { artisBuffs as artisBuffsSR } from '../../resources/meta-sr/artifact/index.js'
import { weaponBuffs } from '../../resources/meta/weapon/index.js'
import lodash from 'lodash'
@ -164,7 +162,6 @@ class AttrCalc {
let wCalcRet = weapon.calcAttr(wData.level, wData.promote)
let self = this
let buffs = weapon.getWeaponBuffs(wData.affix, true)
if (this.isSr) {
// 星铁面板属性
lodash.forEach(wCalcRet, (v, k) => {
@ -174,7 +171,7 @@ class AttrCalc {
// 检查武器类型
if (weapon.type === this.char.weapon) {
// todo sr&gs 统一
let wBuffs = weapon.getWeaponBuffs(wData.affix, true)
let wBuffs = weapon.getWeaponAffixBuffs(wData.affix, true)
lodash.forEach(wBuffs, (buff) => {
lodash.forEach(buff.data || [], (v, k) => {
self.addAttr(k, v)
@ -219,18 +216,21 @@ class AttrCalc {
this.calcArtisAttr(ds, this.char)
})
})
let artiBuffsMap = this.isSr ? artisBuffsSR : artisBuffs
// 计算圣遗物静态加成
artis.eachArtisSet((set, num) => {
let buff = (artiBuffsMap[set.name] && artiBuffsMap[set.name][num]) || artiBuffsMap[set.name + num]
if (!buff || !buff.isStatic) {
return true
}
if (buff.elem && !this.char.isElem(buff.elem)) {
return true
}
lodash.forEach(buff.data, (val, key) => {
this.addAttr(key, val)
let buffs = ArtifactSet.getArtisSetBuff(set.name, num, this.game)
if (!buffs) return true
lodash.forEach(buffs, (buff) => {
if (!buff.isStatic) {
return true
}
if (buff.elem && !this.char.isElem(buff.elem)) {
return true
}
lodash.forEach(buff.data, (val, key) => {
this.addAttr(key, val)
})
})
})
}

View File

@ -1,7 +1,8 @@
/*
* 伤害计算 - 属性计算
* */
import { attrMap } from '../../resources/meta/artifact/index.js'
import { attrMap as attrMapGS } from '../../resources/meta/artifact/index.js'
import { attrMap as attrMapSR } from '../../resources/meta-sr/artifact/index.js'
import lodash from 'lodash'
import DmgMastery from './DmgMastery.js'
import { Format } from '#miao'
@ -13,7 +14,7 @@ let DmgAttr = {
},
// 获取profile对应attr属性值
getAttr ({ id, attr, weapon, char }) {
getAttr ({ id, attr, weapon, char, game = 'gs' }) {
let ret = {}
// 基础属性
@ -25,7 +26,7 @@ let DmgAttr = {
}
})
lodash.forEach('mastery,recharge,cpct,cdmg,heal,dmg,phy'.split(','), (key) => {
lodash.forEach((game === 'gs' ? 'mastery,recharge,cpct,cdmg,heal,dmg,phy' : 'speed,recharge,cpct,cdmg,heal,dmg').split(','), (key) => {
ret[key] = {
base: attr[key] * 1 || 0, // 基础值
plus: 0, // 加成值
@ -35,7 +36,7 @@ let DmgAttr = {
})
// 技能属性记录
lodash.forEach('a,a2,a3,e,q'.split(','), (key) => {
lodash.forEach((game === 'gs' ? 'a,a2,a3,e,q' : 'a,a2,a3,e,q,t').split(','), (key) => {
ret[key] = {
pct: 0, // 倍率加成
multi: 0, // 独立倍率乘区加成宵宫E等
@ -67,21 +68,23 @@ let DmgAttr = {
ret.element = Format.elemName(char.elem) // 元素类型
ret.refine = ((weapon.affix || ret.refine || 1) * 1 - 1) || 0 // 武器精炼
ret.multi = 0 // 倍率独立乘区
ret.vaporize = 0 // 蒸发
ret.melt = 0 // 融化
ret.burning = 0 // 燃烧
ret.superConduct = 0 // 超导
ret.swirl = 0 // 扩散
ret.electroCharged = 0 // 感电
ret.shatter = 0 // 碎冰
ret.overloaded = 0 // 超载
ret.bloom = 0 // 绽放
ret.burgeon = 0 // 烈绽放
ret.hyperBloom = 0 // 超绽放
ret.aggravate = 0 // 超激化
ret.spread = 0 // 蔓激化
ret.kx = 0 // 敌人抗性降低
ret.fykx = 0 // 敌人反应抗性降低
if (game === 'gs') {
ret.vaporize = 0 // 蒸发
ret.melt = 0 // 融化
ret.burning = 0 // 燃烧
ret.superConduct = 0 // 超导
ret.swirl = 0 // 扩散
ret.electroCharged = 0 // 感电
ret.shatter = 0 // 碎冰
ret.overloaded = 0 // 超载
ret.bloom = 0 // 绽放
ret.burgeon = 0 // 烈绽放
ret.hyperBloom = 0 // 超绽放
ret.aggravate = 0 // 超激化
ret.spread = 0 // 蔓激化
ret.fykx = 0 // 敌人反应抗性降低
}
return ret
},
@ -101,10 +104,12 @@ let DmgAttr = {
},
// 计算属性
calcAttr ({ originalAttr, buffs, meta, params = {}, incAttr = '', reduceAttr = '', talent = '' }) {
calcAttr ({ originalAttr, buffs, meta, params = {}, incAttr = '', reduceAttr = '', talent = '', game = 'gs' }) {
let attr = lodash.merge({}, originalAttr)
let msg = []
let attrMap = game === 'gs' ? attrMapGS : attrMapSR
if (incAttr && attrMap[incAttr]) {
let aCfg = attrMap[incAttr]
attr[incAttr][aCfg.calc] += aCfg.value
@ -144,6 +149,11 @@ let DmgAttr = {
return
}
}
if (!lodash.isUndefined(buff.maxCons)) {
if (ds.cons * 1 > buff.maxCons * 1) {
return
}
}
let title = buff.title
@ -163,12 +173,12 @@ let DmgAttr = {
title = title.replace(`[${key}]`, Format.comma(val, 1))
// 技能提高
let tRet = /^(a|a2|a3|e|q)(Def|Ignore|Dmg|Plus|Pct|Cpct|Cdmg|Multi)$/.exec(key)
let tRet = /^(a|a2|a3|e|q|t)(Def|Ignore|Dmg|Plus|Pct|Cpct|Cdmg|Multi)$/.exec(key)
if (tRet) {
attr[tRet[1]][tRet[2].toLowerCase()] += val * 1 || 0
return
}
let aRet = /^(hp|def|atk|mastery|cpct|cdmg|heal|recharge|dmg|phy|shield)(Plus|Pct|Inc)?$/.exec(key)
let aRet = /^(hp|def|atk|mastery|cpct|cdmg|heal|recharge|dmg|phy|shield|speed)(Plus|Pct|Inc)?$/.exec(key)
if (aRet) {
attr[aRet[1]][aRet[2] ? aRet[2].toLowerCase() : 'plus'] += val * 1 || 0
return
@ -177,6 +187,10 @@ let DmgAttr = {
attr.enemy.def += val * 1 || 0
return
}
if (key === 'ignore' || key === 'enemyIgnore') {
attr.enemy.ignore += val * 1 || 0
return
}
if (['vaporize', 'melt', 'burning', 'superConduct', 'swirl', 'electroCharged', 'shatter', 'overloaded', 'bloom', 'burgeon', 'hyperBloom', 'aggravate', 'spread', 'kx', 'fykx'].includes(key)) {
attr[key] += val * 1 || 0

View File

@ -2,63 +2,12 @@
* 伤害计算 - Buff计算
* */
import lodash from 'lodash'
import { Data } from '#miao'
import { ProfileArtis } from '../index.js'
let weaponBuffs = {}
let artisBuffs = {}
// lazy load
setTimeout(async function init () {
weaponBuffs = (await Data.importModule('resources/meta/weapon/index.js', 'miao')).weaponBuffs || {}
artisBuffs = (await Data.importModule('resources/meta/artifact/index.js', 'miao')).calc || {}
})
import { ProfileArtis, ArtifactSet, Weapon } from '../index.js'
let DmgBuffs = {
// 圣遗物Buff
getArtisBuffs (artis = {}) {
let buffs = artisBuffs
let retBuffs = []
ProfileArtis._eachArtisSet(artis, (sets, num) => {
let buff = buffs[sets.name] && buffs[sets.name][num]
if (buff && !buff.isStatic) {
retBuffs.push({
...buff,
title: `${sets.name}${num}` + buff.title
})
}
})
return retBuffs
},
// 武器Buff
getWeaponBuffs (weaponName) {
let weaponCfg = weaponBuffs[weaponName] || []
if (lodash.isPlainObject(weaponCfg)) {
weaponCfg = [weaponCfg]
}
let ret = []
lodash.forEach(weaponCfg, (ds) => {
if (ds.isStatic) {
return true
}
if (!//.test(ds.title)) {
ds.title = `${weaponName}${ds.title}`
}
if (ds.refine) {
ds.data = ds.data || {}
lodash.forEach(ds.refine, (r, key) => {
ds.data[key] = ({ refine }) => r[refine] * (ds.buffCount || 1)
})
}
ret.push(ds)
})
return ret
},
getBuffs (profile, buffs = []) {
let weaponBuffs = DmgBuffs.getWeaponBuffs(profile.weapon?.name || '')
let artisBuffs = DmgBuffs.getArtisBuffs(profile.artis)
getBuffs (profile, buffs = [], game = 'gs') {
let weaponBuffs = DmgBuffs.getWeaponBuffs(profile.weapon, game)
let artisBuffs = DmgBuffs.getArtisBuffs(profile.artis, game)
buffs = lodash.concat(buffs, weaponBuffs, artisBuffs)
let mKey = {
vaporize: '蒸发',
@ -88,6 +37,44 @@ let DmgBuffs = {
})
buffs = lodash.sortBy(buffs, ['sort'])
return buffs
},
// 圣遗物Buff
getArtisBuffs (artis = {}, game = 'gs') {
let retBuffs = []
ProfileArtis._eachArtisSet(artis, (sets, num) => {
let buffs = ArtifactSet.getArtisSetBuff(sets.name, num, game)
if (lodash.isPlainObject(buffs)) {
buffs = [buffs]
}
lodash.forEach(buffs, (buff) => {
if (buff && !buff.isStatic) {
retBuffs.push({
...buff,
title: `${sets.name}${num}` + buff.title
})
}
})
})
return retBuffs
},
// 武器Buff
getWeaponBuffs (wData, game = 'gs') {
let weapon = Weapon.get(wData.name, game)
if (!weapon) {
return false
}
let affix = wData.refine || wData.affix
let weaponCfg = weapon.getWeaponAffixBuffs(affix, false)
let ret = []
lodash.forEach(weaponCfg, (ds) => {
if (ds.isStatic) {
return true
}
ret.push(ds)
})
return ret
}
}
export default DmgBuffs

View File

@ -144,13 +144,17 @@ let DmgCalc = {
return ret
},
getDmgFn (data) {
let { showDetail, attr, ds } = data
let { showDetail, attr, ds, game } = data
let { calc } = ds
let dmgFn = function (pctNum = 0, talent = false, ele = false, basicNum = 0, mode = 'talent') {
if (ele) {
ele = erTitle[ele] || ele
}
if (game === 'sr') {
// 星铁meta数据天赋为百分比前数字
pctNum = pctNum * 100
}
return DmgCalc.calcRet({ pctNum, talent, ele, basicNum, mode }, data)
}

View File

@ -166,7 +166,7 @@
<span>+{{ds.level}}</span>
</div>
<div class="head">
<strong>{{ds.name}}</strong>
<strong>{{ds.abbr || ds.name}}</strong>
<span class="mark mark-{{ds.markClass}}"><span>{{ds.mark}}分</span> - {{ds.markClass}}</span>
</div>
<ul class="detail attr">
@ -248,8 +248,8 @@
<div class="td">词条变化</div>
{{each dmgCfg.attr attr}}
<div class="td">
<strong>{{attr.title}}</strong>
<span>+{{attr.text}}</span>
<strong>{{attr?.title}}</strong>
<span>+{{attr?.text}}</span>
</div>
{{/each}}
</div>

View File

@ -7,27 +7,139 @@ let attr = (key, val) => {
}
}
export default {
云无留迹的过客2: attr('heal', 10),
野穗伴行的快枪手2: attr('atkPct', 12),
野穗伴行的快枪手4: [attr('speed', 6), attr('aDmg', 10)],
净庭教宗的圣骑士2: attr('defPct', 15),
净庭教宗的圣骑士4: attr('shield', 20),
密林卧雪的猎人2: attr('ice', 10),
街头出身的拳王2: attr('phy', 10),
熔岩锻铸的火匠2: attr('fire', 10),
繁星璀璨的天才2: attr('quantum', 10),
激奏雷电的乐队2: attr('elec', 10),
晨昏交界的翔鹰2: attr('wind', 10),
流星追迹的怪盗2: attr('stance', 16),
流星追迹的怪盗4: attr('stance', 16),
盗匪荒漠的废土客2: attr('imaginary', 10),
太空封印站2: attr('atkPct', 12),
不老者的仙舟2: attr('hpPct', 12),
泛银河商业公司2: attr('effPct', 12),
筑城者的贝洛伯格2: attr('defPct', 12),
星体差分机2: attr('cdmg', 16),
停转的萨尔索图2: attr('cpct', 8),
盗贼公国塔利亚2: attr('stance', 16),
生命的翁瓦克2: attr('recharge', 5)
云无留迹的过客: {
2: attr('heal', 10)
},
野穗伴行的快枪手: {
2: attr('atkPct', 12),
4: [attr('speed', 6), attr('aDmg', 10)]
},
净庭教宗的圣骑士: {
2: attr('defPct', 15),
4: attr('shield', 20)
},
密林卧雪的猎人: {
2: attr('ice', 10),
4: {
title: '释放终结技后2回合爆伤提高25%',
data: {
cdmg: 25
}
}
},
街头出身的拳王: {
2: attr('phy', 10),
4: {
title: '攻击或被攻击5层Buff提高攻击力25%',
data: {
atkPct: 25
}
}
},
熔岩锻铸的火匠: {
2: attr('fire', 10),
4: {
title: '战技造成的伤害提高12%释放终结技下一次的火属性伤害提高12%',
data: {
eDmg: 12,
dmg: 12 // todo: 检查属性
}
}
},
繁星璀璨的天才: {
2: attr('quantum', 10),
4: {
title: '对有量子弱点的目标造成伤害时无视其20%的防御力',
data: {
ignore: 20
}
}
},
激奏雷电的乐队: {
2: attr('elec', 10),
4: {
title: '释放战绩时攻击力提高20%',
data: {
atkPct: 20
}
}
},
晨昏交界的翔鹰: {
2: attr('wind', 10)
},
流星追迹的怪盗: {
2: attr('stance', 16),
4: attr('stance', 16)
},
盗匪荒漠的废土客: {
2: attr('imaginary', 10),
4: {
title: '对陷入负面效果的目标的暴击率提高10%对禁锢状态的目标暴击率提高20%',
data: {
cpct: 10
}
}
},
太空封印站: {
2: [attr('atkPct', 12), {
title: '速度大于等于120提高攻击力12%',
check: ({ calc, attr }) => calc(attr.speed) > 120,
data: {
atkPct: 12
}
}]
},
不老者的仙舟: {
2: [attr('hpPct', 12), {
title: '速度大于等于120提高攻击力8%',
check: ({ calc, attr }) => calc(attr.speed) > 120,
data: {
atkPct: 8
}
}]
},
泛银河商业公司: {
2: [attr('effPct', 12), {
title: '基于效果命中提高攻击力[atkPct]%',
data: {
atkPct: ({ calc, attr }) => Math.min(25, calc(attr.effPct) / 4 || 0)
}
}]
},
筑城者的贝洛伯格: {
2: [attr('defPct', 12), {
title: '效果命中大于50%时提高防御力15%',
check: ({ calc, attr }) => calc(attr.effPct) > 50,
data: {
defPct: 15
}
}]
},
星体差分机: {
2: attr('cdmg', 16)
},
停转的萨尔索图: {
2: [attr('cpct', 8), {
title: '终结技与追加攻击造成的伤害提高15%',
check: ({ attr, calc }) => {
return calc(attr.cpct) > 50
},
data: {
qDmg: 15,
a3Dmg: 15
}
}]
},
盗贼公国塔利亚: {
2: [attr('stance', 16), {
title: '速度大于145时击破特攻提高20%',
check: ({ calc, attr }) => calc(attr.speed) > 145,
data: {
stance: 20
}
}]
},
生命的翁瓦克: {
2: attr('recharge', 5)
}
}

View File

@ -30,5 +30,7 @@ lodash.forEach(data, (setData) => {
artiSet.sets[idx] = ds.name
})
})
export const metaData = meta
export { artiMap, idMap, artisBuffs, artiSetMap }
export { artiMap, idMap, artisBuffs, artiSetMap }
export * from './meta.js'

View File

@ -1,3 +1,7 @@
import lodash from 'lodash'
import { Format } from '#miao'
import { attrPct, basicNum } from '../../meta/artifact/index.js'
export const mainAttr = {
3: 'atk,def,hp,cpct,cdmg,heal,effPct'.split(','),
4: 'atk,def,hp,speed'.split(','),
@ -16,20 +20,62 @@ export const subAttr = 'atk,atkPlus,def,defPlus,hp,hpPlus,speed,cpct,cdmg,effPct
* @[]base 词条类型为小词条时对应的大词条
* @[]text 展示文字
*/
export const attrMap = {
atk: { title: '大攻击', format: 'pct', calc: 'pct' },
atkPlus: { title: '小攻击', format: 'comma' },
def: { title: '大防御', format: 'pct', calc: 'pct' },
defPlus: { title: '小防御', format: 'comma' },
hp: { title: '大生命', format: 'pct', calc: 'pct' },
hpPlus: { title: '小生命', format: 'comma' },
speed: { title: '速度', format: 'comma' },
cpct: { title: '暴击率', format: 'pct', calc: 'plus' },
cdmg: { title: '暴击伤害', format: 'pct', calc: 'plus' },
const attrMap = {
atk: { title: '大攻击', format: 'pct', calc: 'pct', value: 4.32 },
atkPlus: { title: '小攻击', format: 'comma', value: 21 },
def: { title: '大防御', format: 'pct', calc: 'pct', value: 5.4 },
defPlus: { title: '小防御', format: 'comma', value: 21 },
hp: { title: '大生命', format: 'pct', calc: 'pct', value: 4.32 },
hpPlus: { title: '小生命', format: 'comma', value: 42 },
speed: { title: '速度', format: 'comma', calc: 'plus', value: 2.6 },
cpct: { title: '暴击率', format: 'pct', calc: 'plus', value: 3.24 },
cdmg: { title: '暴击伤害', format: 'pct', calc: 'plus', value: 6.48 },
recharge: { title: '充能效率', format: 'pct', calc: 'plus' },
dmg: { title: '伤害加成', format: 'pct' },
heal: { title: '治疗加成', format: 'pct' },
stance: { title: '击破特攻', format: 'pct' },
effPct: { title: '效果命中', format: 'pct' },
effDef: { title: '效果抵抗', format: 'pct' }
stance: { title: '击破特攻', format: 'pct', value: 6.48 },
effPct: { title: '效果命中', format: 'pct', value: 4.32 },
effDef: { title: '效果抵抗', format: 'pct', value: 4.32 }
}
lodash.forEach(attrMap, (attr, key) => {
// 设置value
if (!attr.value) {
return true
}
// 设置type
attr.base = { hpPlus: 'hp', atkPlus: 'atk', defPlus: 'def' }[key]
attr.type = attr.base ? 'plus' : 'normal'
// 设置展示文字
attr.text = Format[attr.format](attr.value, 2)
})
export { attrMap }
export const abbr = {
快枪手的野穗毡帽: '快枪手的毡帽',
快枪手的粗革手套: '快枪手的手套',
快枪手的猎风披肩: '快枪手的披肩',
快枪手的铆钉马靴: '快枪手的铆钉靴',
废土客的呼吸面罩: '废土客的面罩',
废土客的荒漠终端: '废土客的终端',
废土客的修士长袍: '废土客的长袍',
废土客的动力腿甲: '废土客的腿甲',
'「黑塔」的空间站点': '黑塔的空间站点',
'「黑塔」的漫历轨迹': '黑塔的漫历轨迹',
罗浮仙舟的天外楼船: '罗浮仙舟的楼船',
罗浮仙舟的建木枝蔓: '罗浮仙舟的建木',
贝洛伯格的存护堡垒: '贝洛伯格的堡垒',
贝洛伯格的铁卫防线: '贝洛伯格的防线',
螺丝星的机械烈阳: '螺丝星的烈阳',
螺丝星的环星孔带: '螺丝星的孔带',
萨尔索图的移动城市: '萨尔索图的城市',
萨尔索图的晨昏界线: '萨尔索图的界线',
塔利亚的钉壳小镇: '塔利亚的小镇',
塔利亚的裸皮电线: '塔利亚的电线',
翁瓦克的诞生之岛: '翁瓦克的诞生岛',
翁瓦克的环岛海岸: '翁瓦克的海岸'
}

View File

@ -9,14 +9,14 @@ let alias = {
卡夫卡: '亲妈',
姬子: '',
娜塔莎: '纳塔莎,纳塔沙,纳塔沙',
布洛妮娅: '大鸭鸭,鸭鸭,板鸭,布洛尼亚',
希儿: '希尔,云天明,蝴蝶',
布洛妮娅: '大鸭鸭,鸭鸭,板鸭,布洛尼亚,布洛妮亚,布洛尼娅',
希儿: '希尔,蝴蝶,云天明',
希露瓦: '希璐瓦',
彦卿: '延卿,闫卿,彦清,彦青',
景元: '景原,景源,神君发射器',
杰帕德: '',
桑博: '',
瓦尔特: '老杨,瓦尔特杨',
桑博: '桑柏,桑伯',
瓦尔特: '老杨,杨叔,瓦尔特杨',
白露: '小龙人',
素裳: '',
罗刹: '罗沙,罗杀',

View File

@ -0,0 +1,43 @@
export const details = [{
title: '普攻伤害',
dmg: ({ talent }, dmg) => dmg(talent.a['技能伤害'], 'a')
}, {
title: '战技伤害',
dmg: ({ talent }, dmg) => dmg(talent.e['技能伤害'], 'e')
}, {
title: '终结技伤害',
dmg: ({ talent }, dmg) => dmg(talent.q['技能伤害'], 'q')
}]
export const mainAttr = 'atk,cpct,cdmg,speed'
export const buffs = [{
title: '希儿天赋:击杀敌人增幅状态提高伤害[dmg]%',
data: {
dmg: ({ talent }) => talent.t['伤害提高'] * 100
}
}, {
title: '希儿战技释放战技后速度提高25%',
maxCons: 1,
data: {
speedPct: 25
}
}, {
title: '希儿1命对生命小于80%的敌人造成伤害时暴击率提高15%',
cons: 1,
data: {
cpct: 15
}
}, {
title: '希儿2命释放战技后2层Buff速度提高50%',
cons: 2,
data: {
speedPct: 50
}
}, {
title: '夜行抗性穿透提高20',
check: ({ trees }) => trees[101],
data: {
kx: 20
}
}]

View File

@ -27,6 +27,12 @@ let loadBuffs = async function () {
idx,
key
}
}, (idx, key, title) => {
return {
title,
idx,
key
}
})
}
lodash.forEach(calc, (ds, key) => {

View File

@ -1,27 +1,65 @@
export default function (staticIdx) {
export default function (staticIdx, keyIdx) {
return {
于夜色中: [staticIdx(1, 'cpct'), ({ attr, tables }) => {
let buffCount = Math.min(6, Math.floor((attr.speed - 100) / 10))
let dmg = tables[2] * buffCount
let cdmg = tables[3] * buffCount
于夜色中: [
staticIdx(1, 'cpct'),
(tables) => {
return {
title: `[_count]层Buff提高普攻与战技伤害[aDmg]%,终结技的暴击伤害[qCdmg]%`,
data: {
_count: ({ attr, calc }) => Math.min(6, Math.floor((calc(attr.speed) - 100) / 10)) + '',
aDmg: ({ attr, calc }) => Math.min(6, Math.floor((calc(attr.speed) - 100) / 10)) * tables[2],
eDmg: ({ attr, calc }) => Math.min(6, Math.floor((calc(attr.speed) - 100) / 10)) * tables[2],
qCdmg: ({ attr, calc }) => Math.min(6, Math.floor((calc(attr.speed) - 100) / 10)) * tables[3]
}
}
}],
唯有沉默: [
staticIdx(1, 'atkPct'),
keyIdx(2, 'cpct', '场上目标小于等于2时暴击率提高[cpct]%')
],
如泥酣眠: [
staticIdx(1, 'cdmg')
],
星海巡航: [
staticIdx(1, 'cpct'),
keyIdx(2, 'cpct', '对生命值小于50%的敌人暴击率提高[cpct]%'),
keyIdx(3, 'atkPct', '消灭敌方目标后,攻击力提高[atkPct]%')
],
春水初生: [(tables) => {
return {
title: `${buffCount}层Buff提高普攻与战技伤害[aDmg]%,终结技的暴击伤害[qCdmg]%`,
title: '进入战斗提高速度[speedPct]%,伤害[dmg]%',
data: {
aDmg: dmg,
eDmg: dmg,
qCdmg: cdmg
speedPct: tables[1],
dmg: tables[2]
}
}
}],
'点个关注吧!': [(tables) => {
return {
title: '满能量提高普攻和战技伤害[aDmg]%',
data: {
aDmg: tables[1] * 2,
eDmg: tables[1] * 2
}
}
}],
相抗: [
keyIdx(1, 'speedPct', '消灭敌方目标后,速度提高[speedPct]%')
],
离弦: [
keyIdx(1, 'atkPct', '消灭敌方目标后,攻击力[atkPct]%')
],
论剑: [(tables) => {
return {
title: '连续击中5次同一个目标伤害提高[dmg]%',
data: {
dmg: tables[1] * 5
}
}
}],
唯有沉默: [staticIdx(1, 'atkPct')],
如泥酣眠: [staticIdx(1, 'cdmg')],
星海巡航: [staticIdx(1, 'cpct')],
春水初生: [],
'点个关注吧!': [],
相抗: [],
离弦: [],
论剑: [],
重返幽冥: [staticIdx(1, 'cpct')],
锋镝: []
锋镝: [
keyIdx(1, 'cpct', '战斗开始时暴击率提高[cpct]%')
]
}
}