Merge branch 'master' of github.com:yoimiya-kokomi/miao-plugin
Conflicts: resources/meta-sr/artifact/meta.json resources/meta-sr/character/三月七/data.json resources/meta-sr/character/三月七/imgs/splash.webp resources/meta-sr/character/丹恒/data.json resources/meta-sr/character/丹恒/imgs/splash.webp resources/meta-sr/character/佩拉/data.json resources/meta-sr/character/佩拉/imgs/splash.webp resources/meta-sr/character/停云/data.json resources/meta-sr/character/停云/imgs/splash.webp resources/meta-sr/character/克拉拉/data.json resources/meta-sr/character/克拉拉/imgs/splash.webp resources/meta-sr/character/卡芙卡/data.json resources/meta-sr/character/卡芙卡/imgs/splash.webp resources/meta-sr/character/姬子/data.json resources/meta-sr/character/姬子/imgs/splash.webp resources/meta-sr/character/娜塔莎/data.json resources/meta-sr/character/娜塔莎/imgs/splash.webp resources/meta-sr/character/布洛妮娅/data.json resources/meta-sr/character/布洛妮娅/imgs/splash.webp resources/meta-sr/character/希儿/data.json resources/meta-sr/character/希儿/imgs/splash.webp resources/meta-sr/character/希露瓦/data.json resources/meta-sr/character/希露瓦/imgs/splash.webp resources/meta-sr/character/彦卿/data.json resources/meta-sr/character/彦卿/imgs/splash.webp resources/meta-sr/character/景元/data.json resources/meta-sr/character/景元/imgs/splash.webp resources/meta-sr/character/杰帕德/data.json resources/meta-sr/character/杰帕德/imgs/splash.webp resources/meta-sr/character/桑博/data.json resources/meta-sr/character/桑博/imgs/splash.webp resources/meta-sr/character/瓦尔特/data.json resources/meta-sr/character/瓦尔特/imgs/splash.webp resources/meta-sr/character/白露/data.json resources/meta-sr/character/白露/imgs/splash.webp resources/meta-sr/character/素裳/data.json resources/meta-sr/character/素裳/imgs/splash.webp resources/meta-sr/character/罗刹/data.json resources/meta-sr/character/罗刹/imgs/splash.webp resources/meta-sr/character/艾丝妲/data.json resources/meta-sr/character/艾丝妲/imgs/splash.webp resources/meta-sr/character/虎克/data.json resources/meta-sr/character/虎克/imgs/splash.webp resources/meta-sr/character/银狼/data.json resources/meta-sr/character/银狼/imgs/splash.webp resources/meta-sr/character/阿兰/data.json resources/meta-sr/character/阿兰/imgs/splash.webp resources/meta-sr/character/青雀/data.json resources/meta-sr/character/青雀/imgs/splash.webp resources/meta-sr/character/黑塔/data.json resources/meta-sr/character/黑塔/imgs/splash.webp resources/meta-sr/weapon/丰饶/一场术后对话/data.json resources/meta-sr/weapon/丰饶/同一种心情/data.json resources/meta-sr/weapon/丰饶/嘉果/data.json resources/meta-sr/weapon/丰饶/时节不居/data.json resources/meta-sr/weapon/丰饶/暖夜不会漫长/data.json resources/meta-sr/weapon/丰饶/此时恰好/data.json resources/meta-sr/weapon/丰饶/物穰/data.json resources/meta-sr/weapon/丰饶/等价交换/data.json resources/meta-sr/weapon/丰饶/蕃息/data.json resources/meta-sr/weapon/同谐/与行星相会/data.json resources/meta-sr/weapon/同谐/但战斗还未结束/data.json resources/meta-sr/weapon/同谐/舞!舞!舞!/data.json resources/meta-sr/weapon/同谐/记忆中的模样/data.json resources/meta-sr/weapon/同谐/调和/data.json resources/meta-sr/weapon/同谐/轮契/data.json resources/meta-sr/weapon/同谐/过往未来/data.json resources/meta-sr/weapon/同谐/镂月裁云之意/data.json resources/meta-sr/weapon/同谐/齐颂/data.json resources/meta-sr/weapon/存护/余生的第一天/data.json resources/meta-sr/weapon/存护/制胜的瞬间/data.json resources/meta-sr/weapon/存护/宇宙市场趋势/data.json resources/meta-sr/weapon/存护/开疆/data.json resources/meta-sr/weapon/存护/戍御/data.json resources/meta-sr/weapon/存护/我们是地火/data.json resources/meta-sr/weapon/存护/朗道的选择/data.json resources/meta-sr/weapon/存护/琥珀/data.json resources/meta-sr/weapon/存护/记忆的质料/data.json resources/meta-sr/weapon/存护/这就是我啦!/data.json resources/meta-sr/weapon/巡猎/于夜色中/data.json resources/meta-sr/weapon/巡猎/唯有沉默/data.json resources/meta-sr/weapon/巡猎/如泥酣眠/data.json resources/meta-sr/weapon/巡猎/星海巡航/data.json resources/meta-sr/weapon/巡猎/春水初生/data.json resources/meta-sr/weapon/巡猎/点个关注吧!/data.json resources/meta-sr/weapon/巡猎/相抗/data.json resources/meta-sr/weapon/巡猎/离弦/data.json resources/meta-sr/weapon/巡猎/论剑/data.json resources/meta-sr/weapon/巡猎/重返幽冥/data.json resources/meta-sr/weapon/巡猎/锋镝/data.json resources/meta-sr/weapon/智识/「我」的诞生/data.json resources/meta-sr/weapon/智识/今日亦是和平的一日/data.json resources/meta-sr/weapon/智识/别让世界静下来/data.json resources/meta-sr/weapon/智识/天才们的休憩/data.json resources/meta-sr/weapon/智识/拂晓之前/data.json resources/meta-sr/weapon/智识/早餐的仪式感/data.json resources/meta-sr/weapon/智识/智库/data.json resources/meta-sr/weapon/智识/灵钥/data.json resources/meta-sr/weapon/智识/睿见/data.json resources/meta-sr/weapon/智识/银河铁道之夜/data.json resources/meta-sr/weapon/毁灭/乐圮/data.json resources/meta-sr/weapon/毁灭/俱殁/data.json resources/meta-sr/weapon/毁灭/在蓝天下/data.json resources/meta-sr/weapon/毁灭/天倾/data.json resources/meta-sr/weapon/毁灭/无可取代的东西/data.json resources/meta-sr/weapon/毁灭/无处可逃/data.json resources/meta-sr/weapon/毁灭/汪!散步时间!/data.json resources/meta-sr/weapon/毁灭/秘密誓心/data.json resources/meta-sr/weapon/毁灭/记一位星神的陨落/data.json resources/meta-sr/weapon/毁灭/鼹鼠党欢迎你/data.json resources/meta-sr/weapon/虚无/以世界之名/data.json resources/meta-sr/weapon/虚无/决心如汗珠般闪耀/data.json resources/meta-sr/weapon/虚无/匿影/data.json resources/meta-sr/weapon/虚无/后会有期/data.json resources/meta-sr/weapon/虚无/幽邃/data.json resources/meta-sr/weapon/虚无/延长记号/data.json resources/meta-sr/weapon/虚无/晚安与睡颜/data.json resources/meta-sr/weapon/虚无/渊环/data.json resources/meta-sr/weapon/虚无/猎物的视线/data.json
@ -1,3 +1,9 @@
|
||||
# 2.4.0 Dev
|
||||
|
||||
* !!!尚未完成,不推荐切换至Dev!!!
|
||||
* 初步支持星铁面板数据获取与展示
|
||||
* 面板属性计算暂未包含武器及圣遗物Buff,面板数据暂不准确
|
||||
|
||||
# 2.3.8
|
||||
|
||||
* 面板服务增加由**Snap Hutao**提供的Enka转发代理,可通过`#喵喵设置面板服务4`进行选择
|
||||
|
@ -14,6 +14,13 @@ let app = App.init({
|
||||
})
|
||||
|
||||
app.reg({
|
||||
profileList: {
|
||||
name: '面板角色列表',
|
||||
desc: '查看当前已获取面板数据的角色列表',
|
||||
fn: ProfileList.render,
|
||||
rule: /^#(星铁|原神)?(面板角色|角色面板|面板)(列表)?\s*(\d{9})?$/
|
||||
},
|
||||
|
||||
profileDetail: {
|
||||
name: '角色面板',
|
||||
fn: ProfileDetail.detail,
|
||||
@ -62,13 +69,6 @@ app.reg({
|
||||
rule: /^#圣遗物列表\s*(\d{9})?$/
|
||||
},
|
||||
|
||||
profileList: {
|
||||
name: '面板角色列表',
|
||||
desc: '查看当前已获取面板数据的角色列表',
|
||||
fn: ProfileList.render,
|
||||
rule: /^#(面板角色|角色面板|面板)(列表)?\s*(\d{9})?$/
|
||||
},
|
||||
|
||||
profileStat: {
|
||||
name: '面板练度统计',
|
||||
fn: ProfileStat.stat,
|
||||
@ -102,7 +102,7 @@ app.reg({
|
||||
name: '面板更新',
|
||||
describe: '【#角色】 获取游戏橱窗详情数据',
|
||||
fn: ProfileList.refresh,
|
||||
rule: /^#(全部面板更新|更新全部面板|获取游戏角色详情|更新面板|面板更新)\s*(\d{9})?$/
|
||||
rule: /^#(星铁|原神)?(全部面板更新|更新全部面板|获取游戏角色详情|更新面板|面板更新)\s*(\d{9})?$/
|
||||
},
|
||||
|
||||
uploadImg: {
|
||||
|
@ -86,7 +86,7 @@ const ProfileChange = {
|
||||
let wRet = /^(?:等?级?([1-9][0-9])?级?)?\s*(?:([1-5一二三四五满])?精炼?([1-5一二三四五])?)?\s*(?:等?级?([1-9][0-9])?级?)?\s*(.*)$/.exec(txt)
|
||||
if (wRet && wRet[5]) {
|
||||
let weaponName = lodash.trim(wRet[5])
|
||||
let weapon = Weapon.get(weaponName)
|
||||
let weapon = Weapon.get(weaponName, ret.char.game)
|
||||
if (weapon || weaponName === '武器' || Weapon.isWeaponSet(weaponName)) {
|
||||
let affix = wRet[2] || wRet[3]
|
||||
affix = { 一: 1, 二: 2, 三: 3, 四: 4, 五: 5, 满: 5 }[affix] || affix * 1
|
||||
@ -195,14 +195,14 @@ const ProfileChange = {
|
||||
elem: char.elem,
|
||||
dataSource: 'change',
|
||||
promote
|
||||
}, false)
|
||||
}, char.game, false)
|
||||
|
||||
// 设置武器
|
||||
let wCfg = ds.weapon || {}
|
||||
let wSource = getSource(wCfg).weapon || {}
|
||||
let weapon = Weapon.get(wCfg?.weapon || wSource?.name || defWeapon[char.weaponType], char.weaponType)
|
||||
let weapon = Weapon.get(wCfg?.weapon || wSource?.name || defWeapon[char.weaponType], char.game, char.weaponType)
|
||||
if (!weapon || weapon.type !== char.weaponType) {
|
||||
weapon = Weapon.get(defWeapon[char.weaponType])
|
||||
weapon = Weapon.get(defWeapon[char.weaponType], char.game)
|
||||
}
|
||||
let wDs = {
|
||||
name: weapon.name,
|
||||
|
@ -1,12 +1,14 @@
|
||||
import lodash from 'lodash'
|
||||
import { getTargetUid, getProfileRefresh } from './ProfileCommon.js'
|
||||
import ProfileList from './ProfileList.js'
|
||||
import { Cfg, Common, Format } from '#miao'
|
||||
import { Cfg, Common, Data, Format } from '#miao'
|
||||
import { MysApi, ProfileRank, ProfileArtis, Character, Weapon } from '#miao.models'
|
||||
import ProfileChange from './ProfileChange.js'
|
||||
import { profileArtis } from './ProfileArtis.js'
|
||||
import { ProfileWeapon } from './ProfileWeapon.js'
|
||||
|
||||
let { diyCfg } = await Data.importCfg('profile')
|
||||
|
||||
// 查看当前角色
|
||||
let ProfileDetail = {
|
||||
async detail (e) {
|
||||
@ -40,7 +42,7 @@ let ProfileDetail = {
|
||||
msg = msg.replace(uidRet[0], '')
|
||||
}
|
||||
|
||||
let name = msg.replace(/#|老婆|老公/g, '').trim()
|
||||
let name = msg.replace(/#|老婆|老公|星铁|原神/g, '').trim()
|
||||
msg = msg.replace('面版', '面板')
|
||||
let dmgRet = /(?:伤害|武器)(\d?)$/.exec(name)
|
||||
let dmgIdx = 0
|
||||
@ -72,6 +74,9 @@ let ProfileDetail = {
|
||||
if (!char) {
|
||||
return false
|
||||
}
|
||||
if (/星铁/.test(msg) || char.isSr) {
|
||||
e.isSr = true
|
||||
}
|
||||
|
||||
let uid = e.uid || await getTargetUid(e)
|
||||
if (!uid) {
|
||||
@ -128,33 +133,39 @@ let ProfileDetail = {
|
||||
let a = profile.attr
|
||||
let base = profile.base
|
||||
let attr = {}
|
||||
lodash.forEach(['hp', 'def', 'atk', 'mastery'], (key) => {
|
||||
let game = char.game
|
||||
let isGs = game === 'gs'
|
||||
|
||||
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(['cpct', 'cdmg', 'recharge', 'dmg'], (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' && a.phy > a.dmg) {
|
||||
key2 = 'phy'
|
||||
if (key === 'dmg') {
|
||||
if (isGs) {
|
||||
if (a.phy > a.dmg) {
|
||||
key2 = 'phy'
|
||||
}
|
||||
}
|
||||
}
|
||||
attr[key] = fn(a[key2])
|
||||
attr[`${key}Base`] = fn(base[key2])
|
||||
attr[`${key}Plus`] = fn(a[key2] - base[key2])
|
||||
})
|
||||
|
||||
let weapon = Weapon.get(profile.weapon.name)
|
||||
let weapon = Weapon.get(profile.weapon.name, game)
|
||||
let w = profile.weapon
|
||||
let wCfg = {}
|
||||
if (mode === 'weapon') {
|
||||
wCfg = weapon.calcAttr(w.level, w.promote)
|
||||
wCfg.info = weapon.getAffixInfo(weapon.affix)
|
||||
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
|
||||
@ -164,11 +175,14 @@ let ProfileDetail = {
|
||||
}
|
||||
|
||||
let artisDetail = profile.getArtisMark()
|
||||
let artisKeyTitle = ProfileArtis.getArtisKeyTitle()
|
||||
let artisKeyTitle = ProfileArtis.getArtisKeyTitle(game)
|
||||
let data = profile.getData('name,abbr,cons,level,talent,dataSource,updateTime,imgs,costumeSplash')
|
||||
data.weapon = profile.getWeaponDetail()
|
||||
let renderData = {
|
||||
save_id: uid,
|
||||
uid,
|
||||
data: profile.getData('name,abbr,cons,level,weapon,talent,dataSource,updateTime,imgs,costumeSplash'),
|
||||
game,
|
||||
data,
|
||||
attr,
|
||||
elem: char.elem,
|
||||
dmgCalc,
|
||||
@ -192,6 +206,9 @@ let ProfileDetail = {
|
||||
},
|
||||
|
||||
async getProfileDmgCalc ({ profile, enemyLv, mode, params }) {
|
||||
if (profile.isSr && !diyCfg.srDmg) {
|
||||
return false
|
||||
}
|
||||
let dmgMsg = []
|
||||
let dmgData = []
|
||||
let dmgCalc = await profile.calcDmg({
|
||||
@ -201,8 +218,10 @@ let ProfileDetail = {
|
||||
})
|
||||
if (dmgCalc && dmgCalc.ret) {
|
||||
lodash.forEach(dmgCalc.ret, (ds) => {
|
||||
ds.dmg = Format.comma(ds.dmg, 0)
|
||||
ds.avg = Format.comma(ds.avg, 0)
|
||||
if (ds.type !== 'text') {
|
||||
ds.dmg = Format.comma(ds.dmg, 0)
|
||||
ds.avg = Format.comma(ds.avg, 0)
|
||||
}
|
||||
dmgData.push(ds)
|
||||
})
|
||||
lodash.forEach(dmgCalc.msg, (msg) => {
|
||||
|
@ -61,7 +61,7 @@ const ProfileList = {
|
||||
isSelfUid = uids.join(',').split(',').includes(uid + '')
|
||||
}
|
||||
let rank = false
|
||||
let servName = Player.getProfileServName(uid)
|
||||
|
||||
let hasNew = false
|
||||
let newCount = 0
|
||||
|
||||
@ -75,10 +75,12 @@ const ProfileList = {
|
||||
const cfg = await Data.importCfg('cfg')
|
||||
// 获取面板数据
|
||||
let player = Player.create(e)
|
||||
let servName = Player.getProfileServName(uid, player.game)
|
||||
if (!player.hasProfile) {
|
||||
await player.refresh({ profile: true })
|
||||
}
|
||||
if (!player.hasProfile) {
|
||||
console.log(player.game)
|
||||
e.reply(`本地暂无uid${uid}的面板数据...`)
|
||||
return true
|
||||
}
|
||||
|
@ -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 = []
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ProfileData, Weapon } from '#miao.models'
|
||||
|
||||
export const ProfileWeapon = {
|
||||
async calc (profile) {
|
||||
async calc (profile, game = 'gs') {
|
||||
let ret = []
|
||||
await Weapon.forEach(async (w) => {
|
||||
let weaponRet = w.getData('name,star,abbr,icon')
|
||||
@ -13,7 +13,7 @@ export const ProfileWeapon = {
|
||||
let tempProfile = new ProfileData({
|
||||
...profile.getData('uid,id,level,cons,fetter,elem,promote,talent,artis'),
|
||||
dataSource: 'change'
|
||||
}, false)
|
||||
}, game, false)
|
||||
|
||||
tempProfile.setWeapon({
|
||||
name: w.name,
|
||||
|
@ -4,9 +4,10 @@ import { Common } from '#miao'
|
||||
import { Character, MysApi, Player } from '#miao.models'
|
||||
|
||||
export async function AbyssTeam (e) {
|
||||
let mys = await MysApi.init(e, 'cookie')
|
||||
if (!mys || !mys.uid || !mys.isSelfCookie) {
|
||||
return true
|
||||
let mys = await MysApi.init(e, 'all')
|
||||
if (!mys || !mys.uid) {
|
||||
e.reply(`请绑定ck后再使用${e.original_msg || e.msg}`)
|
||||
return false
|
||||
}
|
||||
let player = Player.create(e)
|
||||
await player.refreshMysDetail(2)
|
||||
|
@ -7,7 +7,7 @@
|
||||
import fetch from 'node-fetch'
|
||||
import { Data } from '#miao'
|
||||
|
||||
const host = 'http://miaoapi.cn/api/hutao'
|
||||
const host = 'http://49.232.91.210/api/hutao'
|
||||
|
||||
function getApi (api) {
|
||||
return `${host}?api=${api}`
|
||||
|
@ -96,7 +96,7 @@ let Cal = {
|
||||
}
|
||||
})
|
||||
}
|
||||
let miaoApi = 'http://miaoapi.cn/api/calendar'
|
||||
let miaoApi = 'http://49.232.91.210/api/calendar'
|
||||
try {
|
||||
request2 = await fetch(miaoApi)
|
||||
let data = await request2.json()
|
||||
|
@ -11,23 +11,39 @@ const elemAlias = {
|
||||
cryo: '冰,至冬'
|
||||
}
|
||||
|
||||
const elemAliasSR = {
|
||||
fire: '火',
|
||||
ice: '冰',
|
||||
wind: '风',
|
||||
elec: '雷',
|
||||
phy: '物理',
|
||||
quantum: '量子',
|
||||
imaginary: '虚数'
|
||||
}
|
||||
|
||||
// 元素属性映射, 名称=>elem
|
||||
let elemMap = {}
|
||||
let elemMapSR = {}
|
||||
|
||||
// 标准元素名
|
||||
let elemTitleMap = {}
|
||||
let elemTitleMapSR = elemAliasSR
|
||||
|
||||
lodash.forEach(elemAlias, (txt, key) => {
|
||||
elemMap[key] = key
|
||||
elemTitleMap[key] = txt[0]
|
||||
Data.eachStr(txt, (t) => (elemMap[t] = key))
|
||||
})
|
||||
lodash.forEach(elemAliasSR, (txt, key) => {
|
||||
elemMapSR[key] = key
|
||||
elemMapSR[txt] = key
|
||||
})
|
||||
|
||||
const Elem = {
|
||||
// 根据名称获取元素key
|
||||
elem (elem = '', defElem = '') {
|
||||
elem (elem = '', defElem = '', game = 'gs') {
|
||||
elem = elem.toLowerCase()
|
||||
return elemMap[elem] || defElem
|
||||
return (game === 'gs' ? elemMap : elemMapSR)[elem] || defElem
|
||||
},
|
||||
|
||||
// 根据key获取元素名
|
||||
@ -52,14 +68,19 @@ const Elem = {
|
||||
return ''
|
||||
},
|
||||
|
||||
eachElem (fn) {
|
||||
lodash.forEach(elemTitleMap, (title, key) => {
|
||||
eachElem (fn, game = 'gs') {
|
||||
lodash.forEach(game === 'gs' ? elemTitleMap : elemTitleMapSR, (title, key) => {
|
||||
fn(key, title)
|
||||
})
|
||||
},
|
||||
|
||||
isElem (elem = '') {
|
||||
return !!elemMap[elem]
|
||||
isElem (elem = '', game = 'gs') {
|
||||
return !!(game === 'gs' ? elemMap : elemMapSR)[elem]
|
||||
},
|
||||
|
||||
sameElem (key1, key2, game = 'gs') {
|
||||
let map = (game === 'gs' ? elemMap : elemMapSR)
|
||||
return map[key1] === map[key2]
|
||||
}
|
||||
}
|
||||
export default Elem
|
||||
|
@ -4,11 +4,11 @@
|
||||
* */
|
||||
|
||||
export const miaoApi = {
|
||||
listApi: ({ url, uid, diyCfg }) => {
|
||||
listApi: ({ url, uid, diyCfg, game = 'gs' }) => {
|
||||
let qq = /\d{5,12}/.test(diyCfg.qq) ? diyCfg.qq : 'none'
|
||||
let token = diyCfg.token
|
||||
url = url || 'http://miaoapi.cn/'
|
||||
return `${url}profile/data?uid=${uid}&qq=${qq}&token=${token}&version=2`
|
||||
url = url || 'http://49.232.91.210/'
|
||||
return `${url}profile/data?uid=${uid}&qq=${qq}&token=${token}&version=2&game=${game}`
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,6 +36,13 @@ export const hutaoApi = {
|
||||
}
|
||||
}
|
||||
|
||||
export const homoApi = {
|
||||
url: 'https://api.mihomo.me/sr_info',
|
||||
listApi: ({ url, uid, diyCfg }) => {
|
||||
return `${url}/${uid}`
|
||||
}
|
||||
}
|
||||
|
||||
export const requestInterval = 3
|
||||
|
||||
export const isSys = true
|
||||
|
@ -5,41 +5,54 @@ 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, abbr as abbrSR } from '../resources/meta-sr/artifact/index.js'
|
||||
import lodash from 'lodash'
|
||||
|
||||
class Artifact extends Base {
|
||||
static getAttrs
|
||||
|
||||
constructor (name) {
|
||||
constructor (name, game = 'gs') {
|
||||
super()
|
||||
let cache = this._getCache(`arti:${name}`)
|
||||
let cache = this._getCache(`arti:${game}:${name}`)
|
||||
if (cache) {
|
||||
return cache
|
||||
}
|
||||
let data = artiMap[name]
|
||||
this.game = game
|
||||
let data = (this.isGs ? artiMap : artiMapSR)[name]
|
||||
if (!data) {
|
||||
return false
|
||||
}
|
||||
this.name = name
|
||||
this.id = data.id || ''
|
||||
this.name = data.name
|
||||
this.meta = data
|
||||
return this._cache()
|
||||
}
|
||||
|
||||
get artiSet () {
|
||||
return ArtifactSet.get(this.set)
|
||||
return ArtifactSet.get(this.set, this.game)
|
||||
}
|
||||
|
||||
get setName () {
|
||||
return this.set
|
||||
}
|
||||
|
||||
get img () {
|
||||
return `meta/artifact/imgs/${this.setName}/${this.idx}.webp`
|
||||
get abbr () {
|
||||
return (abbrSR && abbrSR[this.name]) || this.name
|
||||
}
|
||||
|
||||
static get (name) {
|
||||
if (artiMap[name]) {
|
||||
return new Artifact(name)
|
||||
get img () {
|
||||
return this.isGs ? `meta/artifact/imgs/${this.setName}/${this.idx}.webp` : `meta-sr/artifact/${this.setName}/arti-${this.idx}.webp`
|
||||
}
|
||||
|
||||
static get (name, game = 'gs') {
|
||||
if (!name) {
|
||||
return false
|
||||
}
|
||||
if (game === 'sr') {
|
||||
name = idMapSR[name]?.name || name
|
||||
}
|
||||
if ((game === 'gs' ? artiMap : artiMapSR)[name]) {
|
||||
return new Artifact(name, game)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -96,6 +109,47 @@ class Artifact extends Base {
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
getStarById (id) {
|
||||
return this.meta.ids[id] || ''
|
||||
}
|
||||
|
||||
getAttrData (mainId, attrData, level = 1, star = 5, idx = 1) {
|
||||
let mainKey = metaDataSR.mainIdx[idx][mainId]
|
||||
let starCfg = metaDataSR.starData[star]
|
||||
let mainCfg = starCfg.main[mainKey]
|
||||
if (!mainId || !mainCfg) {
|
||||
return false
|
||||
}
|
||||
let main = {
|
||||
id: mainId,
|
||||
key: mainKey,
|
||||
value: mainCfg.base + mainCfg.step * level
|
||||
}
|
||||
let attrs = []
|
||||
lodash.forEach(attrData, (ds) => {
|
||||
let _ds = ds
|
||||
if (lodash.isString(ds)) {
|
||||
let [id, count, step] = ds.split(',')
|
||||
ds = { id, count, step }
|
||||
}
|
||||
let attrCfg = starCfg.sub[ds.id]
|
||||
if (!attrCfg) {
|
||||
console.log('not found attr', ds, _ds)
|
||||
return true
|
||||
}
|
||||
attrs.push({
|
||||
...ds,
|
||||
key: attrCfg?.key,
|
||||
value: attrCfg?.base * ds.count + attrCfg.step * ds.step
|
||||
})
|
||||
})
|
||||
return {
|
||||
main,
|
||||
attrs
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Artifact
|
||||
|
@ -1,21 +1,30 @@
|
||||
/*
|
||||
* 圣遗物套装
|
||||
* */
|
||||
import lodash from 'lodash'
|
||||
import Base from './Base.js'
|
||||
import { abbr, artiMap, artiSetMap } from '../resources/meta/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'
|
||||
|
||||
class ArtifactSet extends Base {
|
||||
constructor (name) {
|
||||
constructor (name, game = 'gs') {
|
||||
super()
|
||||
let cache = this._getCache(`arti-set:${name}`)
|
||||
let cache = this._getCache(`arti-set:${game}:${name}`)
|
||||
if (cache) {
|
||||
return cache
|
||||
}
|
||||
let data = artiSetMap[name]
|
||||
let data = (game === 'gs' ? artiSetMap : artiSetMapSR)[name]
|
||||
if (!data) {
|
||||
return false
|
||||
if (artiSetMapSR[name]) {
|
||||
data = artiSetMapSR[name]
|
||||
game = 'sr'
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
this.game = game
|
||||
this.meta = data
|
||||
return this._cache()
|
||||
}
|
||||
@ -33,24 +42,22 @@ class ArtifactSet extends Base {
|
||||
if (artiMap[name]) {
|
||||
return ArtifactSet.get(artiMap[name].set)
|
||||
}
|
||||
if (artiMapSR[name]) {
|
||||
return ArtifactSet.get(artiMap[name].set, 'sr')
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
static get (name) {
|
||||
if (artiSetMap[name]) {
|
||||
return new ArtifactSet(name)
|
||||
return new ArtifactSet(name, 'gs')
|
||||
}
|
||||
if (artiSetMapSR[name]) {
|
||||
return new ArtifactSet(name, 'sr')
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
getArtiName (idx = 1) {
|
||||
return this.sets[idx]
|
||||
}
|
||||
|
||||
getArti (idx = 1) {
|
||||
return Artifact.get(this.getArtiName(idx))
|
||||
}
|
||||
|
||||
static getArtiNameBySet (set, idx = 1) {
|
||||
let artiSet = ArtifactSet.get(set)
|
||||
if (artiSet) {
|
||||
@ -58,6 +65,22 @@ 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]
|
||||
}
|
||||
|
||||
getArti (idx = 1) {
|
||||
return Artifact.get(this.getArtiName(idx))
|
||||
}
|
||||
}
|
||||
|
||||
export default ArtifactSet
|
||||
|
@ -8,8 +8,9 @@ import { Format, Data } from '#miao'
|
||||
import ArtisMark from './profile/ArtisMark.js'
|
||||
|
||||
export default class AvatarArtis extends Base {
|
||||
constructor (charid = 0) {
|
||||
constructor (charid = 0, game = 'gs') {
|
||||
super()
|
||||
this.game = game
|
||||
this.charid = charid
|
||||
this.artis = {}
|
||||
}
|
||||
@ -27,12 +28,15 @@ export default class AvatarArtis extends Base {
|
||||
}
|
||||
|
||||
get hasAttr () {
|
||||
if (this.isSr) {
|
||||
return true
|
||||
}
|
||||
return ArtisMark.hasAttr(this.artis)
|
||||
}
|
||||
|
||||
static _eachArtisSet (sets, fn) {
|
||||
static _eachArtisSet (sets, fn, game = 'gs') {
|
||||
lodash.forEach(sets || [], (v, k) => {
|
||||
let artisSet = ArtifactSet.get(k)
|
||||
let artisSet = ArtifactSet.get(k, game)
|
||||
if (artisSet) {
|
||||
if (v >= 4) {
|
||||
fn(artisSet, 2)
|
||||
@ -42,44 +46,67 @@ export default class AvatarArtis extends Base {
|
||||
})
|
||||
}
|
||||
|
||||
static getArtisKeyTitle () {
|
||||
return ArtisMark.getKeyTitleMap()
|
||||
static getArtisKeyTitle (game = 'gs') {
|
||||
return ArtisMark.getKeyTitleMap(game)
|
||||
}
|
||||
|
||||
setArtisData (ds = {}, profile = false) {
|
||||
// let force = !this.hasArtis || ArtisMark.hasAttr(ds) || !ArtisMark.hasAttr(this.artis)
|
||||
if (!profile || (profile && ArtisMark.hasAttr(ds))) {
|
||||
for (let idx = 1; idx <= 5; idx++) {
|
||||
setArtisData (ds = {}, isProfile = false) {
|
||||
if (!isProfile || (isProfile && ArtisMark.hasAttr(ds))) {
|
||||
for (let idx = 1; idx <= (this.isGs ? 5 : 6); idx++) {
|
||||
if (ds[idx] || ds[`arti${idx}`]) {
|
||||
this.setArtis(idx, ds[idx] || ds[`arti${idx}`], profile)
|
||||
this.setArtis(idx, ds[idx] || ds[`arti${idx}`], isProfile)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setArtis (idx = 1, ds = {}, profile = false) {
|
||||
setArtis (idx = 1, ds = {}, isProfile = false) {
|
||||
idx = idx.toString().replace('arti', '')
|
||||
this.artis[idx] = this.artis[idx] || {}
|
||||
let arti = this.artis[idx]
|
||||
if (profile) {
|
||||
arti.name = ds._name || ds.name || arti.name || ''
|
||||
arti.set = ds._set || Artifact.getSetNameByArti(arti._name) || ds.set || ''
|
||||
arti.level = ds._level || ds.level || 1
|
||||
arti.star = ds._star || ds.star || 5
|
||||
arti.main = ds.main
|
||||
arti.attrs = ds.attrs
|
||||
return true
|
||||
}
|
||||
arti.name = ds.name || arti.name || ''
|
||||
arti.set = ds.set || Artifact.getSetNameByArti(arti.name) || ''
|
||||
arti.level = ds.level || 1
|
||||
arti.star = ds.star || 5
|
||||
let artiObj
|
||||
if (this.isSr) {
|
||||
artiObj = Artifact.get(ds.id, this.game)
|
||||
if (!artiObj) {
|
||||
return false
|
||||
}
|
||||
arti.id = artiObj.id || ds.id || arti.id || ''
|
||||
arti.name = artiObj.name || arti.name || ''
|
||||
arti.set = artiObj.setName || arti.set || ''
|
||||
arti.level = ds.level || arti.level || 1
|
||||
arti.star = artiObj.getStarById(ds.id) || arti.star || 5
|
||||
|
||||
if (ds.mainId || ds.main) {
|
||||
arti._name = ds._name || ds.name || arti._name || arti.name
|
||||
arti._set = ds._set || Artifact.getSetNameByArti(arti._name) || arti._set || ''
|
||||
arti._level = ds._level || ds.level || arti._level || arti.level
|
||||
arti._star = ds._star || ds.star || arti._star || arti.star || 5
|
||||
if (ds.mainId && ds.attrs) {
|
||||
let attr = artiObj.getAttrData(ds.mainId, ds.attrs, arti.level, arti.star, idx)
|
||||
if (attr) {
|
||||
arti.mainId = ds.mainId
|
||||
arti.main = attr.main || arti.main || {}
|
||||
arti.attrs = attr.attrs || arti.attrs || {}
|
||||
} else {
|
||||
console.log('attr id error', ds.main, ds.mainId, idx, arti.level, arti.star)
|
||||
}
|
||||
}
|
||||
return
|
||||
} else {
|
||||
if (isProfile) {
|
||||
arti.name = ds._name || ds.name || arti.name || ''
|
||||
arti.set = ds._set || Artifact.getSetNameByArti(arti._name) || ds.set || ''
|
||||
arti.level = ds._level || ds.level || 1
|
||||
arti.star = ds._star || ds.star || 5
|
||||
arti.main = ds.main
|
||||
arti.attrs = ds.attrs
|
||||
} else {
|
||||
arti.name = ds.name || arti.name || ''
|
||||
arti.set = ds.set || Artifact.getSetNameByArti(arti.name) || ''
|
||||
arti.level = ds.level || 1
|
||||
arti.star = ds.star || 5
|
||||
}
|
||||
if (ds.mainId || ds.main) {
|
||||
arti._name = ds._name || ds.name || arti._name || arti.name
|
||||
arti._set = ds._set || Artifact.getSetNameByArti(arti._name) || arti._set || ''
|
||||
arti._level = ds._level || ds.level || arti._level || arti.level
|
||||
arti._star = ds._star || ds.star || arti._star || arti.star || 5
|
||||
}
|
||||
}
|
||||
|
||||
// 存在面板数据,更新面板数据
|
||||
@ -120,14 +147,29 @@ export default class AvatarArtis extends Base {
|
||||
|
||||
toJSON () {
|
||||
let ret = {}
|
||||
for (let idx = 1; idx <= 5; idx++) {
|
||||
for (let idx = 1; idx <= (this.isGs ? 5 : 6); idx++) {
|
||||
let ds = this.artis[idx]
|
||||
if (ds) {
|
||||
let tmp = {
|
||||
name: ds.name || '',
|
||||
level: ds.level || 1,
|
||||
star: ds.star || 5
|
||||
}
|
||||
if (!ds) {
|
||||
continue
|
||||
}
|
||||
let tmp = {
|
||||
level: ds.level || 1,
|
||||
star: ds.star || 5
|
||||
}
|
||||
|
||||
if (this.isSr) {
|
||||
tmp.id = ds.id
|
||||
tmp.mainId = ds.main?.id
|
||||
tmp.attrs = []
|
||||
lodash.forEach(ds.attrs, (as) => {
|
||||
tmp.attrs.push([
|
||||
as?.id || '',
|
||||
as?.count || 1,
|
||||
as?.step || 0
|
||||
].join(','))
|
||||
})
|
||||
} else {
|
||||
tmp.name = ds.name || ''
|
||||
if ((ds.mainId && ds.attrIds) || (ds.main && ds.attrs)) {
|
||||
if ((ds._name && ds._name !== ds.name) || (ds._level && ds._level !== ds.level) || (ds._star && ds._star !== ds.star)) {
|
||||
tmp._name = ds._name || null
|
||||
@ -147,8 +189,8 @@ export default class AvatarArtis extends Base {
|
||||
}
|
||||
}
|
||||
}
|
||||
ret[idx] = tmp
|
||||
}
|
||||
ret[idx] = tmp
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@ -263,6 +305,6 @@ export default class AvatarArtis extends Base {
|
||||
}
|
||||
|
||||
eachArtisSet (fn) {
|
||||
AvatarArtis._eachArtisSet(this.sets, fn)
|
||||
AvatarArtis._eachArtisSet(this.sets, fn, this.game)
|
||||
}
|
||||
}
|
||||
|
@ -2,14 +2,14 @@ import lodash from 'lodash'
|
||||
import Base from './Base.js'
|
||||
import moment from 'moment'
|
||||
import { Character, AvatarArtis, ProfileData, Weapon } from './index.js'
|
||||
import { Data } from '#miao'
|
||||
import { Data, Format } from '#miao'
|
||||
import AttrCalc from './profile/AttrCalc.js'
|
||||
import Profile from './player/Profile.js'
|
||||
|
||||
const charKey = 'name,abbr,sName,star,imgs,face,side,gacha,weaponTypeName'.split(',')
|
||||
|
||||
export default class AvatarData extends Base {
|
||||
constructor (ds = {}, source) {
|
||||
constructor (ds = {}, game = 'gs') {
|
||||
super()
|
||||
let char = Character.get({ id: ds.id, elem: ds.elem })
|
||||
if (!char) {
|
||||
@ -17,8 +17,9 @@ export default class AvatarData extends Base {
|
||||
}
|
||||
this.id = char.id
|
||||
this.char = char
|
||||
this.game = char.game || game
|
||||
this.initArtis()
|
||||
this.setAvatar(ds, source)
|
||||
this.setAvatar(ds)
|
||||
}
|
||||
|
||||
get hasTalent () {
|
||||
@ -62,9 +63,10 @@ export default class AvatarData extends Base {
|
||||
return {
|
||||
enka: 'Enka.Network',
|
||||
miao: '喵喵Api',
|
||||
mgg: 'MiniGG-API',
|
||||
mgg: 'MiniGG-Api',
|
||||
hutao: 'Hutao-Enka',
|
||||
mys: '米游社'
|
||||
mys: '米游社',
|
||||
homo: 'Mihomo'
|
||||
}[this._source] || this._source
|
||||
}
|
||||
|
||||
@ -82,8 +84,8 @@ export default class AvatarData extends Base {
|
||||
return ''
|
||||
}
|
||||
|
||||
static create (ds, source) {
|
||||
let avatar = new AvatarData(ds)
|
||||
static create (ds, game = 'gs') {
|
||||
let avatar = new AvatarData(ds, game)
|
||||
if (!avatar) {
|
||||
return false
|
||||
}
|
||||
@ -91,7 +93,7 @@ export default class AvatarData extends Base {
|
||||
}
|
||||
|
||||
initArtis () {
|
||||
this.artis = new AvatarArtis(this.id)
|
||||
this.artis = new AvatarArtis(this.id, this.game)
|
||||
}
|
||||
|
||||
_get (key) {
|
||||
@ -122,11 +124,12 @@ export default class AvatarData extends Base {
|
||||
this._costume = ds.costume || this._costume || 0
|
||||
this.elem = ds.elem || this.elem || this.char.elem || ''
|
||||
this.promote = lodash.isUndefined(ds.promote) ? (this.promote || AttrCalc.calcPromote(this.level)) : (ds.promote || 0)
|
||||
|
||||
this._source = ds._source || ds.dataSource || this._source || ''
|
||||
this.trees = ds.trees || this.trees || []
|
||||
this._source = ds._source || this._source || ''
|
||||
this._time = ds._time || this._time || now
|
||||
this._update = ds._update || this._update || ds._time || now
|
||||
this._talent = ds._talent || this._talent || ds._time || now
|
||||
|
||||
// 存在数据源时更新时间
|
||||
if (source) {
|
||||
this._update = now
|
||||
@ -141,12 +144,13 @@ export default class AvatarData extends Base {
|
||||
}
|
||||
|
||||
setWeapon (ds = {}) {
|
||||
let w = Weapon.get(ds.name)
|
||||
let w = Weapon.get(ds.name || ds.id, this.game)
|
||||
if (!w) {
|
||||
return false
|
||||
}
|
||||
this.weapon = {
|
||||
name: ds.name,
|
||||
id: ds.id || w.id,
|
||||
name: ds.name || w.name,
|
||||
level: ds.level || ds.lv || 1,
|
||||
promote: lodash.isUndefined(ds.promote) ? AttrCalc.calcPromote(ds.level || ds.lv || 1) : (ds.promote || 0),
|
||||
affix: ds.affix,
|
||||
@ -157,6 +161,24 @@ export default class AvatarData extends Base {
|
||||
}
|
||||
}
|
||||
|
||||
getWeaponDetail () {
|
||||
if (this.isGs) {
|
||||
return this.weapon
|
||||
}
|
||||
let ret = {
|
||||
...this.weapon
|
||||
}
|
||||
let wData = Weapon.get(ret.id, this.game)
|
||||
ret.splash = wData.imgs.gacha
|
||||
let attrs = wData.calcAttr(ret.level, ret.promote)
|
||||
lodash.forEach(attrs, (val, key) => {
|
||||
attrs[key] = Format.comma(val, 1)
|
||||
})
|
||||
ret.attrs = attrs
|
||||
ret.desc = wData.getAffixDesc(ret.affix)
|
||||
return ret
|
||||
}
|
||||
|
||||
setTalent (ds = false, mode = 'original', updateTime = '') {
|
||||
const now = this._now || (new Date()) * 1
|
||||
if (ds) {
|
||||
@ -180,7 +202,7 @@ export default class AvatarData extends Base {
|
||||
if (!this.isProfile) {
|
||||
return false
|
||||
}
|
||||
return ProfileData.create(this)
|
||||
return ProfileData.create(this, this.game)
|
||||
}
|
||||
|
||||
// 判断当前profileData是否具备有效圣遗物信息
|
||||
@ -190,18 +212,28 @@ export default class AvatarData extends Base {
|
||||
|
||||
// toJSON 供保存使用
|
||||
toJSON () {
|
||||
let keys = this.isGs ?
|
||||
'name,id,elem,level,promote,fetter,costume,cons,talent:originalTalent' :
|
||||
'name,id,elem,level,promote,cons,talent:originalTalent,trees'
|
||||
return {
|
||||
...this.getData('name,id,elem,level,promote,fetter,costume,cons,talent:originalTalent'),
|
||||
weapon: Data.getData(this.weapon, 'name,level,promote,affix'),
|
||||
...this.getData(keys),
|
||||
weapon: Data.getData(this.weapon, this.isGs ? 'name,level,promote,affix' : 'id,level,promote,affix'),
|
||||
...this.getData('artis,_source,_time,_update,_talent')
|
||||
}
|
||||
}
|
||||
|
||||
getDetail (keys = '') {
|
||||
let imgs = this.char.getImgs(this.costume)
|
||||
return {
|
||||
...(this.getData(keys || 'id,name,level,star,cons,fetter,elem,abbr,weapon,talent,artisSet') || {}),
|
||||
...Data.getData(imgs, 'face,qFace,side,gacha')
|
||||
if (this.isGs) {
|
||||
return {
|
||||
...(this.getData(keys || 'id,name,level,star,cons,fetter,elem,abbr,weapon,talent,artisSet') || {}),
|
||||
...Data.getData(imgs, 'face,qFace,side,gacha')
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
...(this.getData(keys || 'id,name,level,star,cons,elem,abbr,weapon,talent,artisSet,trees') || {}),
|
||||
...Data.getData(imgs, 'face,qFace,gacha,preview')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ let metaMap = {}
|
||||
|
||||
export default class Base {
|
||||
constructor () {
|
||||
this.game = 'gs'
|
||||
let proxy = new Proxy(this, {
|
||||
get (self, key, receiver) {
|
||||
if (self._uuid && key === 'meta') {
|
||||
@ -92,4 +93,12 @@ export default class Base {
|
||||
delete cacheMap[id]
|
||||
delete metaMap[id]
|
||||
}
|
||||
|
||||
get isSr () {
|
||||
return this.game === 'sr'
|
||||
}
|
||||
|
||||
get isGs () {
|
||||
return !this.isSr
|
||||
}
|
||||
}
|
||||
|
@ -15,15 +15,19 @@ import CharCfg from './character/CharCfg.js'
|
||||
|
||||
let { wifeMap, idSort, idMap } = CharId
|
||||
|
||||
let getMeta = function (name) {
|
||||
return Data.readJSON(`resources/meta/character/${name}/data.json`, 'miao')
|
||||
let getMeta = function (name, game = 'gs') {
|
||||
if (game === 'gs') {
|
||||
return Data.readJSON(`resources/meta/character/${name}/data.json`, 'miao')
|
||||
} else {
|
||||
return CharId.getSrMeta(name)
|
||||
}
|
||||
}
|
||||
|
||||
class Character extends Base {
|
||||
// 默认获取的数据
|
||||
_dataKey = 'id,name,abbr,title,star,elem,allegiance,weapon,birthday,astro,cncv,jpcv,ver,desc,talentCons'
|
||||
|
||||
constructor ({ id, name = '', elem = '' }) {
|
||||
constructor ({ id, name = '', elem = '', game = 'gs' }) {
|
||||
super()
|
||||
// 检查缓存
|
||||
let cacheObj = this._getCache(CharId.isTraveler(id) ? `character:${id}:${elem || 'anemo'}` : `character:${id}`)
|
||||
@ -33,10 +37,13 @@ class Character extends Base {
|
||||
// 设置数据
|
||||
this._id = id
|
||||
this.name = name
|
||||
this.game = game
|
||||
if (!this.isCustom) {
|
||||
let meta = getMeta(name)
|
||||
let meta = getMeta(name, game)
|
||||
this.meta = meta
|
||||
this.elem = Format.elem(elem || meta.elem, 'anemo')
|
||||
if (this.isGs) {
|
||||
this.elem = Format.elem(elem || meta.elem, 'anemo')
|
||||
}
|
||||
} else {
|
||||
this.meta = {}
|
||||
}
|
||||
@ -45,7 +52,7 @@ class Character extends Base {
|
||||
|
||||
// 是否为官方角色
|
||||
get isOfficial () {
|
||||
return /[12]0\d{6}/.test(this._id)
|
||||
return this.game === 'sr' || /[12]0\d{6}/.test(this._id)
|
||||
}
|
||||
|
||||
// 是否为实装官方角色
|
||||
@ -61,13 +68,21 @@ class Character extends Base {
|
||||
|
||||
// 是否为自定义角色
|
||||
get isCustom () {
|
||||
return !/[12]0\d{6}/.test(this._id)
|
||||
return !this.isOfficial
|
||||
}
|
||||
|
||||
get id () {
|
||||
return this.isCustom ? this._id : this._id * 1
|
||||
}
|
||||
|
||||
get isGs () {
|
||||
return this.game === 'gs'
|
||||
}
|
||||
|
||||
get isSr () {
|
||||
return this.game === 'sr'
|
||||
}
|
||||
|
||||
// 获取短名字
|
||||
get sName () {
|
||||
let name = this.name
|
||||
@ -77,7 +92,7 @@ class Character extends Base {
|
||||
|
||||
// 是否是旅行者
|
||||
get isTraveler () {
|
||||
return CharId.isTraveler(this.id)
|
||||
return this.isGs && CharId.isTraveler(this.id)
|
||||
}
|
||||
|
||||
get weaponType () {
|
||||
@ -86,6 +101,9 @@ class Character extends Base {
|
||||
|
||||
// 获取武器类型
|
||||
get weaponTypeName () {
|
||||
if (this.isSr) {
|
||||
return this.weapon
|
||||
}
|
||||
const map = {
|
||||
sword: '单手剑',
|
||||
catalyst: '法器',
|
||||
@ -99,6 +117,9 @@ class Character extends Base {
|
||||
|
||||
// 获取元素名称
|
||||
get elemName () {
|
||||
if (this.isSr) {
|
||||
return this.elem
|
||||
}
|
||||
return Format.elemName(this.elem)
|
||||
}
|
||||
|
||||
@ -114,6 +135,9 @@ class Character extends Base {
|
||||
|
||||
// 获取侧脸图像
|
||||
get side () {
|
||||
if (this.isSr) {
|
||||
return this.getImgs().face
|
||||
}
|
||||
return this.getImgs().side
|
||||
}
|
||||
|
||||
@ -134,6 +158,9 @@ class Character extends Base {
|
||||
|
||||
// 获取命座天赋等级
|
||||
get talentCons () {
|
||||
if (this.isSr) {
|
||||
return this.meta?.talentCons || {}
|
||||
}
|
||||
if (this.isTraveler) {
|
||||
return this.elem === 'dendro' ? { e: 3, q: 5 } : { e: 5, q: 3 }
|
||||
}
|
||||
@ -151,17 +178,20 @@ class Character extends Base {
|
||||
}
|
||||
|
||||
// 基于角色名获取Character
|
||||
static get (val) {
|
||||
let id = CharId.getId(val, Character.gsCfg)
|
||||
static get (val, game = 'gs') {
|
||||
let id = CharId.getId(val, Character.gsCfg, game)
|
||||
if (!id) {
|
||||
return false
|
||||
}
|
||||
return new Character(id)
|
||||
}
|
||||
|
||||
static forEach (fn, type = 'all') {
|
||||
static forEach (fn, type = 'all', game = 'gs') {
|
||||
lodash.forEach(idMap, (name, id) => {
|
||||
let char = Character.get({ id, name })
|
||||
if (char.game !== 'game') {
|
||||
return true
|
||||
}
|
||||
if (type === 'release' && !char.isRelease) {
|
||||
return true
|
||||
}
|
||||
@ -196,10 +226,26 @@ class Character extends Base {
|
||||
return CharImg.getCardImg(this.name, se, def)
|
||||
}
|
||||
|
||||
// 设置旅行者数据
|
||||
|
||||
// 设置天赋数据
|
||||
getAvatarTalent (talent = {}, cons = 0, mode = 'original') {
|
||||
return CharTalent.getAvatarTalent(this.id, talent, cons, mode, this.talentCons)
|
||||
return CharTalent.getAvatarTalent(this, talent, cons, mode)
|
||||
}
|
||||
|
||||
getTalentKey (id) {
|
||||
if (this.talentId[id]) {
|
||||
return this.talentId[id]
|
||||
}
|
||||
if (this.isSr) {
|
||||
id = (id + '').replace(this.id, '')
|
||||
return {
|
||||
'001': 'a',
|
||||
'002': 'e',
|
||||
'003': 'q',
|
||||
'004': 't',
|
||||
'007': 'z'
|
||||
}[id]
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查老婆类型
|
||||
@ -230,12 +276,16 @@ class Character extends Base {
|
||||
this._imgs = {}
|
||||
}
|
||||
if (!this._imgs[cacheId]) {
|
||||
this._imgs[cacheId] = CharImg.getImgs(this.name, costumeIdx, this.isTraveler ? this.elem : '', this.weaponType, this.talentCons)
|
||||
if (this.isSr) {
|
||||
this._imgs[cacheId] = CharImg.getImgsSr(this.name, this.talentCons)
|
||||
} else {
|
||||
this._imgs[cacheId] = CharImg.getImgs(this.name, costumeIdx, this.isTraveler ? this.elem : '', this.weaponType, this.talentCons)
|
||||
}
|
||||
}
|
||||
let imgs = this._imgs[cacheId]
|
||||
return {
|
||||
...imgs,
|
||||
qFace: Cfg.get('qFace') ? imgs.qFace : imgs.face
|
||||
qFace: Cfg.get('qFace') ? (imgs.qFace || imgs.face) : imgs.face
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,13 +299,14 @@ class Character extends Base {
|
||||
if (this.isCustom) {
|
||||
return {}
|
||||
}
|
||||
const path = 'resources/meta/character'
|
||||
const path = this.isSr ? 'resources/meta-sr/character' : 'resources/meta/character'
|
||||
const file = this.isSr ? 'data' : 'detail'
|
||||
|
||||
try {
|
||||
if (this.isTraveler) {
|
||||
this._detail = Data.readJSON(`${path}/旅行者/${this.elem}/detail.json`, 'miao')
|
||||
this._detail = Data.readJSON(`${path}/旅行者/${this.elem}/${file}.json`, 'miao')
|
||||
} else {
|
||||
this._detail = Data.readJSON(`${path}/${this.name}/detail.json`, 'miao')
|
||||
this._detail = Data.readJSON(`${path}/${this.name}/${file}.json`, 'miao')
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
@ -277,6 +328,31 @@ class Character extends Base {
|
||||
}
|
||||
return this._artisRule
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取等级属性
|
||||
* @param level
|
||||
* @param promote
|
||||
* @returns {{}|boolean}
|
||||
*/
|
||||
getLvAttr (level, promote) {
|
||||
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(lvAttr.grow, (v, k) => {
|
||||
ret[k] = ret[k] * 1 + v * (level - 1)
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Character.CharId = CharId
|
||||
|
@ -13,19 +13,22 @@ import MysAvatar from './player/MysAvatar.js'
|
||||
import Profile from './player/Profile.js'
|
||||
|
||||
Data.createDir('/data/UserData', 'root')
|
||||
Data.createDir('/data/PlayerData/gs', 'root')
|
||||
Data.createDir('/data/PlayerData/sr', 'root')
|
||||
|
||||
export default class Player extends Base {
|
||||
constructor (uid) {
|
||||
constructor (uid, game = 'gs') {
|
||||
super()
|
||||
uid = uid?._mys?.uid || uid?.uid || uid
|
||||
if (!uid) {
|
||||
return false
|
||||
}
|
||||
let cacheObj = this._getCache(`player:${uid}`)
|
||||
let cacheObj = this._getCache(`player:${game}:${uid}`)
|
||||
if (cacheObj) {
|
||||
return cacheObj
|
||||
}
|
||||
this.uid = uid
|
||||
this.game = game
|
||||
this.reload()
|
||||
return this._cache(100)
|
||||
}
|
||||
@ -41,25 +44,33 @@ export default class Player extends Base {
|
||||
return ret
|
||||
}
|
||||
|
||||
static create (e) {
|
||||
get _file () {
|
||||
if (this.isSr) {
|
||||
return `/data/PlayerData/sr/${this.uid}.json`
|
||||
} else {
|
||||
return `/data/UserData/${this.uid}.json`
|
||||
}
|
||||
}
|
||||
|
||||
static create (e, game = 'gs') {
|
||||
if (e?._mys?.uid || e.uid) {
|
||||
// 传入为e
|
||||
let player = new Player(e?._mys?.uid || e.uid)
|
||||
let player = new Player(e?._mys?.uid || e.uid, (game === 'sr' || e.isSr) ? 'sr' : 'gs')
|
||||
player.e = e
|
||||
return player
|
||||
} else {
|
||||
return new Player(e)
|
||||
return new Player(e, game)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取面板更新服务名
|
||||
static getProfileServName (uid) {
|
||||
let Serv = Profile.getServ(uid)
|
||||
static getProfileServName (uid, game = 'gs') {
|
||||
let Serv = Profile.getServ(uid, game)
|
||||
return Serv.name
|
||||
}
|
||||
|
||||
static delByUid (uid) {
|
||||
let player = Player.create(uid)
|
||||
static delByUid (uid, game = 'gs') {
|
||||
let player = Player.create(uid, game)
|
||||
if (player) {
|
||||
player.del()
|
||||
}
|
||||
@ -70,7 +81,7 @@ export default class Player extends Base {
|
||||
*/
|
||||
reload () {
|
||||
let data
|
||||
data = Data.readJSON(`/data/UserData/${this.uid}.json`, 'root')
|
||||
data = Data.readJSON(this._file, 'root')
|
||||
this.setBasicData(data)
|
||||
if (data.chars) {
|
||||
this.setAvatars(data.chars)
|
||||
@ -104,13 +115,17 @@ export default class Player extends Base {
|
||||
if (this._ck) {
|
||||
ret._ck = this._ck
|
||||
}
|
||||
Data.writeJSON(`/data/UserData/${this.uid}.json`, ret, 'root')
|
||||
if (this.isSr) {
|
||||
Data.writeJSON(`/data/PlayerData/sr/${this.uid}.json`, ret, 'root')
|
||||
} else {
|
||||
Data.writeJSON(`/data/UserData/${this.uid}.json`, ret, 'root')
|
||||
}
|
||||
}
|
||||
|
||||
del () {
|
||||
try {
|
||||
Data.delFile(`/data/UserData/${this.uid}.json`, 'root')
|
||||
ProfileRank.delUidInfo(this.uid)
|
||||
Data.delFile(this._file, 'root')
|
||||
ProfileRank.delUidInfo(this.uid, this.game)
|
||||
this._delCache()
|
||||
Bot.logger.mark(`【面板数据删除】${this.uid}本地文件数据已删除...`)
|
||||
} catch (e) {
|
||||
@ -154,12 +169,14 @@ export default class Player extends Base {
|
||||
getAvatar (id, create = false) {
|
||||
let char = Character.get(id)
|
||||
let avatars = this._avatars
|
||||
// 兼容处理旅行者的情况
|
||||
if (char.isTraveler && !create) {
|
||||
id = avatars['10000005'] ? 10000005 : 10000007
|
||||
if (this.isGs) {
|
||||
// 兼容处理旅行者的情况
|
||||
if (char.isTraveler && !create) {
|
||||
id = avatars['10000005'] ? 10000005 : 10000007
|
||||
}
|
||||
}
|
||||
if (!avatars[id] && create) {
|
||||
avatars[id] = AvatarData.create({ id })
|
||||
avatars[id] = AvatarData.create({ id }, this.game)
|
||||
}
|
||||
return avatars[id] || false
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ import { attrMap } from '../resources/meta/artifact/index.js'
|
||||
import CharArtis from './profile/CharArtis.js'
|
||||
|
||||
export default class ProfileArtis extends AvatarArtis {
|
||||
constructor (charid = 0, elem = '') {
|
||||
super(charid)
|
||||
constructor (charid = 0, elem = '', game = 'gs') {
|
||||
super(charid, game)
|
||||
this.elem = elem
|
||||
}
|
||||
|
||||
@ -67,15 +67,16 @@ export default class ProfileArtis extends AvatarArtis {
|
||||
let artis = {}
|
||||
let setCount = {}
|
||||
let totalMark = 0
|
||||
let totalCrit = 0
|
||||
let totalVaild = 0
|
||||
let self = this
|
||||
this.forEach((arti, idx) => {
|
||||
let mark = ArtisMark.getMark(charCfg, idx, arti.main, arti.attrs, this.elem)
|
||||
let crit = ArtisMark.getCritMark(charCfg, idx, arti.main, arti.attrs, this.elem)
|
||||
let vaild = ArtisMark.getValidMark(charCfg, idx, arti.main, arti.attrs, this.elem)
|
||||
let mark = ArtisMark.getMark({
|
||||
charCfg,
|
||||
idx,
|
||||
arti,
|
||||
elem: this.elem,
|
||||
game: self.game
|
||||
})
|
||||
totalMark += mark
|
||||
totalCrit += crit
|
||||
totalVaild += vaild
|
||||
setCount[arti.set] = (setCount[arti.set] || 0) + 1
|
||||
if (!withDetail) {
|
||||
artis[idx] = {
|
||||
@ -84,17 +85,18 @@ export default class ProfileArtis extends AvatarArtis {
|
||||
markClass: ArtisMark.getMarkClass(mark)
|
||||
}
|
||||
} else {
|
||||
let artifact = Artifact.get(arti.name)
|
||||
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,
|
||||
_mark: mark,
|
||||
mark: Format.comma(mark, 1),
|
||||
markClass: ArtisMark.getMarkClass(mark),
|
||||
main: ArtisMark.formatArti(arti.main, charCfg.attrs, true, this.elem || ''),
|
||||
attrs: ArtisMark.formatArti(arti.attrs, charCfg.attrs)
|
||||
main: ArtisMark.formatArti(arti.main, charCfg.attrs, true, this.game),
|
||||
attrs: ArtisMark.formatArti(arti.attrs, charCfg.attrs, false, this.game)
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -114,10 +116,10 @@ export default class ProfileArtis extends AvatarArtis {
|
||||
let ret = {
|
||||
mark: Format.comma(totalMark, 1),
|
||||
_mark: totalMark,
|
||||
crit: Format.comma(totalCrit, 1),
|
||||
/* crit: Format.comma(totalCrit, 1),
|
||||
_crit: totalCrit,
|
||||
valid: Format.comma(totalVaild, 1),
|
||||
_valid: totalVaild,
|
||||
_valid: totalVaild, */
|
||||
markClass: ArtisMark.getMarkClass(totalMark / 5),
|
||||
artis,
|
||||
sets,
|
||||
|
@ -1,17 +1,26 @@
|
||||
import lodash from 'lodash'
|
||||
import Base from './Base.js'
|
||||
import { Format } from '#miao'
|
||||
|
||||
const baseAttr = 'atk,def,hp,mastery,recharge,cpct,cdmg,dmg,phy,heal,shield'.split(',')
|
||||
let attrReg = new RegExp(`^(${baseAttr.join('|')})(Base|Plus|Pct|Inc)$`)
|
||||
const baseAttr = {
|
||||
gs: 'atk,def,hp,mastery,recharge,cpct,cdmg,dmg,phy,heal,shield'.split(','),
|
||||
sr: 'atk,def,hp,speed,recharge,cpct,cdmg,dmg,heal,stance,effPct,effDmg'.split(',')
|
||||
}
|
||||
let attrReg = {
|
||||
gs: new RegExp(`^(${baseAttr.gs.join('|')})(Base|Plus|Pct|Inc)$`),
|
||||
sr: new RegExp(`^(${baseAttr.sr.join('|')})(Base|Plus|Pct|Inc)$`)
|
||||
}
|
||||
|
||||
class ProfileAttr extends Base {
|
||||
constructor (data = null) {
|
||||
constructor (char, data = null) {
|
||||
super()
|
||||
this.init(data)
|
||||
this.char = char
|
||||
this.game = char.game
|
||||
this.init(data, this.game)
|
||||
}
|
||||
|
||||
static create (data = null) {
|
||||
return new ProfileAttr(data)
|
||||
static create (char, data = null) {
|
||||
return new ProfileAttr(char, data)
|
||||
}
|
||||
|
||||
init (data) {
|
||||
@ -20,7 +29,7 @@ class ProfileAttr extends Base {
|
||||
this._base = {}
|
||||
let attr = this._attr
|
||||
let base = this._base
|
||||
lodash.forEach(baseAttr, (key) => {
|
||||
lodash.forEach(baseAttr[this.game], (key) => {
|
||||
attr[key] = {
|
||||
base: 0,
|
||||
plus: 0,
|
||||
@ -28,6 +37,7 @@ class ProfileAttr extends Base {
|
||||
}
|
||||
base[key] = 0
|
||||
})
|
||||
|
||||
if (data) {
|
||||
this.setAttr(data, true)
|
||||
}
|
||||
@ -42,12 +52,12 @@ class ProfileAttr extends Base {
|
||||
*/
|
||||
_get (key) {
|
||||
let attr = this._attr
|
||||
if (baseAttr.includes(key)) {
|
||||
if (baseAttr[this.game].includes(key)) {
|
||||
let a = attr[key]
|
||||
return a.base * (1 + a.pct / 100) + a.plus
|
||||
}
|
||||
|
||||
let testRet = attrReg.exec(key)
|
||||
let testRet = attrReg[this.game].exec(key)
|
||||
if (testRet && testRet[1] && testRet[2]) {
|
||||
let key = testRet[1]
|
||||
let key2 = testRet[2].toLowerCase()
|
||||
@ -59,13 +69,20 @@ class ProfileAttr extends Base {
|
||||
* 添加或追加Attr数据
|
||||
* @param key
|
||||
* @param val
|
||||
* @param base
|
||||
* @param isBase
|
||||
* @returns {boolean}
|
||||
*/
|
||||
addAttr (key, val, isBase = false) {
|
||||
let attr = this._attr
|
||||
let base = this._base
|
||||
if (baseAttr.includes(key)) {
|
||||
|
||||
if (this.isSr && Format.isElem(key, this.game)) {
|
||||
if (Format.sameElem(this.char.elem, key, this.game)) {
|
||||
key = 'dmg'
|
||||
}
|
||||
}
|
||||
|
||||
if (baseAttr[this.game].includes(key)) {
|
||||
attr[key].plus += val * 1
|
||||
if (isBase) {
|
||||
base[key] = (base[key] || 0) + val * 1
|
||||
@ -73,7 +90,7 @@ class ProfileAttr extends Base {
|
||||
return true
|
||||
}
|
||||
|
||||
let testRet = attrReg.exec(key)
|
||||
let testRet = attrReg[this.game].exec(key)
|
||||
if (testRet && testRet[1] && testRet[2]) {
|
||||
let key = testRet[1]
|
||||
let key2 = testRet[2].toLowerCase()
|
||||
@ -103,13 +120,19 @@ class ProfileAttr extends Base {
|
||||
})
|
||||
}
|
||||
lodash.forEach(data, (val, key) => {
|
||||
this.addAttr(key, val)
|
||||
if (this.isSr && Format.isElem(key, this.game)) {
|
||||
if (this.char.elem === Format.elem(key, '', this.game)) {
|
||||
this.addAttr('dmg', val)
|
||||
}
|
||||
} else {
|
||||
this.addAttr(key, val)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getAttr () {
|
||||
let ret = {}
|
||||
lodash.forEach(baseAttr, (key) => {
|
||||
lodash.forEach(baseAttr[this.game], (key) => {
|
||||
ret[key] = this[key]
|
||||
if (['hp', 'atk', 'def'].includes(key)) {
|
||||
ret[`${key}Base`] = this[`${key}Base`]
|
||||
|
@ -6,8 +6,8 @@ import AttrCalc from './profile/AttrCalc.js'
|
||||
import CharImg from './character/CharImg.js'
|
||||
|
||||
export default class ProfileData extends AvatarData {
|
||||
constructor (ds = {}, calc = true) {
|
||||
super(ds)
|
||||
constructor (ds = {}, game = 'gs', calc = true) {
|
||||
super(ds, game)
|
||||
if (calc) {
|
||||
this.calcAttr()
|
||||
}
|
||||
@ -50,11 +50,11 @@ 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) {
|
||||
let profile = new ProfileData(ds)
|
||||
static create (ds, game = 'gs') {
|
||||
let profile = new ProfileData(ds, game)
|
||||
if (!profile) {
|
||||
return false
|
||||
}
|
||||
@ -62,7 +62,7 @@ export default class ProfileData extends AvatarData {
|
||||
}
|
||||
|
||||
initArtis () {
|
||||
this.artis = new ProfileArtis(this.id, this.elem)
|
||||
this.artis = new ProfileArtis(this.id, this.elem, this.game)
|
||||
}
|
||||
|
||||
setAttr (ds) {
|
||||
@ -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 })
|
||||
}
|
||||
|
@ -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,8 @@ export default class ProfileDmg extends Base {
|
||||
return false
|
||||
}
|
||||
let { profile } = this
|
||||
let { game } = this.char
|
||||
let sp = this.detail?.sp
|
||||
let charCalcData = await this.getCalcRule()
|
||||
|
||||
if (!charCalcData) {
|
||||
@ -123,13 +116,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, sp })
|
||||
|
||||
buffs = this.getBuffs(buffs)
|
||||
|
||||
@ -173,7 +168,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 +204,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 +225,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({
|
||||
|
@ -2,20 +2,21 @@ import Base from './Base.js'
|
||||
import fetch from 'node-fetch'
|
||||
|
||||
export default class ProfileReq extends Base {
|
||||
constructor (e) {
|
||||
constructor (e, game = 'gs') {
|
||||
super()
|
||||
this.e = e
|
||||
this.game = game
|
||||
this.uid = e.uid
|
||||
}
|
||||
|
||||
static create (e) {
|
||||
static create (e, game = 'gs') {
|
||||
if (!e || !e.uid) {
|
||||
return false
|
||||
}
|
||||
if (e.uid * 1 < 100000005) {
|
||||
return false
|
||||
}
|
||||
return new ProfileReq(e)
|
||||
return new ProfileReq(e, game)
|
||||
}
|
||||
|
||||
async setCd (seconds = 60) {
|
||||
@ -67,10 +68,10 @@ export default class ProfileReq extends Base {
|
||||
let self = this
|
||||
this.serv = serv
|
||||
let uid = this.uid
|
||||
let reqParam = await serv.getReqParam(uid)
|
||||
let reqParam = await serv.getReqParam(uid, self.game)
|
||||
let cdTime = await this.inCd()
|
||||
if (cdTime && !process.argv.includes('web-debug')) {
|
||||
return this.err(`请求过快,请${cdTime}秒后重试..`)
|
||||
// return this.err(`请求过快,请${cdTime}秒后重试..`)
|
||||
}
|
||||
await this.setCd(20)
|
||||
// 若3秒后还未响应则返回提示
|
||||
@ -107,7 +108,7 @@ export default class ProfileReq extends Base {
|
||||
self._isReq = false
|
||||
data = {}
|
||||
}
|
||||
data = await serv.response(data, this)
|
||||
data = await serv.response(data, this, self.game)
|
||||
// 设置CD
|
||||
cdTime = serv.getCdTime(data)
|
||||
if (cdTime) {
|
||||
|
@ -31,14 +31,15 @@ export default class ProfileServ extends Base {
|
||||
}
|
||||
|
||||
// 请求当前面板服务
|
||||
async getReqParam (uid) {
|
||||
async getReqParam (uid, game = 'gs') {
|
||||
let url = this.getCfg('url')
|
||||
let profileApi = this.getCfg('listApi')
|
||||
let cfg = this._cfg
|
||||
let api = profileApi({
|
||||
url,
|
||||
uid: uid,
|
||||
diyCfg: this.diyCfg
|
||||
diyCfg: this.diyCfg,
|
||||
game
|
||||
})
|
||||
let param = {}
|
||||
|
||||
@ -53,11 +54,11 @@ export default class ProfileServ extends Base {
|
||||
}
|
||||
}
|
||||
|
||||
async response (data, req) {
|
||||
async response (data, req, game = 'gs') {
|
||||
// 处理返回
|
||||
let cfg = this._cfg
|
||||
if (cfg.response) {
|
||||
return await cfg.response.call(this, data, req)
|
||||
return await cfg.response.call(this, data, req, game)
|
||||
}
|
||||
}
|
||||
|
||||
|
175
models/Weapon.js
@ -1,16 +1,22 @@
|
||||
import Base from './Base.js'
|
||||
import { Data } from '#miao'
|
||||
import { weaponData, weaponAbbr, weaponAlias, weaponType, weaponSet } from '../resources/meta/weapon/index.js'
|
||||
import { Data, Format } from '#miao'
|
||||
import { weaponData, weaponAbbr, weaponAlias, weaponType, weaponSet, weaponBuffs } from '../resources/meta/weapon/index.js'
|
||||
import {
|
||||
weaponData as weaponDataSR,
|
||||
weaponAlias as weaponAliasSR,
|
||||
weaponBuffs as weaponBuffsSR
|
||||
} from '../resources/meta-sr/weapon/index.js'
|
||||
|
||||
import lodash from 'lodash'
|
||||
|
||||
class Weapon extends Base {
|
||||
constructor (name) {
|
||||
constructor (name, game = 'gs') {
|
||||
super(name)
|
||||
let meta = weaponData[name]
|
||||
let meta = game === 'gs' ? weaponData[name] : weaponDataSR[name]
|
||||
if (!meta) {
|
||||
return false
|
||||
}
|
||||
let cache = this._getCache(`weapon:${name}`)
|
||||
let cache = this._getCache(`weapon:${game}:${name}`)
|
||||
if (cache) {
|
||||
return cache
|
||||
}
|
||||
@ -19,6 +25,7 @@ class Weapon extends Base {
|
||||
this.meta = meta
|
||||
this.type = meta.type
|
||||
this.star = meta.star
|
||||
this.game = game
|
||||
return this._cache()
|
||||
}
|
||||
|
||||
@ -31,14 +38,22 @@ class Weapon extends Base {
|
||||
}
|
||||
|
||||
get img () {
|
||||
return `meta/weapon/${this.type}/${this.name}/icon.webp`
|
||||
return `${this.isGs ? 'meta' : 'meta-sr'}/weapon/${this.type}/${this.name}/icon.webp`
|
||||
}
|
||||
|
||||
get imgs () {
|
||||
return {
|
||||
icon: `meta/weapon/${this.type}/${this.name}/icon.webp`,
|
||||
icon2: `meta/weapon/${this.type}/${this.name}/awaken.webp`,
|
||||
gacha: `meta/weapon/${this.type}/${this.name}/gacha.webp`
|
||||
if (this.isGs) {
|
||||
return {
|
||||
icon: `meta/weapon/${this.type}/${this.name}/icon.webp`,
|
||||
icon2: `meta/weapon/${this.type}/${this.name}/awaken.webp`,
|
||||
gacha: `meta/weapon/${this.type}/${this.name}/gacha.webp`
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
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`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,12 +82,13 @@ class Weapon extends Base {
|
||||
return weaponSet.includes(name)
|
||||
}
|
||||
|
||||
static get (name, type = '') {
|
||||
static get (name, game = 'gs', type = '') {
|
||||
name = lodash.trim(name)
|
||||
if (weaponAlias[name]) {
|
||||
return new Weapon(weaponAlias[name])
|
||||
let alias = game === 'gs' ? weaponAlias : weaponAliasSR
|
||||
if (alias[name]) {
|
||||
return new Weapon(alias[name], game)
|
||||
}
|
||||
if (type) {
|
||||
if (type && game === 'gs') {
|
||||
let name2 = name + (weaponType[type] || type)
|
||||
if (weaponAlias[name2]) {
|
||||
return new Weapon(weaponAlias[name2])
|
||||
@ -96,7 +112,7 @@ class Weapon extends Base {
|
||||
if (this._detail) {
|
||||
return this._detail
|
||||
}
|
||||
const path = 'resources/meta/weapon'
|
||||
const path = this.isGs ? 'resources/meta/weapon' : 'resources/meta-sr/weapon'
|
||||
try {
|
||||
this._detail = Data.readJSON(`${path}/${this.type}/${this.name}/data.json`, 'miao')
|
||||
} catch (e) {
|
||||
@ -106,6 +122,22 @@ class Weapon extends Base {
|
||||
}
|
||||
|
||||
calcAttr (level, promote = -1) {
|
||||
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
|
||||
}
|
||||
|
||||
let lvLeft = 1
|
||||
let lvRight = 20
|
||||
let lvStep = [1, 20, 40, 50, 60, 70, 80, 90]
|
||||
@ -140,22 +172,105 @@ class Weapon extends Base {
|
||||
}
|
||||
}
|
||||
|
||||
getAffixInfo (affix) {
|
||||
let d = this.getDetail()
|
||||
let ad = this.detail.affixData
|
||||
let txt = ad.text
|
||||
lodash.forEach(ad.datas, (ds, idx) => {
|
||||
txt = txt.replace(`$[${idx}]`, ds[affix - 1])
|
||||
})
|
||||
return {
|
||||
name: d.name,
|
||||
star: d.star,
|
||||
desc: d.desc,
|
||||
imgs: this.imgs,
|
||||
affix,
|
||||
affixTitle: d.affixTitle,
|
||||
affixDetail: txt
|
||||
// 获取精炼描述
|
||||
getAffixDesc (affix = 1) {
|
||||
let skill = this.detail.skill
|
||||
let { name, desc, tables } = skill
|
||||
let reg = /\$(\d)\[[i|f1]\](\%?)/g
|
||||
let ret
|
||||
while ((ret = reg.exec(desc)) !== null) {
|
||||
let idx = ret[1]
|
||||
let pct = ret[2]
|
||||
let value = tables?.[idx]?.[affix - 1]
|
||||
if (pct === '%') {
|
||||
value = Format.pct(value)
|
||||
} else {
|
||||
value = Format.comma(value)
|
||||
}
|
||||
desc = desc.replaceAll(ret[0], value)
|
||||
}
|
||||
return {
|
||||
name: skill.name,
|
||||
desc
|
||||
}
|
||||
}
|
||||
|
||||
getWeaponBuffs () {
|
||||
let { isSr } = this
|
||||
let wBuffs = (isSr ? weaponBuffsSR : weaponBuffs)
|
||||
let buffs = wBuffs[this.id] || wBuffs[this.name]
|
||||
if (!buffs) {
|
||||
return false
|
||||
}
|
||||
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 (ds.isStatic) {
|
||||
let 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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
import lodash from 'lodash'
|
||||
import { Data, Format } from '#miao'
|
||||
import { charPosIdx } from './CharMeta.js'
|
||||
import { aliasMap as aliasMapSR } from '../../resources/meta-sr/character/meta.js'
|
||||
|
||||
|
||||
// 别名表
|
||||
let aliasMap = {}
|
||||
@ -16,8 +18,26 @@ let wifeMap = {}
|
||||
// id排序
|
||||
let idSort = {}
|
||||
|
||||
let gameMap = {}
|
||||
|
||||
let srData = Data.readJSON('/resources/meta-sr/character/data.json', 'miao')
|
||||
|
||||
async function init () {
|
||||
let { sysCfg, diyCfg } = await Data.importCfg('character')
|
||||
|
||||
lodash.forEach(srData, (ds) => {
|
||||
let { id, name } = ds
|
||||
aliasMap[id] = id
|
||||
aliasMap[name] = id
|
||||
idMap[id] = name
|
||||
gameMap[id] = 'sr'
|
||||
})
|
||||
|
||||
// 添加别名
|
||||
lodash.forEach(aliasMapSR, (v, k) => {
|
||||
aliasMap[k] = aliasMap[v]
|
||||
})
|
||||
|
||||
lodash.forEach([diyCfg.customCharacters, sysCfg.characters], (roleIds) => {
|
||||
lodash.forEach(roleIds || {}, (aliases, id) => {
|
||||
aliases = aliases || []
|
||||
@ -31,6 +51,7 @@ async function init () {
|
||||
})
|
||||
aliasMap[id] = id
|
||||
idMap[id] = aliases[0]
|
||||
gameMap[id] = 'gs'
|
||||
})
|
||||
})
|
||||
|
||||
@ -66,15 +87,26 @@ lodash.forEach(charPosIdx, (chars, pos) => {
|
||||
const CharId = {
|
||||
aliasMap,
|
||||
idMap,
|
||||
gameMap,
|
||||
abbrMap,
|
||||
wifeMap,
|
||||
idSort,
|
||||
getId (ds = '', gsCfg = null) {
|
||||
isGs (id) {
|
||||
return gameMap[id] === 'gs'
|
||||
},
|
||||
isSr (id) {
|
||||
return gameMap[id] === 'sr'
|
||||
},
|
||||
getId (ds = '', gsCfg = null, game = 'gs') {
|
||||
if (!ds) {
|
||||
return false
|
||||
}
|
||||
const ret = (id, elem = '') => {
|
||||
return { id, elem, name: idMap[id] }
|
||||
if (CharId.isSr(id)) {
|
||||
return { id, name: idMap[id], game: 'sr' }
|
||||
} else {
|
||||
return { id, elem, name: idMap[id], game: 'gs' }
|
||||
}
|
||||
}
|
||||
if (!lodash.isObject(ds)) {
|
||||
let original = lodash.trim(ds || '')
|
||||
@ -114,15 +146,19 @@ const CharId = {
|
||||
return false
|
||||
},
|
||||
|
||||
isTraveler (id) {
|
||||
isTraveler (id, game = 'gs') {
|
||||
if (id) {
|
||||
return [10000007, 10000005, 20000000].includes(id * 1)
|
||||
}
|
||||
return false
|
||||
},
|
||||
|
||||
getTravelerId (id) {
|
||||
getTravelerId (id, game = 'gs') {
|
||||
return id * 1 === 10000005 ? 10000005 : 10000007
|
||||
},
|
||||
|
||||
getSrMeta (name) {
|
||||
return srData?.[aliasMap[name]] || {}
|
||||
}
|
||||
}
|
||||
export default CharId
|
||||
|
@ -118,6 +118,31 @@ const CharImg = {
|
||||
imgs.e = talentCons.e === 3 ? imgs['cons3'] : imgs['cons5']
|
||||
imgs.q = talentCons.q === 5 ? imgs['cons5'] : imgs['cons3']
|
||||
return imgs
|
||||
},
|
||||
getImgsSr (name, talentCons) {
|
||||
let fileType = 'webp'
|
||||
const nPath = `/meta-sr/character/${name}/`
|
||||
let imgs = {}
|
||||
let add = (key, path, path2) => {
|
||||
imgs[key] = `${nPath}${path}.${fileType}`
|
||||
}
|
||||
add('face', 'imgs/face')
|
||||
add('splash', 'imgs/splash')
|
||||
add('preview', 'imgs/preview')
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
add(`tree${i}`, `imgs/tree-${i}`)
|
||||
}
|
||||
for (let key of ['a', 'e', 'q', 't', 'z']) {
|
||||
add(key, `imgs/talent-${key}`)
|
||||
}
|
||||
for (let i = 1; i <= 6; i++) {
|
||||
if (i !==3 && i !== 5) {
|
||||
add(`cons${i}`, `imgs/cons-${i}`)
|
||||
}
|
||||
}
|
||||
imgs.cons3 = imgs[talentCons[3]]
|
||||
imgs.cons5 = imgs[talentCons[5]]
|
||||
return imgs
|
||||
}
|
||||
}
|
||||
export default CharImg
|
||||
|
@ -5,9 +5,14 @@ import lodash from 'lodash'
|
||||
|
||||
const CharTalent = {
|
||||
// 处理获取天赋数据
|
||||
getAvatarTalent (id, talent, cons, mode, consTalent = {}) {
|
||||
getAvatarTalent (char, talent, cons, mode) {
|
||||
let { id, talentCons, game, isGs } = char
|
||||
let ret = {}
|
||||
lodash.forEach(['a', 'e', 'q'], (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
|
||||
@ -22,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') {
|
||||
if (key === 'a' && isGs) {
|
||||
level = aPlus ? value + 1 : value
|
||||
} else {
|
||||
level = cons >= consTalent[key] ? (value + 3) : value
|
||||
level = cons >= talentCons[key] ? (value + addNum) : value
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -37,10 +42,10 @@ const CharTalent = {
|
||||
// 基于level计算original
|
||||
value = value || ds.level || ds.level_current || ds.original || ds.level_original
|
||||
level = value
|
||||
if (key === 'a') {
|
||||
if (key === 'a' && isGs) {
|
||||
original = aPlus ? value - 1 : value
|
||||
} else {
|
||||
original = cons >= consTalent[key] ? (value - 3) : value
|
||||
original = cons >= talentCons[key] ? (value - addNum) : value
|
||||
}
|
||||
}
|
||||
ret[key] = { level, original }
|
||||
|
109
models/player/HomoApi.js
Normal file
@ -0,0 +1,109 @@
|
||||
import lodash from 'lodash'
|
||||
import { Data } from '#miao'
|
||||
import { Character } from '#miao.models'
|
||||
|
||||
export default {
|
||||
id: 'homo',
|
||||
name: 'Mihomo',
|
||||
cfgKey: 'homoApi',
|
||||
// 处理请求参数
|
||||
async request (api) {
|
||||
let params = {
|
||||
headers: { 'User-Agent': this.getCfg('userAgent') }
|
||||
}
|
||||
return { api, params }
|
||||
},
|
||||
|
||||
// 处理服务返回
|
||||
async response (data, req) {
|
||||
if (!data.PlayerDetailInfo) {
|
||||
return req.err('error', 60)
|
||||
}
|
||||
let ds = data.PlayerDetailInfo
|
||||
let ac = ds.AssistAvatar
|
||||
let avatars = {}
|
||||
if (ac && !lodash.isEmpty(ac)) {
|
||||
avatars[ac.AvatarID] = ac
|
||||
}
|
||||
lodash.forEach(ds.DisplayAvatarList, (ds) => {
|
||||
avatars[ds.AvatarID] = ds
|
||||
})
|
||||
|
||||
if (lodash.isEmpty(avatars)) {
|
||||
return req.err('empty', 5 * 60)
|
||||
}
|
||||
data.avatars = avatars
|
||||
return data
|
||||
},
|
||||
|
||||
updatePlayer (player, data) {
|
||||
try {
|
||||
player.setBasicData(Data.getData(data, 'name:NickName,face:HeadIconID,level:Level,word:WorldLevel,sign:Signature'))
|
||||
lodash.forEach(data.avatars, (ds, id) => {
|
||||
let ret = HomoData.setAvatar(player, ds)
|
||||
if (ret) {
|
||||
player._update.push(ds.AvatarID)
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
|
||||
// 获取冷却时间
|
||||
cdTime (data) {
|
||||
return data.ttl || 60
|
||||
}
|
||||
}
|
||||
|
||||
const HomoData = {
|
||||
setAvatar (player, data) {
|
||||
let char = Character.get(data.AvatarID)
|
||||
if (!char) {
|
||||
return false
|
||||
}
|
||||
let avatar = player.getAvatar(char.id, true)
|
||||
let setData = {
|
||||
level: data.Level,
|
||||
promote: data.Promotion,
|
||||
cons: data.Rank || 0,
|
||||
weapon: Data.getData(data.EquipmentID, 'id:ID,promote:Promotion,level:Level,affix:Rank'),
|
||||
...HomoData.getTalent(data.BehaviorList, char),
|
||||
artis: HomoData.getArtis(data.RelicList)
|
||||
}
|
||||
avatar.setAvatar(setData, 'homo')
|
||||
return avatar
|
||||
},
|
||||
getTalent (ds, char) {
|
||||
let talent = {}
|
||||
let trees = []
|
||||
lodash.forEach(ds, (d) => {
|
||||
let key = char.getTalentKey(d.BehaviorID)
|
||||
if (key || d.Level > 1) {
|
||||
talent[key || d.BehaviorID] = d.Level
|
||||
} else {
|
||||
trees.push(d.BehaviorID)
|
||||
}
|
||||
})
|
||||
return { talent, trees }
|
||||
},
|
||||
getArtis (artis) {
|
||||
let ret = {}
|
||||
lodash.forEach(artis, (ds) => {
|
||||
let tmp = {
|
||||
id: ds.ID,
|
||||
level: ds.Level || 1,
|
||||
mainId: ds.MainAffixID,
|
||||
attrs: []
|
||||
}
|
||||
lodash.forEach(ds.RelicSubAffix, (s) => {
|
||||
if (!s.SubAffixID) {
|
||||
return true
|
||||
}
|
||||
tmp.attrs.push([s.SubAffixID, s.Cnt, s.Step || 0].join(','))
|
||||
})
|
||||
ret[ds.Type] = tmp
|
||||
})
|
||||
return ret
|
||||
}
|
||||
}
|
@ -10,10 +10,13 @@ export default {
|
||||
api = this.getCfg('api') || api
|
||||
return { api }
|
||||
},
|
||||
async response (data, req) {
|
||||
async response (data, req, game = 'gs') {
|
||||
if (data.status !== 0) {
|
||||
return req.err(data.msg || 'error', 60)
|
||||
}
|
||||
if (game === 'sr') {
|
||||
return data.data
|
||||
}
|
||||
if (data.version === 2) {
|
||||
data = data.data || {}
|
||||
if (!data.avatars || data.avatars.length === 0) {
|
||||
@ -22,32 +25,18 @@ export default {
|
||||
data.version = 2
|
||||
return data
|
||||
} else {
|
||||
data = data.data || {}
|
||||
if (!data.showAvatarInfoList || data.showAvatarInfoList.length === 0) {
|
||||
return req.err('empty', 5 * 60)
|
||||
}
|
||||
return data
|
||||
return req.err('empty', 5 * 60)
|
||||
}
|
||||
},
|
||||
|
||||
updatePlayer (player, data) {
|
||||
if (data.version === 2) {
|
||||
player.setBasicData(data)
|
||||
lodash.forEach(data.avatars, (avatar) => {
|
||||
let ret = MiaoData.setAvatarNew(player, avatar)
|
||||
if (ret) {
|
||||
player._update.push(ret.id)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
player.setBasicData(Data.getData(data, 'name:nickname,face:profilePicture.avatarId,card:nameCardID,level,word:worldLevel,sign:signature'))
|
||||
lodash.forEach(data.showAvatarInfoList, (ds) => {
|
||||
let ret = MiaoData.setAvatar(player, ds)
|
||||
if (ret) {
|
||||
player._update.push(ret.id)
|
||||
}
|
||||
})
|
||||
}
|
||||
player.setBasicData(data)
|
||||
lodash.forEach(data.avatars, (avatar) => {
|
||||
let ret = MiaoData.setAvatar(player, avatar)
|
||||
if (ret) {
|
||||
player._update.push(ret.id)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 获取冷却时间
|
||||
|
@ -7,44 +7,26 @@ let MiaoData = {
|
||||
setAvatar (player, ds) {
|
||||
let char = Character.get(ds.id)
|
||||
let avatar = player.getAvatar(ds.id, true)
|
||||
let talentRet = MiaoData.getTalent(char.id, ds.skill)
|
||||
avatar.setAvatar({
|
||||
level: ds.level,
|
||||
cons: ds.constellationNum || 0,
|
||||
promote: ds.promoteLevel,
|
||||
fetter: ds.fetterLevel,
|
||||
costume: char.checkCostume(ds.costumeID) ? ds.costumeID : 0,
|
||||
elem: talentRet.elem,
|
||||
weapon: MiaoData.getWeapon(ds.weapon),
|
||||
talent: talentRet.talent,
|
||||
artis: MiaoData.getArtifact(ds.reliquary)
|
||||
}, 'miao')
|
||||
return avatar
|
||||
},
|
||||
|
||||
setAvatarNew (player, ds) {
|
||||
let char = Character.get(ds.id)
|
||||
let avatar = player.getAvatar(ds.id, true)
|
||||
let talentRet = MiaoData.getTalentNew(char.id, ds.talent)
|
||||
avatar.setAvatar({
|
||||
...ds,
|
||||
elem: talentRet.elem,
|
||||
talent: talentRet.talent
|
||||
}, 'miao')
|
||||
return avatar
|
||||
},
|
||||
|
||||
getWeapon (weapon) {
|
||||
return {
|
||||
name: weapon.name,
|
||||
level: weapon.level,
|
||||
promote: weapon.promoteLevel,
|
||||
affix: (weapon.affixLevel || 0) + 1
|
||||
if (!char) {
|
||||
return false
|
||||
}
|
||||
if (player.isSr) {
|
||||
avatar.setAvatar({
|
||||
...ds,
|
||||
...MiaoData.getTalentSR(char, ds.talent)
|
||||
}, 'miao')
|
||||
} else {
|
||||
let talentRet = MiaoData.getTalent(char, ds.talent)
|
||||
avatar.setAvatar({
|
||||
...ds,
|
||||
elem: talentRet.elem,
|
||||
talent: talentRet.talent
|
||||
}, 'miao')
|
||||
}
|
||||
return avatar
|
||||
},
|
||||
|
||||
getTalentNew (charid, data = {}) {
|
||||
let char = Character.get(charid)
|
||||
getTalent (char, data = {}) {
|
||||
let { talentId = {}, talentElem = {} } = char.meta
|
||||
let elem = ''
|
||||
let idx = 0
|
||||
@ -67,70 +49,18 @@ let MiaoData = {
|
||||
}
|
||||
},
|
||||
|
||||
getTalent (charid, data = {}) {
|
||||
let char = Character.get(charid)
|
||||
let { talentId = {}, talentElem = {} } = char.meta
|
||||
let elem = ''
|
||||
let idx = 0
|
||||
let ret = {}
|
||||
lodash.forEach(data, (ds) => {
|
||||
let key
|
||||
if (talentId[ds.id]) {
|
||||
key = talentId[ds.id]
|
||||
elem = elem || talentElem[ds.id]
|
||||
ret[key] = {
|
||||
level: ds.level
|
||||
}
|
||||
getTalentSR (char, data) {
|
||||
let talent = {}
|
||||
let trees = []
|
||||
lodash.forEach(data, (lv, id) => {
|
||||
let key = char.getTalentKey(id)
|
||||
if (key || lv > 1) {
|
||||
talent[key || id] = lv
|
||||
} else {
|
||||
key = ['a', 'e', 'q'][idx++]
|
||||
ret[key] = ret[key] || {
|
||||
level: ds.level
|
||||
}
|
||||
trees.push(id)
|
||||
}
|
||||
})
|
||||
return {
|
||||
talent: ret,
|
||||
elem
|
||||
}
|
||||
},
|
||||
|
||||
getArtifact (data) {
|
||||
let ret = {}
|
||||
let get = function (d) {
|
||||
if (!d) {
|
||||
return []
|
||||
}
|
||||
let name = d.name
|
||||
name = name.replace('FIGHT_PROP_', '')
|
||||
if (!attrMap[name]) {
|
||||
return []
|
||||
}
|
||||
let value = d.value
|
||||
if (value && value < 1) {
|
||||
value = value * 100
|
||||
}
|
||||
return { key: attrMap[name], value }
|
||||
}
|
||||
lodash.forEach(data, (ds) => {
|
||||
let sub = ds.appendAffix || []
|
||||
let idx = artisIdxMap[ds.type]
|
||||
if (!idx) {
|
||||
return
|
||||
}
|
||||
ret[idx] = {
|
||||
name: ds.name,
|
||||
level: ds.level,
|
||||
star: ds.rank,
|
||||
main: get(ds.mainAffix),
|
||||
attrs: [
|
||||
get(sub[0]),
|
||||
get(sub[1]),
|
||||
get(sub[2]),
|
||||
get(sub[3])
|
||||
]
|
||||
}
|
||||
})
|
||||
return ret
|
||||
return { talent, trees }
|
||||
}
|
||||
}
|
||||
export default MiaoData
|
||||
|
@ -40,7 +40,6 @@ const MysAvatar = {
|
||||
/**
|
||||
* 更新米游社角色信息
|
||||
* @param player
|
||||
* @param mys
|
||||
* @param force
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
|
@ -6,6 +6,9 @@ import enkaApi from './EnkaApi.js'
|
||||
import miaoApi from './MiaoApi.js'
|
||||
import mggApi from './MggApi.js'
|
||||
import hutaoApi from './HutaoApi.js'
|
||||
import homoApi from './HomoApi.js'
|
||||
|
||||
import lodash from 'lodash'
|
||||
|
||||
let { diyCfg } = await Data.importCfg('profile')
|
||||
|
||||
@ -17,7 +20,8 @@ const Profile = {
|
||||
miao: miaoApi,
|
||||
mgg: mggApi,
|
||||
enka: enkaApi,
|
||||
hutao: hutaoApi
|
||||
hutao: hutaoApi,
|
||||
homo: homoApi
|
||||
}[key])
|
||||
}
|
||||
return Profile.servs[key]
|
||||
@ -26,9 +30,10 @@ const Profile = {
|
||||
/**
|
||||
* 根据UID分配请求服务器
|
||||
* @param uid
|
||||
* @param game
|
||||
* @returns {ProfileServ}
|
||||
*/
|
||||
getServ (uid) {
|
||||
getServ (uid, game = 'gs') {
|
||||
let token = diyCfg?.miaoApi?.token
|
||||
let qq = diyCfg?.miaoApi?.qq
|
||||
let hasToken = !!(qq && token && token.length === 32 && !/^test/.test(token))
|
||||
@ -40,6 +45,13 @@ const Profile = {
|
||||
let servCfg = Cfg.get('profileServer', '0').toString() || '0'
|
||||
servCfg = servCfg[servIdx] || servCfg[0] || '0'
|
||||
|
||||
if (game === 'sr') {
|
||||
if ((servCfg === '0' || servCfg === '1') && hasToken) {
|
||||
return Profile.serv('miao')
|
||||
}
|
||||
return Profile.serv('homo')
|
||||
}
|
||||
|
||||
if ((servCfg === '0' || servCfg === '1') && hasToken) {
|
||||
return Profile.serv('miao')
|
||||
}
|
||||
@ -68,13 +80,13 @@ const Profile = {
|
||||
if (uid.toString().length !== 9 || !e) {
|
||||
return false
|
||||
}
|
||||
let req = ProfileReq.create(e)
|
||||
let req = ProfileReq.create(e, player.game)
|
||||
if (!req) {
|
||||
return false
|
||||
}
|
||||
let serv = Profile.getServ(uid)
|
||||
let serv = Profile.getServ(uid, player.game)
|
||||
try {
|
||||
await req.requestProfile(player, serv)
|
||||
await req.requestProfile(player, serv, player.game)
|
||||
player._profile = new Date() * 1
|
||||
player.save()
|
||||
return player._update.length
|
||||
@ -82,17 +94,21 @@ const Profile = {
|
||||
if (!e._isReplyed) {
|
||||
e.reply(`UID:${uid}更新面板失败,更新服务:${serv.name}`)
|
||||
}
|
||||
console.log(err)
|
||||
return false
|
||||
}
|
||||
},
|
||||
|
||||
isProfile (avatar) {
|
||||
if (avatar.isSr) {
|
||||
return true
|
||||
}
|
||||
// 检查数据源
|
||||
if (!avatar._source || !['enka', 'change', 'miao', 'mgg', 'hutao'].includes(avatar._source)) {
|
||||
if (!avatar._source || !['enka', 'change', 'miao', 'mgg', 'hutao', 'homo'].includes(avatar._source)) {
|
||||
return false
|
||||
}
|
||||
// 检查武器及天赋
|
||||
if (!avatar.weapon || !avatar.talent) {
|
||||
if (!avatar.weapon || lodash.isUndefined(avatar.weapon.promote) || !avatar.talent) {
|
||||
return false
|
||||
}
|
||||
// 检查圣遗物词条是否完备
|
||||
|
@ -1,47 +1,40 @@
|
||||
import lodash from 'lodash'
|
||||
import { Format } from '#miao'
|
||||
import { attrNameMap, mainAttr, subAttr, attrMap, basicNum, attrPct } from '../../resources/meta/artifact/index.js'
|
||||
import { attrNameMap, mainAttr, subAttr, attrMap } from '../../resources/meta/artifact/index.js'
|
||||
import {
|
||||
attrMap as attrMapSR
|
||||
} from '../../resources/meta-sr/artifact/meta.js'
|
||||
|
||||
let ArtisMark = {
|
||||
// 根据Key获取标题
|
||||
getKeyByTitle (title, dmg = false) {
|
||||
getKeyByTitle (title, game = 'gs') {
|
||||
if (/元素伤害加成/.test(title) || Format.isElem(title)) {
|
||||
let elem = Format.matchElem(title)
|
||||
return dmg ? 'dmg' : elem
|
||||
return elem
|
||||
} else if (title === '物理伤害加成') {
|
||||
return 'phy'
|
||||
}
|
||||
return attrNameMap[title]
|
||||
return (game === 'gs' ? attrNameMap : attrMap)[title]
|
||||
},
|
||||
|
||||
// 根据标题获取Key
|
||||
getTitleByKey (key) {
|
||||
// 检查是否是伤害字段
|
||||
let dmg = Format.elemName(key, '')
|
||||
if (dmg) {
|
||||
return `${dmg}伤加成`
|
||||
}
|
||||
return attrMap[key].title
|
||||
},
|
||||
|
||||
getKeyTitleMap () {
|
||||
getKeyTitleMap (game = 'gs') {
|
||||
let ret = {}
|
||||
lodash.forEach(attrMap, (ds, key) => {
|
||||
lodash.forEach(game === 'gs' ? attrMap : attrMapSR, (ds, key) => {
|
||||
ret[key] = ds.title
|
||||
})
|
||||
Format.eachElem((key, name) => {
|
||||
ret[key] = `${name}伤加成`
|
||||
})
|
||||
}, game)
|
||||
return ret
|
||||
},
|
||||
|
||||
formatAttr (ds) {
|
||||
formatAttr (ds, game = 'gs') {
|
||||
if (!ds) {
|
||||
return {}
|
||||
}
|
||||
if (lodash.isArray(ds) && ds[0] && ds[1]) {
|
||||
return {
|
||||
key: ArtisMark.getKeyByTitle(ds[0]),
|
||||
key: ArtisMark.getKeyByTitle(ds[0], game),
|
||||
value: ds[1]
|
||||
}
|
||||
}
|
||||
@ -49,7 +42,7 @@ let ArtisMark = {
|
||||
return {}
|
||||
}
|
||||
return {
|
||||
key: ds.key || ArtisMark.getKeyByTitle(ds.title || ds.name || ds.key || ds.id || ''),
|
||||
key: ds.key || ArtisMark.getKeyByTitle(ds.title || ds.name || ds.key || ds.id || '', game),
|
||||
value: ds.value || ''
|
||||
}
|
||||
},
|
||||
@ -57,76 +50,41 @@ let ArtisMark = {
|
||||
/**
|
||||
* 格式化圣遗物词条
|
||||
* @param ds
|
||||
* @param markCfg
|
||||
* @param charAttrCfg
|
||||
* @param isMain
|
||||
* @param game
|
||||
* @returns {{title: *, value: string}|*[]}
|
||||
*/
|
||||
formatArti (ds, charAttrCfg = false, isMain = false, elem = '') {
|
||||
formatArti (ds, charAttrCfg = false, isMain = false, game = 'gs') {
|
||||
// 若为attr数组
|
||||
if (ds[0] && (ds[0].title || ds[0].key)) {
|
||||
let ret = []
|
||||
let totalUpNum = 0
|
||||
let ltArr = []
|
||||
let isIdAttr = false
|
||||
|
||||
lodash.forEach(ds, (d) => {
|
||||
isIdAttr = !d.isCalcNum
|
||||
let arti = ArtisMark.formatArti(d, charAttrCfg)
|
||||
let arti = ArtisMark.formatArti(d, charAttrCfg, isMain, game)
|
||||
ret.push(arti)
|
||||
if (isIdAttr) {
|
||||
return true
|
||||
}
|
||||
totalUpNum += arti.upNum
|
||||
if (arti.hasLt) {
|
||||
ltArr.push(arti)
|
||||
}
|
||||
delete arti.hasLt
|
||||
delete arti.hasGt
|
||||
})
|
||||
if (!isIdAttr) {
|
||||
ltArr = lodash.sortBy(ltArr, 'upNum').reverse()
|
||||
for (let arti of ltArr) {
|
||||
if (totalUpNum > 9) {
|
||||
arti.upNum = arti.upNum - 1
|
||||
totalUpNum--
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
let key = ds.key
|
||||
let title = ds.title || ds[0]
|
||||
if (!key) {
|
||||
key = ArtisMark.getKeyByTitle(title)
|
||||
} else if (!title) {
|
||||
title = ArtisMark.getTitleByKey(key)
|
||||
key = ArtisMark.getKeyByTitle(title, game)
|
||||
}
|
||||
let isDmg = Format.isElem(key)
|
||||
let val = ds.value || ds[1]
|
||||
let value = val
|
||||
let num = ds.value || ds[1]
|
||||
if (!key || key === 'undefined') {
|
||||
return {}
|
||||
}
|
||||
let arrCfg = attrMap[isDmg ? 'dmg' : key]
|
||||
val = Format[arrCfg.format](val, 1)
|
||||
let arrCfg = (game === 'gs' ? attrMap : attrMapSR)[isDmg ? 'dmg' : key]
|
||||
val = Format[arrCfg?.format || 'comma'](val, 1)
|
||||
let ret = {
|
||||
key,
|
||||
value: val,
|
||||
upNum: ds.upNum || 0,
|
||||
eff: ds.eff || 0
|
||||
}
|
||||
if (!isMain && !ret.upNum) {
|
||||
let incRet = ArtisMark.getIncNum(key, value)
|
||||
ret.upNum = incRet.num
|
||||
ret.eff = incRet.eff
|
||||
ret.hasGt = incRet.hasGt
|
||||
ret.hasLt = incRet.hasLt
|
||||
ret.isCalcNum = true
|
||||
}
|
||||
|
||||
if (charAttrCfg) {
|
||||
let mark = charAttrCfg[key]?.mark * num || 0
|
||||
@ -141,27 +99,6 @@ let ArtisMark = {
|
||||
return ret
|
||||
},
|
||||
|
||||
// 获取升级次数
|
||||
getIncNum (key, value) {
|
||||
let cfg = attrMap[key]
|
||||
if (!value || !cfg || !cfg.value || !cfg.valueMin) {
|
||||
return { num: 0 }
|
||||
}
|
||||
let maxNum = Math.min(5, Math.floor((value / cfg.valueMin).toFixed(1) * 1))
|
||||
let minNum = Math.max(1, Math.ceil((value / cfg.value).toFixed(1) * 1))
|
||||
// 相等时直接返回
|
||||
if (maxNum === minNum) {
|
||||
return { num: minNum, eff: value / cfg.value }
|
||||
}
|
||||
let avg = Math.round(value / (cfg.value + cfg.valueMin) * 2)
|
||||
return {
|
||||
num: avg,
|
||||
eff: value / cfg.value,
|
||||
hasGt: maxNum > avg,
|
||||
hasLt: minNum < avg
|
||||
}
|
||||
},
|
||||
|
||||
// 获取评分档位
|
||||
getMarkClass (mark) {
|
||||
let pct = mark
|
||||
@ -174,22 +111,27 @@ let ArtisMark = {
|
||||
},
|
||||
|
||||
// 获取位置分数
|
||||
getMark (charCfg, posIdx, mainAttr, subAttr, elem = '') {
|
||||
getMark ({ charCfg, idx, arti, elem = '', game = 'gs' }) {
|
||||
if (game === 'sr') {
|
||||
return 0
|
||||
}
|
||||
let ret = 0
|
||||
let mainAttr = arti.main
|
||||
let subAttr = arti.attrs
|
||||
let { attrs, posMaxMark } = charCfg
|
||||
let key = mainAttr?.key
|
||||
if (!key) {
|
||||
return 0
|
||||
}
|
||||
let fixPct = 1
|
||||
posIdx = posIdx * 1
|
||||
if (posIdx >= 3) {
|
||||
idx = idx * 1
|
||||
if (idx >= 3) {
|
||||
let mainKey = key
|
||||
if (key !== 'recharge') {
|
||||
if (posIdx === 4 && Format.isElem(key) && key === elem) {
|
||||
if (idx === 4 && Format.isElem(key) && key === elem) {
|
||||
mainKey = 'dmg'
|
||||
}
|
||||
fixPct = Math.max(0, Math.min(1, (attrs[mainKey]?.weight || 0) / (posMaxMark['m' + posIdx])))
|
||||
fixPct = Math.max(0, Math.min(1, (attrs[mainKey]?.weight || 0) / (posMaxMark['m' + idx])))
|
||||
}
|
||||
ret += (attrs[mainKey]?.mark || 0) * (mainAttr.value || 0) / 4
|
||||
}
|
||||
@ -197,61 +139,7 @@ let ArtisMark = {
|
||||
lodash.forEach(subAttr, (ds) => {
|
||||
ret += (attrs[ds.key]?.mark || 0) * (ds.value || 0)
|
||||
})
|
||||
return ret * (1 + fixPct) / 2 / posMaxMark[posIdx] * 66
|
||||
},
|
||||
|
||||
getCritMark (charCfg, posIdx, mainAttr, subAttr, elem = '') {
|
||||
let ret = 0
|
||||
let { attrs, posMaxMark } = charCfg
|
||||
let key = mainAttr?.key
|
||||
if (!key) {
|
||||
return 0
|
||||
}
|
||||
let fixPct = 1
|
||||
posIdx = posIdx * 1
|
||||
if (posIdx >= 4) {
|
||||
let mainKey = key
|
||||
if (posIdx === 4 && Format.isElem(key) && key === elem) {
|
||||
mainKey = 'dmg'
|
||||
}
|
||||
fixPct = Math.max(0, Math.min(1, (attrs[mainKey]?.weight || 0) / (posMaxMark['m' + posIdx])))
|
||||
}
|
||||
if (key === 'cpct' || key === 'cdmg') {
|
||||
ret += 9.41
|
||||
}
|
||||
|
||||
lodash.forEach(subAttr, (ds) => {
|
||||
if (ds.key === 'cpct' || ds.key === 'cdmg') {
|
||||
let temp_s = (attrs[ds.key]?.mark || 0) * (ds.value || 0) / 85
|
||||
ret += temp_s
|
||||
}
|
||||
})
|
||||
return ret
|
||||
},
|
||||
|
||||
getValidMark (charCfg, posIdx, mainAttr, subAttr, elem = '') {
|
||||
let ret = 0
|
||||
let { attrs, posMaxMark } = charCfg
|
||||
let key = mainAttr?.key
|
||||
if (!key) {
|
||||
return 0
|
||||
}
|
||||
let fixPct = 1
|
||||
posIdx = posIdx * 1
|
||||
if (posIdx >= 4) {
|
||||
let mainKey = key
|
||||
if (posIdx === 4 && Format.isElem(key) && key === elem) {
|
||||
mainKey = 'dmg'
|
||||
}
|
||||
|
||||
|
||||
fixPct = Math.max(0, Math.min(1, (attrs[mainKey]?.weight || 0) / (posMaxMark['m' + posIdx])))
|
||||
}
|
||||
lodash.forEach(subAttr, (ds) => {
|
||||
let temp_s = (attrs[ds.key]?.mark || 0) * (ds.value || 0) / 85
|
||||
ret += temp_s
|
||||
})
|
||||
return ret
|
||||
return ret * (1 + fixPct) / 2 / posMaxMark[idx] * 66
|
||||
},
|
||||
|
||||
// 获取位置最高分
|
||||
@ -300,7 +188,8 @@ let ArtisMark = {
|
||||
for (let idx = 1; idx <= 5; idx++) {
|
||||
let ds = artis[idx]
|
||||
if (ds) {
|
||||
if (!ds.name || !ds.main || !ds.attrs || !ds?.main?.key) {
|
||||
// 不再支持非id格式的面板
|
||||
if (!ds.attrs || !ds.mainId) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +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 { weaponBuffs } from '../../resources/meta/weapon/index.js'
|
||||
import lodash from 'lodash'
|
||||
|
||||
@ -13,6 +12,15 @@ class AttrCalc {
|
||||
constructor (profile) {
|
||||
this.profile = profile
|
||||
this.char = profile.char
|
||||
this.game = this.char.game
|
||||
}
|
||||
|
||||
get isGs () {
|
||||
return this.game === 'gs'
|
||||
}
|
||||
|
||||
get isSr () {
|
||||
return this.game === 'sr'
|
||||
}
|
||||
|
||||
/**
|
||||
@ -24,6 +32,7 @@ class AttrCalc {
|
||||
return new AttrCalc(profile)
|
||||
}
|
||||
|
||||
// 只有原神才需要
|
||||
static calcPromote (lv) {
|
||||
if (lv === 20) {
|
||||
return 1
|
||||
@ -47,14 +56,17 @@ class AttrCalc {
|
||||
* @returns {{}}
|
||||
*/
|
||||
calc () {
|
||||
this.attr = ProfileAttr.create({})
|
||||
this.addAttr('recharge', 100, true)
|
||||
this.addAttr('cpct', 5, true)
|
||||
this.addAttr('cdmg', 50, true)
|
||||
this.attr = ProfileAttr.create(this.char, {})
|
||||
if (this.isGs) {
|
||||
this.addAttr('recharge', 100, true)
|
||||
this.addAttr('cpct', 5, true)
|
||||
this.addAttr('cdmg', 50, true)
|
||||
}
|
||||
this.setCharAttr()
|
||||
this.setWeaponAttr()
|
||||
this.setArtisAttr()
|
||||
return this.attr.getAttr()
|
||||
|
||||
}
|
||||
|
||||
getBase () {
|
||||
@ -71,8 +83,31 @@ class AttrCalc {
|
||||
* @param affix
|
||||
*/
|
||||
setCharAttr (affix = '') {
|
||||
let { char, level, promote } = this.profile
|
||||
let { char, level, promote, trees } = this.profile
|
||||
let metaAttr = char.detail?.attr || {}
|
||||
let self = this
|
||||
if (this.isSr) {
|
||||
// 星铁面板属性
|
||||
let attr = char.getLvAttr(level, promote)
|
||||
lodash.forEach(attr, (v, k) => {
|
||||
k = k + (['hp', 'atk', 'def'].includes(k) ? 'Base' : '')
|
||||
self.addAttr(k, v, true)
|
||||
})
|
||||
|
||||
let tree = char.detail?.tree || {}
|
||||
lodash.forEach(trees || [], (tid) => {
|
||||
let tCfg = tree[tid]
|
||||
if (tCfg) {
|
||||
let key = tCfg.key
|
||||
if (['atk', 'hp', 'def'].includes(key)) {
|
||||
key = key + 'Pct'
|
||||
}
|
||||
self.addAttr(key, tCfg.value)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
let { keys = {}, details = {} } = metaAttr
|
||||
let lvLeft = 0
|
||||
let lvRight = 0
|
||||
@ -123,9 +158,30 @@ class AttrCalc {
|
||||
*/
|
||||
setWeaponAttr () {
|
||||
let wData = this.profile?.weapon || {}
|
||||
let weapon = Weapon.get(wData?.name)
|
||||
let weapon = Weapon.get(wData?.name || wData?.id, this.game)
|
||||
let wCalcRet = weapon.calcAttr(wData.level, wData.promote)
|
||||
let self = this
|
||||
|
||||
if (this.isSr) {
|
||||
// 星铁面板属性
|
||||
lodash.forEach(wCalcRet, (v, k) => {
|
||||
k = k + (['hp', 'atk', 'def'].includes(k) ? 'Base' : '')
|
||||
self.addAttr(k, v, true)
|
||||
})
|
||||
// 检查武器类型
|
||||
if (weapon.type === this.char.weapon) {
|
||||
// todo sr&gs 统一
|
||||
let wBuffs = weapon.getWeaponAffixBuffs(wData.affix, true)
|
||||
lodash.forEach(wBuffs, (buff) => {
|
||||
lodash.forEach(buff.data || [], (v, k) => {
|
||||
self.addAttr(k, v)
|
||||
})
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 原神属性
|
||||
if (wCalcRet) {
|
||||
this.addAttr('atkBase', wCalcRet.atkBase)
|
||||
this.addAttr(wCalcRet.attr?.key, wCalcRet.attr?.value)
|
||||
@ -157,20 +213,24 @@ class AttrCalc {
|
||||
artis.forEach((arti) => {
|
||||
this.calcArtisAttr(arti.main, this.char)
|
||||
lodash.forEach(arti.attrs, (ds) => {
|
||||
this.calcArtisAttr(ds)
|
||||
this.calcArtisAttr(ds, this.char)
|
||||
})
|
||||
})
|
||||
// 计算圣遗物静态加成
|
||||
artis.eachArtisSet((set, num) => {
|
||||
let buff = artisBuffs[set.name] && artisBuffs[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)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -178,6 +238,8 @@ class AttrCalc {
|
||||
/**
|
||||
* 计算单条圣遗物词缀
|
||||
* @param ds
|
||||
* @param char
|
||||
* @param autoPct
|
||||
* @returns {boolean}
|
||||
*/
|
||||
calcArtisAttr (ds, char) {
|
||||
|
32
models/profile/DataTrans.js
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 旧面板数据迁移
|
||||
* 去除旧格式,控制逻辑复杂度
|
||||
*/
|
||||
import fs from 'node:fs'
|
||||
import lodash from 'lodash'
|
||||
import { Data } from '#miao'
|
||||
|
||||
const DataTrans = {
|
||||
trans () {
|
||||
const srcPath = './data/UserData'
|
||||
let uids = fs.readdirSync(srcPath)
|
||||
uids = uids.filter((uid) => /\.json/i.test(uid))
|
||||
lodash.forEach(uids, (uid) => {
|
||||
let data = Data.readJSON(`/data/UserData/${uid}`)
|
||||
DataTrans.doTrans(data)
|
||||
})
|
||||
},
|
||||
doTrans (data) {
|
||||
lodash.forEach(data.avatars, (ds, id) => {
|
||||
data.avatars[id] = DataTrans.getAvatar(ds)
|
||||
})
|
||||
},
|
||||
getAvatar (data) {
|
||||
let artisSet = {}
|
||||
lodash.forEach(data.artis, (ds, idx) => {
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
export default DataTrans
|
@ -1,19 +1,20 @@
|
||||
/*
|
||||
* 伤害计算 - 属性计算
|
||||
* */
|
||||
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'
|
||||
|
||||
let DmgAttr = {
|
||||
// 计算并返回指定属性值
|
||||
getAttrValue (ds) {
|
||||
getAttrValue (ds = {}) {
|
||||
return (ds.base || 0) + (ds.plus || 0) + ((ds.base || 0) * (ds.pct || 0) / 100)
|
||||
},
|
||||
|
||||
// 获取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,16 @@ let DmgAttr = {
|
||||
return
|
||||
}
|
||||
}
|
||||
if (!lodash.isUndefined(buff.maxCons)) {
|
||||
if (ds.cons * 1 > buff.maxCons * 1) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if (buff.tree) {
|
||||
if (!ds.trees[`10${buff.tree}`]) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let title = buff.title
|
||||
|
||||
@ -163,12 +178,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 +192,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
|
||||
|
@ -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
|
||||
|
@ -18,7 +18,8 @@ let DmgCalc = {
|
||||
attr, // 属性
|
||||
level, // 面板数据
|
||||
enemyLv, // 敌人等级
|
||||
showDetail = false // 是否展示详情
|
||||
showDetail = false, // 是否展示详情
|
||||
game
|
||||
} = data
|
||||
let calc = ds.calc
|
||||
|
||||
@ -64,20 +65,27 @@ let DmgCalc = {
|
||||
|
||||
// 防御区
|
||||
let defNum = (level + 100) / ((level + 100) + (enemyLv + 100) * (1 - enemyDef) * (1 - enemyIgnore))
|
||||
if (game === 'sr') {
|
||||
defNum = (200 + level * 10) / ((200 + level * 10) + (200 + enemyLv * 10) * (1 - enemyDef) * (1 - enemyIgnore))
|
||||
}
|
||||
|
||||
// 抗性区
|
||||
let kx = attr.kx
|
||||
if (ele === 'swirl') {
|
||||
kx = attr.fykx
|
||||
}
|
||||
kx = 10 - (kx || 0)
|
||||
let kNum = 0.9
|
||||
if (kx >= 75) {
|
||||
kNum = 1 / (1 + 3 * kx / 100)
|
||||
} else if (kx >= 0) {
|
||||
kNum = (100 - kx) / 100
|
||||
if (game === 'sr') {
|
||||
kNum = (1 + (kx / 100)) * 0.9
|
||||
} else {
|
||||
kNum = 1 - kx / 200
|
||||
if (ele === 'swirl') {
|
||||
kx = attr.fykx
|
||||
}
|
||||
kx = 10 - (kx || 0)
|
||||
if (kx >= 75) {
|
||||
kNum = 1 / (1 + 3 * kx / 100)
|
||||
} else if (kx >= 0) {
|
||||
kNum = (100 - kx) / 100
|
||||
} else {
|
||||
kNum = 1 - kx / 200
|
||||
}
|
||||
}
|
||||
|
||||
cpctNum = Math.max(0, Math.min(1, cpctNum))
|
||||
@ -144,13 +152,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)
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,8 @@
|
||||
</div>
|
||||
|
||||
<div class="copyright data-source">
|
||||
数据源:{{ {miao:'喵喵API', 'enka':'Enka.Network', 'mgg':'MiniGG-API', mys:'米游社', 'hutao':'Hutao-Enka' }[data.source]||data.source }} {{data.updateTime}}
|
||||
数据源:{{ {miao:'喵喵API', 'enka':'Enka.Network', 'mgg':'MiniGG-API', mys:'米游社', 'hutao':'Hutao-Enka', 'homo':'Mihomo'
|
||||
}[data.source]||data.source }} {{data.updateTime}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{if custom}}
|
||||
|
BIN
resources/character/imgs/icon-sr.png
Normal file
After Width: | Height: | Size: 11 KiB |
@ -160,12 +160,24 @@ body {
|
||||
.i-cdmg {
|
||||
background-position: -96px 0;
|
||||
}
|
||||
.i-stance {
|
||||
background-position: -64px 0;
|
||||
}
|
||||
.i-recharge {
|
||||
background-position: -112px 0;
|
||||
}
|
||||
.i-dmg {
|
||||
background-position: -128px 0;
|
||||
}
|
||||
.i-heal {
|
||||
background-position: -144px 0;
|
||||
}
|
||||
.i-speed {
|
||||
background-position: -160px 0;
|
||||
}
|
||||
.i-effPct {
|
||||
background-position: -176px 0;
|
||||
}
|
||||
.detail.attr li:nth-child(even) {
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
@ -821,4 +833,116 @@ body {
|
||||
line-height: 20px;
|
||||
color: #bbb;
|
||||
}
|
||||
.game-sr .char-talents {
|
||||
transform: scale(0.8);
|
||||
transform-origin: top left;
|
||||
margin: -8px 0 -14px;
|
||||
}
|
||||
.game-sr .char-talents .talent-item {
|
||||
margin: 0 -3px;
|
||||
}
|
||||
.game-sr .artis-weapon {
|
||||
display: none;
|
||||
}
|
||||
.game-sr .char-attr .icon i {
|
||||
background-image: url('./imgs/icon-sr.png');
|
||||
}
|
||||
.sr-weapon {
|
||||
margin: 0 15px 5px 10px;
|
||||
border-radius: 10px;
|
||||
background: url("../common/cont/card-bg.png") top left repeat-x;
|
||||
background-size: auto 150%;
|
||||
position: relative;
|
||||
box-shadow: 0 0 1px 0 #ccc, 2px 2px 4px 0 rgba(50, 50, 50, 0.8);
|
||||
overflow: hidden;
|
||||
display: table;
|
||||
color: #fff;
|
||||
min-height: 120px;
|
||||
width: calc(100% - 25px);
|
||||
}
|
||||
.sr-weapon .weapon-img {
|
||||
display: table-cell;
|
||||
width: 185px;
|
||||
height: 100%;
|
||||
min-height: 120px;
|
||||
background-size: 100% auto;
|
||||
background-position: 0 5%;
|
||||
box-shadow: 0 0 1px 0 #ccc, 2px 2px 4px 0 rgba(50, 50, 50, 0.8);
|
||||
}
|
||||
.sr-weapon .weapon-info {
|
||||
display: table-cell;
|
||||
padding: 10px 10px 5px 15px;
|
||||
}
|
||||
.sr-weapon .weapon-title span {
|
||||
font-size: 14px;
|
||||
}
|
||||
.sr-weapon .weapon-title strong {
|
||||
color: #d3bc8e;
|
||||
font-weight: normal;
|
||||
}
|
||||
.sr-weapon .weapon-attr {
|
||||
font-size: 12px;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
display: flex;
|
||||
}
|
||||
.sr-weapon .weapon-attr .attr {
|
||||
padding-left: 22px;
|
||||
padding-right: 7px;
|
||||
margin-right: 10px;
|
||||
position: relative;
|
||||
line-height: 22px;
|
||||
height: 22px;
|
||||
font-size: 12px;
|
||||
color: #ffe699;
|
||||
display: inline-block;
|
||||
border-radius: 4px;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
text-align: center;
|
||||
}
|
||||
.sr-weapon .weapon-attr .attr span {
|
||||
font-size: 12px;
|
||||
display: none;
|
||||
}
|
||||
.sr-weapon .weapon-attr .attr:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
background-size: auto 100%;
|
||||
background-position: top center;
|
||||
vertical-align: middle;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.sr-weapon .weapon-attr .i-hp:before {
|
||||
background-image: url('../meta-sr/public/icons/attr-hp.webp');
|
||||
}
|
||||
.sr-weapon .weapon-attr .i-atk:before {
|
||||
background-image: url('../meta-sr/public/icons/attr-atk.webp');
|
||||
}
|
||||
.sr-weapon .weapon-attr .i-def:before {
|
||||
background-image: url('../meta-sr/public/icons/attr-def.webp');
|
||||
}
|
||||
.sr-weapon .weapon-desc {
|
||||
margin-top: 7px;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
color: #fff;
|
||||
white-space: break-spaces;
|
||||
text-shadow: 0 0 1px rgba(0, 0, 0, 0.7), 1px 1px 3px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
.sr-weapon .weapon-desc nobr {
|
||||
color: #ffe699;
|
||||
display: inline-block;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
text-align: center;
|
||||
padding: 0 3px;
|
||||
margin: 0 2px;
|
||||
}
|
||||
/*# sourceMappingURL=profile-detail.css.map */
|
@ -7,265 +7,301 @@
|
||||
{{set weapon = data.weapon}}
|
||||
|
||||
{{set dataSource = data.dataSource}}
|
||||
{{set talentMap = {a: '普攻', e: '战技', q: '爆发'} }}
|
||||
{{set talentMap = game === 'sr' ? {a: '普攻', e: '战技', t:'天赋', q: '爆发'} : {a: '普攻', e: '战技', q: '爆发'} }}
|
||||
{{set {imgs, costumeSplash} = data }}
|
||||
{{set imgs = imgs || {} }}
|
||||
{{set gameHash = game === 'gs' ? '#':'*' }}
|
||||
|
||||
{{block 'main'}}
|
||||
<div class="basic">
|
||||
<div class="main-pic"
|
||||
style="background-image:url({{_res_path}}{{costumeSplash||imgs?.splash}})"></div>
|
||||
<div class="detail">
|
||||
<div class="char-name">{{data.name}}</div>
|
||||
<div class="char-lv">UID {{uid}} - Lv.{{data.level}}
|
||||
<span class="cons cons-{{data.cons}}">{{data.cons}}命</span></div>
|
||||
<div>
|
||||
{{if mode !== 'weapon'}}
|
||||
<div class="char-talents">
|
||||
{{each talentMap tName key}}
|
||||
{{set talent = data.talent[key] || {} }}
|
||||
<div class="talent-item">
|
||||
<div class="talent-icon
|
||||
<div class="game-{{game}}">
|
||||
<div class="basic">
|
||||
<div class="main-pic"
|
||||
style="background-image:url({{_res_path}}{{costumeSplash||imgs?.splash}})"></div>
|
||||
<div class="detail">
|
||||
<div class="char-name">{{data.name}}</div>
|
||||
<div class="char-lv">UID {{uid}} - Lv.{{data.level}}
|
||||
<span class="cons cons-{{data.cons}}">{{data.cons}}命</span></div>
|
||||
<div>
|
||||
{{if mode !== 'weapon'}}
|
||||
<div class="char-talents">
|
||||
{{each talentMap tName key}}
|
||||
{{set talent = data.talent[key] || {} }}
|
||||
<div class="talent-item">
|
||||
<div class="talent-icon
|
||||
{{talent.level > talent.original ? `talent-plus`:``}}
|
||||
{{talent.original >= 10 ? `talent-crown`:``}}">
|
||||
<div class="talent-icon-img"
|
||||
style="background-image:url({{_res_path}}{{imgs[key]}})"></div>
|
||||
<span>{{talent.level}}</span>
|
||||
<div class="talent-icon-img"
|
||||
style="background-image:url({{_res_path}}{{imgs[key]}})"></div>
|
||||
<span>{{talent.level}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<ul class="char-attr">
|
||||
{{set attrMap = game === 'sr' ? {
|
||||
hp:'生命值',atk:'攻击力',def:'防御力',speed:'速度',cpct:'暴击率',cdmg:'暴击伤害',dmg:'伤害加成',stance:'击破特效',effPct:'效果命中'
|
||||
}:{
|
||||
hp:'生命值',atk:'攻击力',def:'防御力',mastery:'元素精通',cpct:'暴击率',cdmg:'暴击伤害',recharge:'元素充能',dmg:'伤害加成'
|
||||
} }}
|
||||
{{set cw = artisDetail?.charWeight || {} }}
|
||||
{{each attrMap title key}}
|
||||
<li>
|
||||
|
||||
<div class="icon"><i class="i-{{key}}"></i></div>
|
||||
|
||||
<div class="title">{{title}}</div>
|
||||
<div class="weight">
|
||||
{{if cw[key]}}
|
||||
<span class="{{cw[key]>=80?'gold':'normal'}}">{{cw[key]}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="value">
|
||||
{{attr[key]}}
|
||||
</div>
|
||||
<div class="value2">
|
||||
<span class="base">{{attr[key+'Base']}}</span>
|
||||
<span class="plus">+{{attr[key+'Plus']}}</span>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<div class="char-weapon">
|
||||
<div class="img" style="background-image:url({{_res_path}}{{weapon.img}})"></div>
|
||||
<div class="head">
|
||||
<strong>{{weapon.name}}</strong>
|
||||
<div class="star star-{{weapon.star}}"></div>
|
||||
<span>Lv.{{weapon.leve || weapon.level}} <span
|
||||
class="affix affix-{{weapon.affix}}">精{{weapon.affix}}</span></span>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<ul class="char-attr">
|
||||
{{set attrMap = {hp:'生命值',atk:'攻击力',def:'防御力',mastery:'元素精通',cpct:'暴击率',cdmg:'暴击伤害',recharge:'元素充能',dmg:'伤害加成'} }}
|
||||
{{set cw = artisDetail?.charWeight || {} }}
|
||||
{{each attrMap title key}}
|
||||
<li>
|
||||
|
||||
<div class="icon"><i class="i-{{key}}"></i></div>
|
||||
|
||||
<div class="title">{{title}}</div>
|
||||
<div class="weight">
|
||||
{{if cw[key]}}
|
||||
<span class="{{cw[key]>=80?'gold':'normal'}}">{{cw[key]}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="value">
|
||||
{{attr[key]}}
|
||||
</div>
|
||||
<div class="value2">
|
||||
<span class="base">{{attr[key+'Base']}}</span>
|
||||
<span class="plus">+{{attr[key+'Plus']}}</span>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<div class="char-weapon">
|
||||
<div class="img" style="background-image:url({{_res_path}}{{weapon.img}})"></div>
|
||||
<div class="head">
|
||||
<strong>{{weapon.name}}</strong>
|
||||
<div class="star star-{{weapon.star}}"></div>
|
||||
<span>Lv.{{weapon.leve || weapon.level}} <span
|
||||
class="affix affix-{{weapon.affix}}">精{{weapon.affix}}</span></span>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="char-cons">
|
||||
{{set cons = [1,2,3,4,5,6]}}
|
||||
{{each cons idx}}
|
||||
<div class="cons-item">
|
||||
<div class="talent-icon {{idx * 1 > data.cons * 1 ? 'off' : '' }}">
|
||||
<div class="talent-icon-img"
|
||||
style="background-image:url({{_res_path}}{{imgs[`cons${idx}`]}})"></div>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
<div class="data-info">
|
||||
{{if data.dataSource}}
|
||||
<span>数据源:{{ {change:"面板变换"}[data.dataSource]||data.dataSource }}</span>
|
||||
{{/if}}
|
||||
{{if data.updateTime}}
|
||||
<span class="time">{{data.updateTime}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if changeProfile}}
|
||||
<div class="cont">
|
||||
<div class="cont-footer dmg-desc">
|
||||
<strong>该面板为非实际数据。当前替换命令:</strong> {{changeProfile}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<!-- 【 武器+圣遗物列表】 -->
|
||||
<div>
|
||||
{{if mode === "profile"}}
|
||||
{{set ad = artisDetail}}
|
||||
<div class="artis">
|
||||
<div>
|
||||
<div class="item weapon">
|
||||
<div class="img" style="background-image:url({{_res_path}}{{weapon.img}})"></div>
|
||||
<div class="head">
|
||||
<strong>{{weapon.name}}</strong>
|
||||
<div class="star star-{{weapon.star}}"></div>
|
||||
<span>Lv.{{weapon.leve || weapon.level}} <span
|
||||
class="affix affix-{{weapon.affix}}">精{{weapon.affix}}</span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item arti-stat">
|
||||
<div class="arti-class-title">评分规则:{{ad.classTitle}}</div>
|
||||
<div class="arti-stat-ret">
|
||||
<div><strong class="mark-{{ad.markClass}}">{{ad.markClass}}</strong><span>圣遗物评级</span></div>
|
||||
<div><strong>{{ad.mark}}</strong><span>圣遗物总分</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{each ad.artis ds idx}}
|
||||
<div class="item arti">
|
||||
{{if ds && ds.name && ds.main && ds.main.key && ds.main.key!="undefined"}}
|
||||
<div class="arti-icon">
|
||||
<div class="img" style="background-image:url({{_res_path}}{{ds.img}})"></div>
|
||||
<span>+{{ds.level}}</span>
|
||||
</div>
|
||||
<div class="head">
|
||||
<strong>{{ds.name}}</strong>
|
||||
<span class="mark mark-{{ds.markClass}}"><span>{{ds.mark}}分</span> - {{ds.markClass}}</span>
|
||||
</div>
|
||||
<ul class="detail attr">
|
||||
<li class="arti-main"><span class="title">{{artisKeyTitle[ds.main?.key]}}</span><span class="val">+{{ds.main.value}}</span>
|
||||
</li>
|
||||
{{each ds.attrs attr}}
|
||||
{{if attr && attr.key}}
|
||||
<li class="{{ad.charWeight[attr.key]*1 > 79.9 ?`great`:(ad.charWeight[attr.key]*1>0 ? `useful`:`nouse`)}}">
|
||||
<span class="title">{{if attr.eff}}<i class="eff">{{attr.eff || ''}}</i>{{/if}}{{if attr.upNum}}<i class="up-num up-{{attr.upNum}}"></i>{{/if}}{{artisKeyTitle[attr.key]}}</span>
|
||||
<span class="val">+{{attr.value}}</span>
|
||||
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="char-cons">
|
||||
{{set cons = [1,2,3,4,5,6]}}
|
||||
{{each cons idx}}
|
||||
<div class="cons-item">
|
||||
<div class="talent-icon {{idx * 1 > data.cons * 1 ? 'off' : '' }}">
|
||||
<div class="talent-icon-img"
|
||||
style="background-image:url({{_res_path}}{{imgs[`cons${idx}`]}})"></div>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
<div class="data-info">
|
||||
{{if data.dataSource}}
|
||||
<span>数据源:{{ {change:"面板变换"}[data.dataSource]||data.dataSource }}</span>
|
||||
{{/if}}
|
||||
{{if data.updateTime}}
|
||||
<span class="time">{{data.updateTime}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 【 伤害表格 】 -->
|
||||
{{ set {dmgRet, dmgCfg, enemyLv, enemyName, dmgMsg, dmgData} = dmgCalc }}
|
||||
<div>
|
||||
{{if mode === "profile"}}
|
||||
{{if changeProfile}}
|
||||
<div class="cont">
|
||||
<div class="cont-footer dmg-desc">
|
||||
当前评分为<strong>喵喵版评分规则</strong>,分值仅供参考与娱乐。可使用<strong>#{{data.abbr}}圣遗物</strong>来查看评分详情
|
||||
<strong>该面板为非实际数据。当前替换命令:</strong> {{changeProfile}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{if dmgData?.length > 0}}
|
||||
<div class="dmg-cont dmg-list cont">
|
||||
<div class="cont-title">
|
||||
伤害计算<span>目标为{{enemyLv}}级{{enemyName||'小宝'}},如需调整等级可使用 #敌人等级{{enemyLv}} 来进行设置</span>
|
||||
</div>
|
||||
<div class="cont-table">
|
||||
<div class="tr thead">
|
||||
<div class="title dmg-idx">#</div>
|
||||
<div class="title dmg-title">伤害类型</div>
|
||||
<div>暴击伤害</div>
|
||||
<div>平均伤害(计算暴击率)</div>
|
||||
<!-- 【 武器+圣遗物列表】 -->
|
||||
<div>
|
||||
{{if game === 'sr'}}
|
||||
<div class="sr-weapon">
|
||||
<div class="weapon-img" style="background-image:url({{_res_path}}{{weapon.splash}})"></div>
|
||||
<div class="weapon-info">
|
||||
<div class="weapon-title">
|
||||
<strong>{{weapon.name}}</strong>
|
||||
<span>Lv.{{weapon.level}}</span>
|
||||
<span>叠影{{weapon.affix}}阶</span>
|
||||
</div>
|
||||
<div class="weapon-attr">
|
||||
{{set a = weapon.attrs}}
|
||||
<div class="attr i-hp"><span>生命</span>{{a.hp}}</div>
|
||||
<div class="attr i-atk"><span>攻击</span>{{a.atk}}</div>
|
||||
<div class="attr i-def"><span>防御</span>{{a.def}}</div>
|
||||
</div>
|
||||
<div class="weapon-desc">{{@weapon.desc?.desc}}</div>
|
||||
</div>
|
||||
{{each dmgData dmg idx}}
|
||||
<div class="dmg tr">
|
||||
<div class="title dmg-idx">{{idx+1}}</div>
|
||||
<div class="title dmg-title">{{dmg.title}}</div>
|
||||
{{if dmg.dmg === "NaN"}}
|
||||
<div class="value value-full">{{dmg.avg}}{{dmg.unit}}</div>
|
||||
<div class="value value-none"></div>
|
||||
{{else}}
|
||||
<div class="value">{{dmg.dmg}}{{dmg.unit}}</div>
|
||||
<div class="value">{{dmg.avg}}{{dmg.unit}}</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{if mode === "profile"}}
|
||||
{{set ad = artisDetail}}
|
||||
<div class="artis">
|
||||
{{ if game === 'gs' }}
|
||||
<div class="artis-weapon">
|
||||
<div class="item weapon">
|
||||
<div class="img" style="background-image:url({{_res_path}}{{weapon.img}})"></div>
|
||||
<div class="head">
|
||||
<strong>{{weapon.name}}</strong>
|
||||
<div class="star star-{{weapon.star}}"></div>
|
||||
<span>Lv.{{weapon.leve || weapon.level}} <span
|
||||
class="affix affix-{{weapon.affix}}">精{{weapon.affix}}</span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item arti-stat">
|
||||
<div class="arti-class-title">评分规则:{{ad.classTitle}}</div>
|
||||
<div class="arti-stat-ret">
|
||||
<div><strong class="mark-{{ad.markClass}}">{{ad.markClass}}</strong><span>圣遗物评级</span></div>
|
||||
<div><strong>{{ad.mark}}</strong><span>圣遗物总分</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{each ad.artis ds idx}}
|
||||
<div class="item arti">
|
||||
{{if ds && ds.name && ds.main && ds.main.key && ds.main.key!="undefined"}}
|
||||
<div class="arti-icon">
|
||||
<div class="img" style="background-image:url({{_res_path}}{{ds.img}})"></div>
|
||||
<span>+{{ds.level}}</span>
|
||||
</div>
|
||||
<div class="head">
|
||||
<strong>{{ds.abbr || ds.name}}</strong>
|
||||
<span class="mark mark-{{ds.markClass}}"><span>{{ds.mark}}分</span> - {{ds.markClass}}</span>
|
||||
</div>
|
||||
<ul class="detail attr">
|
||||
<li class="arti-main"><span class="title">{{artisKeyTitle[ds.main?.key]}}</span><span class="val">+{{ds.main.value}}</span>
|
||||
</li>
|
||||
{{each ds.attrs attr}}
|
||||
{{if attr && attr.key}}
|
||||
<li class="{{ad.charWeight[attr.key]*1 > 79.9 ?`great`:(ad.charWeight[attr.key]*1>0 ? `useful`:`nouse`)}}">
|
||||
<span class="title">{{if attr.eff}}<i class="eff">{{attr.eff || ''}}</i>{{/if}}{{if attr.upNum}}<i
|
||||
class="up-num up-{{attr.upNum}}"></i>{{/if}}{{artisKeyTitle[attr.key] || attr.key}}</span>
|
||||
<span class="val">+{{attr.value}}</span>
|
||||
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="cont-footer dmg-desc">
|
||||
使用命令<strong>#{{data.abbr}}伤害</strong>可以查看伤害详情,使用命令<strong>#角色面板帮助</strong>可查看帮助说明
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<!-- 【 伤害变化详情 】 -->
|
||||
<div>
|
||||
{{if mode === "dmg"}}
|
||||
{{if dmgCfg && dmgCfg.attr && dmgCfg.attr.length>0 && dmgRet}}
|
||||
<div class="dmg-calc dmg-cont cont">
|
||||
<div class="cont-title">
|
||||
词条伤害计算<span>#{{data.abbr}}伤害{{dmgCfg.userIdx+1}}: 当前计算为[{{dmgCfg.title}}]</span>
|
||||
|
||||
<!-- 【 伤害表格 】 -->
|
||||
{{ set {dmgRet, dmgCfg, enemyLv, enemyName, dmgMsg, dmgData} = dmgCalc }}
|
||||
<div>
|
||||
{{if game === 'gs'}}
|
||||
{{if mode === "profile"}}
|
||||
<div class="cont">
|
||||
<div class="cont-footer dmg-desc">
|
||||
当前评分为<strong>喵喵版评分规则</strong>,分值仅供参考与娱乐。可使用<strong>{{gameHash}}{{data.abbr}}圣遗物</strong>来查看评分详情
|
||||
</div>
|
||||
</div>
|
||||
<div class="cont-table">
|
||||
<div class="tr thead ">
|
||||
<div class="td">词条变化</div>
|
||||
{{each dmgCfg.attr attr}}
|
||||
<div class="td">
|
||||
<strong>{{attr.title}}</strong>
|
||||
<span>+{{attr.text}}</span>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<div class="cont">
|
||||
<div class="cont-footer dmg-desc">
|
||||
<strong>伤害计算、圣遗物评分及词条数功能尚未完成...</strong>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{if dmgData?.length > 0}}
|
||||
<div class="dmg-cont dmg-list cont">
|
||||
<div class="cont-title">
|
||||
伤害计算<span>目标为{{enemyLv}}级{{enemyName||'小宝'}}{{if game==='gs'}},如需调整等级可使用 #敌人等级{{enemyLv}} 来进行设置{{/if}}</span>
|
||||
</div>
|
||||
<div class="cont-table">
|
||||
<div class="tr thead">
|
||||
<div class="title dmg-idx">#</div>
|
||||
<div class="title dmg-title">伤害类型</div>
|
||||
<div>暴击伤害</div>
|
||||
<div>期望伤害</div>
|
||||
</div>
|
||||
{{each dmgData dmg idx}}
|
||||
<div class="dmg tr">
|
||||
<div class="title dmg-idx">{{idx+1}}</div>
|
||||
<div class="title dmg-title">{{dmg.title}}</div>
|
||||
{{if !dmg.dmg || dmg.dmg === "NaN"}}
|
||||
<div class="value value-full">{{dmg.avg}}{{dmg.unit}}</div>
|
||||
<div class="value value-none"></div>
|
||||
{{else}}
|
||||
<div class="value">{{dmg.dmg}}{{dmg.unit}}</div>
|
||||
<div class="value">{{dmg.avg}}{{dmg.unit}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{each dmgRet row rowIdx}}
|
||||
<div class="tr">
|
||||
<div class="title">
|
||||
<strong>{{dmgCfg.attr[rowIdx].title}}</strong>
|
||||
<span>-{{dmgCfg.attr[rowIdx].text}}</span>
|
||||
</div>
|
||||
{{each row cell colIdx}}
|
||||
{{if cell.type === "na"}}
|
||||
<div class="td na">
|
||||
<strong>-</strong>
|
||||
<span>{{dmgCfg.basicRet.avg}}{{dmgCfg.basicRet.dmg!="NaN"?`/${dmgCfg.basicRet.dmg}`:''}}</span>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="td {{cell.type}}">
|
||||
<strong>{{cell.val}}</strong>
|
||||
<div class="cont-footer dmg-desc">
|
||||
使用命令<strong>{{gameHash}}{{data.abbr}}伤害</strong>可以查看伤害详情,使用命令<strong>#角色面板帮助</strong>可查看帮助说明
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<span>{{cell.avg}}{{cell.dmg!="NaN"?`/${cell.dmg}`:''}}</span>
|
||||
<!-- 【 伤害变化详情 】 -->
|
||||
<div>
|
||||
{{if mode === "dmg"}}
|
||||
{{if dmgCfg && dmgCfg.attr && dmgCfg.attr.length>0 && dmgRet}}
|
||||
<div class="dmg-calc dmg-cont cont">
|
||||
<div class="cont-title">
|
||||
词条伤害计算<span>{{gameHash}}{{data.abbr}}伤害{{dmgCfg.userIdx+1}}: 当前计算为[{{dmgCfg.title}}]</span>
|
||||
</div>
|
||||
<div class="cont-table">
|
||||
<div class="tr thead ">
|
||||
<div class="td">词条变化</div>
|
||||
{{each dmgCfg.attr attr}}
|
||||
<div class="td">
|
||||
<strong>{{attr?.title}}</strong>
|
||||
<span>+{{attr?.text}}</span>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{each dmgRet row rowIdx}}
|
||||
<div class="tr">
|
||||
<div class="title">
|
||||
<strong>{{dmgCfg.attr[rowIdx].title}}</strong>
|
||||
<span>-{{dmgCfg.attr[rowIdx].text}}</span>
|
||||
</div>
|
||||
{{each row cell colIdx}}
|
||||
{{if cell.type === "na"}}
|
||||
<div class="td na">
|
||||
<strong>-</strong>
|
||||
<span>{{dmgCfg.basicRet.avg}}{{(dmgCfg.basicRet.dmg&&dmgCfg.basicRet.dmg!="NaN")?`/${dmgCfg.basicRet.dmg}`:''}}</span>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="td {{cell.type}}">
|
||||
<strong>{{cell.val}}</strong>
|
||||
|
||||
<span>{{cell.avg}}{{cell.dmg!="NaN"?`/${cell.dmg}`:''}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="cont-footer dmg-desc">
|
||||
<ul>
|
||||
<li>大数字的含义为圣遗物副词条置换后<strong>平均伤害</strong>的变化,下方的详情数字为<strong>平均伤害</strong>/<strong>暴击伤害</strong>。</li>
|
||||
<li>关于<strong>平均伤害</strong>:是将暴击率计算在内的伤害期望,能反映综合的输出能力,不等于实际伤害数字。</li>
|
||||
<li>可用于评估当前面板下圣遗物副词条的侧重方向。实际游戏情况更加复杂,结果供参考~</li>
|
||||
<li>如需更换计算的伤害类型,可使用命令 <strong>#{{data.abbr}}伤害+序号</strong>来切换,序号参见伤害计算板块</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="dmg-cont dmg-msg cont">
|
||||
<div class="cont-title">Buff列表<span>部分Buff的触发条件以及层数可能影响实际伤害结果</span></div>
|
||||
<div class="cont-table">
|
||||
{{each dmgMsg msg}}
|
||||
<div class="tr">
|
||||
<div class="th">{{msg[0]}}</div>
|
||||
<div class="td">{{msg[1]}}</div>
|
||||
<div class="cont-footer dmg-desc">
|
||||
<ul>
|
||||
<li>大数字的含义为圣遗物副词条置换后<strong>平均伤害</strong>的变化,下方的详情数字为<strong>平均伤害</strong>/<strong>暴击伤害</strong>。</li>
|
||||
<li>关于<strong>平均伤害</strong>:是将暴击率计算在内的伤害期望,能反映综合的输出能力,不等于实际伤害数字。</li>
|
||||
<li>可用于评估当前面板下圣遗物副词条的侧重方向。实际游戏情况更加复杂,结果供参考~</li>
|
||||
<li>如需更换计算的伤害类型,可使用命令 <strong>{{gameHash}}{{data.abbr}}伤害+序号</strong>来切换,序号参见伤害计算板块</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="dmg-cont dmg-msg cont">
|
||||
<div class="cont-title">Buff列表<span>部分Buff的触发条件以及层数可能影响实际伤害结果</span></div>
|
||||
<div class="cont-table">
|
||||
{{each dmgMsg msg}}
|
||||
<div class="tr">
|
||||
<div class="th">{{msg[0]}}</div>
|
||||
<div class="td">{{msg[1]}}</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/block}}
|
@ -183,6 +183,8 @@ body {
|
||||
background-position: @i*-4 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.i-cpct {
|
||||
background-position: @i*-5 0;
|
||||
}
|
||||
@ -190,6 +192,9 @@ body {
|
||||
.i-cdmg {
|
||||
background-position: @i*-6 0;
|
||||
}
|
||||
.i-stance {
|
||||
background-position: @i*-4 0;
|
||||
}
|
||||
|
||||
.i-recharge {
|
||||
background-position: @i*-7 0;
|
||||
@ -199,6 +204,18 @@ body {
|
||||
background-position: @i*-8 0;
|
||||
}
|
||||
|
||||
.i-heal {
|
||||
background-position: @i*-9 0;
|
||||
}
|
||||
|
||||
.i-speed {
|
||||
background-position: @i*-10 0;
|
||||
}
|
||||
|
||||
.i-effPct {
|
||||
background-position: @i*-11 0;
|
||||
}
|
||||
|
||||
.detail.attr {
|
||||
li {
|
||||
&:nth-child(even) {
|
||||
@ -1029,4 +1046,145 @@ body {
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.game-sr {
|
||||
.char-talents {
|
||||
transform: scale(.8);
|
||||
transform-origin: top left;
|
||||
margin: -8px 0 -14px;
|
||||
|
||||
|
||||
.talent-item {
|
||||
margin: 0 -3px;
|
||||
}
|
||||
}
|
||||
|
||||
.artis-weapon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.char-attr {
|
||||
.icon i {
|
||||
background-image: url('./imgs/icon-sr.png');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sr-weapon {
|
||||
margin: 0 15px 5px 10px;
|
||||
border-radius: 10px;
|
||||
background: url("../common/cont/card-bg.png") top left repeat-x;
|
||||
background-size: auto 150%;
|
||||
position: relative;
|
||||
box-shadow: 0 0 1px 0 #ccc, 2px 2px 4px 0 rgba(50, 50, 50, .8);
|
||||
overflow: hidden;
|
||||
display: table;
|
||||
color: #fff;
|
||||
min-height: 120px;
|
||||
width: calc(100% - 25px);
|
||||
|
||||
.weapon-img {
|
||||
display: table-cell;
|
||||
width: 185px;
|
||||
height: 100%;
|
||||
min-height: 120px;
|
||||
background-size: 100% auto;
|
||||
background-position: 0 5%;
|
||||
box-shadow: 0 0 1px 0 #ccc, 2px 2px 4px 0 rgba(50, 50, 50, .8);
|
||||
}
|
||||
|
||||
.weapon-info {
|
||||
display: table-cell;
|
||||
padding: 10px 10px 5px 15px;
|
||||
}
|
||||
|
||||
.weapon-title {
|
||||
|
||||
span {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
strong {
|
||||
color: #d3bc8e;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.weapon-attr {
|
||||
font-size: 12px;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
display: flex;
|
||||
|
||||
.attr {
|
||||
padding-left: 22px;
|
||||
padding-right: 7px;
|
||||
margin-right: 10px;
|
||||
position: relative;
|
||||
line-height: 22px;
|
||||
height: 22px;
|
||||
font-size: 12px;
|
||||
|
||||
color: #ffe699;
|
||||
display: inline-block;
|
||||
border-radius: 4px;
|
||||
|
||||
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
text-align: center;
|
||||
|
||||
span {
|
||||
font-size: 12px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
background-size: auto 100%;
|
||||
background-position: top center;
|
||||
vertical-align: middle;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.i-hp:before {
|
||||
background-image: url('../meta-sr/public/icons/attr-hp.webp')
|
||||
}
|
||||
|
||||
.i-atk:before {
|
||||
background-image: url('../meta-sr/public/icons/attr-atk.webp')
|
||||
}
|
||||
|
||||
.i-def:before {
|
||||
background-image: url('../meta-sr/public/icons/attr-def.webp')
|
||||
}
|
||||
}
|
||||
|
||||
.weapon-desc {
|
||||
margin-top: 7px;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
color: #fff;
|
||||
white-space: break-spaces;
|
||||
text-shadow: 0 0 1px rgba(0, 0, 0, 0.7), 1px 1px 3px rgba(0, 0, 0, 0.4);
|
||||
|
||||
nobr {
|
||||
color: #ffe699;
|
||||
display: inline-block;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
text-align: center;
|
||||
padding: 0 3px;
|
||||
margin: 0 2px;
|
||||
}
|
||||
}
|
||||
}
|
BIN
resources/common/bg/bg-sr.jpg
Normal file
After Width: | Height: | Size: 315 KiB |
@ -1,21 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-cn">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link rel="shortcut icon" href="#"/>
|
||||
<link rel="preload" href="{{_miao_path}}common/font/HYWH-65W.woff" as="font" type="font/woff">
|
||||
<link rel="preload" href="{{_miao_path}}common/font/NZBZ.woff" as="font" type="font/woff">
|
||||
<link rel="preload" href="{{_miao_path}}common/font/tttgbnumber.woff" as="font" type="font/woff">
|
||||
<link rel="stylesheet" type="text/css" href="{{_miao_path}}common/common.css"/>
|
||||
<title>miao-plugin</title>
|
||||
{{block 'css'}}
|
||||
{{/block}}
|
||||
</head>
|
||||
<body class="elem-{{element||elem||`hydro`}} {{displayMode || mode || `default`}}-mode {{bodyClass}}" {{sys.scale}}>
|
||||
<div class="container elem-bg" id="container">
|
||||
{{block 'main'}}{{/block}}
|
||||
<div class="copyright">{{@copyright || sys?.copyright}}</div>
|
||||
</div>
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<link rel="shortcut icon" href="#"/>
|
||||
<link rel="preload" href="{{_miao_path}}common/font/HYWH-65W.woff" as="font" type="font/woff">
|
||||
<link rel="preload" href="{{_miao_path}}common/font/NZBZ.woff" as="font" type="font/woff">
|
||||
<link rel="preload" href="{{_miao_path}}common/font/tttgbnumber.woff" as="font" type="font/woff">
|
||||
<link rel="stylesheet" type="text/css" href="{{_miao_path}}common/common.css"/>
|
||||
<title>miao-plugin</title>
|
||||
{{block 'css'}}
|
||||
{{/block}}
|
||||
</head>
|
||||
{{set elemCls = {火:'pyro',冰:'cryo',风:'anemo',雷:'electro',量子:'electro',虚数:'geo',物理:'hydro', }[element||elem] || element || elem || 'hydro' }}
|
||||
<body class="elem-{{elemCls}} {{displayMode || mode || `default`}}-mode {{bodyClass}}" {{sys.scale}}>
|
||||
<div class="container elem-bg" id="container">
|
||||
{{block 'main'}}{{/block}}
|
||||
<div class="copyright">{{@copyright || sys?.copyright}}</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
155
resources/meta-sr/artifact/calc.js
Normal file
@ -0,0 +1,155 @@
|
||||
let attr = (key, val) => {
|
||||
let data = {}
|
||||
data[key] = val
|
||||
return {
|
||||
isStatic: true,
|
||||
data
|
||||
}
|
||||
}
|
||||
export default {
|
||||
云无留迹的过客: {
|
||||
2: attr('heal', 10)
|
||||
},
|
||||
野穗伴行的快枪手: {
|
||||
2: attr('atkPct', 12),
|
||||
4: [attr('speed', 6), {
|
||||
title: '普攻伤害提高10%',
|
||||
data: {
|
||||
aDmg: 10
|
||||
}
|
||||
}]
|
||||
},
|
||||
净庭教宗的圣骑士: {
|
||||
2: attr('defPct', 15),
|
||||
4: {
|
||||
title: '护盾强效提高20%',
|
||||
data: {
|
||||
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)
|
||||
}
|
||||
}
|
36
resources/meta-sr/artifact/index.js
Normal file
@ -0,0 +1,36 @@
|
||||
import { Data } from '#miao'
|
||||
import lodash from 'lodash'
|
||||
import artisBuffs from './calc.js'
|
||||
|
||||
let data = Data.readJSON('/resources/meta-sr/artifact/data.json', 'miao')
|
||||
let meta = Data.readJSON('/resources/meta-sr/artifact/meta.json', 'miao')
|
||||
|
||||
let artiMap = {}
|
||||
let idMap = {}
|
||||
let artiSetMap = {}
|
||||
lodash.forEach(data, (setData) => {
|
||||
let artiSet = {
|
||||
name: setData.name,
|
||||
effect: setData.skill,
|
||||
sets: {}
|
||||
}
|
||||
artiSetMap[setData.name] = artiSet
|
||||
|
||||
lodash.forEach(setData.idxs, (ds, idx) => {
|
||||
artiMap[ds.name] = {
|
||||
...ds,
|
||||
set: setData.name,
|
||||
setId: setData.id,
|
||||
idx
|
||||
}
|
||||
idMap[ds.name] = artiMap[ds.name]
|
||||
lodash.forEach(ds.ids, (star, id) => {
|
||||
idMap[id] = artiMap[ds.name]
|
||||
})
|
||||
artiSet.sets[idx] = ds.name
|
||||
})
|
||||
})
|
||||
|
||||
export const metaData = meta
|
||||
export { artiMap, idMap, artisBuffs, artiSetMap }
|
||||
export * from './meta.js'
|
81
resources/meta-sr/artifact/meta.js
Normal file
@ -0,0 +1,81 @@
|
||||
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(','),
|
||||
5: 'atk,def,hp,dmg'.split(','),
|
||||
6: 'atk,def,hp,recharge,stance'.split(',')
|
||||
}
|
||||
|
||||
export const subAttr = 'atk,atkPlus,def,defPlus,hp,hpPlus,speed,cpct,cdmg,effPct,effDef,stance'.split(',')
|
||||
|
||||
/**
|
||||
* 圣遗物词条配置
|
||||
* @[]value 副词条单次提升值(最大档位)
|
||||
* @[]valueMin 副词条单次提升最小值
|
||||
* @[]calc 伤害计算时变更的字段type
|
||||
* @[]type 词条的类型 normal:普通字段 plus:小词条
|
||||
* @[]base 词条类型为小词条时,对应的大词条
|
||||
* @[]text 展示文字
|
||||
*/
|
||||
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', 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 = {
|
||||
快枪手的野穗毡帽: '快枪手的毡帽',
|
||||
快枪手的粗革手套: '快枪手的手套',
|
||||
快枪手的猎风披肩: '快枪手的披肩',
|
||||
快枪手的铆钉马靴: '快枪手的铆钉靴',
|
||||
废土客的呼吸面罩: '废土客的面罩',
|
||||
废土客的荒漠终端: '废土客的终端',
|
||||
废土客的修士长袍: '废土客的长袍',
|
||||
废土客的动力腿甲: '废土客的腿甲',
|
||||
'「黑塔」的空间站点': '黑塔的空间站点',
|
||||
'「黑塔」的漫历轨迹': '黑塔的漫历轨迹',
|
||||
罗浮仙舟的天外楼船: '罗浮仙舟的楼船',
|
||||
罗浮仙舟的建木枝蔓: '罗浮仙舟的建木',
|
||||
贝洛伯格的存护堡垒: '贝洛伯格的堡垒',
|
||||
贝洛伯格的铁卫防线: '贝洛伯格的防线',
|
||||
螺丝星的机械烈阳: '螺丝星的烈阳',
|
||||
螺丝星的环星孔带: '螺丝星的孔带',
|
||||
萨尔索图的移动城市: '萨尔索图的城市',
|
||||
萨尔索图的晨昏界线: '萨尔索图的界线',
|
||||
塔利亚的钉壳小镇: '塔利亚的小镇',
|
||||
塔利亚的裸皮电线: '塔利亚的电线',
|
||||
翁瓦克的诞生之岛: '翁瓦克的诞生岛',
|
||||
翁瓦克的环岛海岸: '翁瓦克的海岸'
|
||||
}
|
42
resources/meta-sr/character/meta.js
Normal file
@ -0,0 +1,42 @@
|
||||
import lodash from 'lodash'
|
||||
|
||||
let alias = {
|
||||
三月七: '三月,相遇之缘,37,3月7',
|
||||
丹恒: '单恒,单桓,冷面,小青龙,冷面小青龙',
|
||||
佩拉: '佩菈',
|
||||
停云: '',
|
||||
克拉拉: '',
|
||||
卡夫卡: '亲妈',
|
||||
姬子: '',
|
||||
娜塔莎: '纳塔莎,纳塔沙,纳塔沙',
|
||||
布洛妮娅: '大鸭鸭,鸭鸭,板鸭,布洛尼亚,布洛妮亚,布洛尼娅',
|
||||
希儿: '希尔,蝴蝶,云天明',
|
||||
希露瓦: '希璐瓦',
|
||||
彦卿: '延卿,闫卿,彦清,彦青',
|
||||
景元: '景原,景源,神君发射器',
|
||||
杰帕德: '',
|
||||
桑博: '桑柏,桑伯',
|
||||
瓦尔特: '老杨,杨叔,瓦尔特杨',
|
||||
白露: '小龙人',
|
||||
素裳: '',
|
||||
罗刹: '罗沙,罗杀',
|
||||
艾丝妲: '宇宙级富婆',
|
||||
虎克: '胡可,虎克大人,漆黑的虎克,漆黑的虎克大人,鼹鼠党,鼹鼠党老大',
|
||||
银狼: '小鸭鸭,小板鸭,黑客,骇客,骇兔',
|
||||
阿兰: '',
|
||||
青雀: '赌神,赌圣,青鹊',
|
||||
黑塔: ''
|
||||
}
|
||||
|
||||
let aliasMap = {}
|
||||
lodash.forEach(alias, (txt, char) => {
|
||||
if (!txt) {
|
||||
return true
|
||||
}
|
||||
lodash.forEach(txt.split(','), (t) => {
|
||||
aliasMap[t] = char
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
export { aliasMap }
|
@ -398,6 +398,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1001201": {
|
||||
"key": "ice",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1001202": {
|
||||
"key": "def",
|
||||
"value": 5.000000004656613
|
||||
},
|
||||
"1001203": {
|
||||
"key": "ice",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1001204": {
|
||||
"key": "effDef",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1001205": {
|
||||
"key": "ice",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1001206": {
|
||||
"key": "effDef",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1001207": {
|
||||
"key": "def",
|
||||
"value": 7.499999972060323
|
||||
},
|
||||
"1001208": {
|
||||
"key": "ice",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1001209": {
|
||||
"key": "ice",
|
||||
"value": 6.399999978020787
|
||||
},
|
||||
"1001210": {
|
||||
"key": "def",
|
||||
"value": 10.000000009313226
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"877640": {
|
||||
"id": 877640,
|
||||
"type": "skill",
|
||||
|
Before Width: | Height: | Size: 831 KiB After Width: | Height: | Size: 554 KiB |
39
resources/meta-sr/character/丹恒/calc.js
Normal file
@ -0,0 +1,39 @@
|
||||
export const details = [{
|
||||
title: 'A普攻伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.a['技能伤害'], 'a')
|
||||
}, {
|
||||
title: 'E战技主目标伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.e['技能伤害'], 'e')
|
||||
}, {
|
||||
title: 'Q终结技伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.q['技能伤害'], 'q')
|
||||
}, {
|
||||
title: '减速目标终结技伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.q['技能伤害'] + talent.q['减速目标q伤害倍率提高'], 'q')
|
||||
}]
|
||||
|
||||
export const mainAttr = 'atk,cpct,cdmg'
|
||||
|
||||
export const buffs = [{
|
||||
title: '丹恒天赋:丹恒成为我方技能的目标时提高抗性穿透[kx]%',
|
||||
data: {
|
||||
kx: ({ talent }) => talent.t['风抗性穿透']
|
||||
}
|
||||
}, {
|
||||
title: '丹恒秘技:使用秘技提高40%攻击力',
|
||||
data: {
|
||||
atkPct: 40
|
||||
}
|
||||
}, {
|
||||
title: '丹恒1命:击中目标生命值大于50%,暴击率提高12%',
|
||||
cons: 1,
|
||||
data: {
|
||||
cpct: 12
|
||||
}
|
||||
}, {
|
||||
title: '行迹-罡风:普攻对减速状态下的敌方目标造成的伤害提高40%',
|
||||
tree: 3,
|
||||
data: {
|
||||
aDmg: 40
|
||||
}
|
||||
}]
|
@ -377,6 +377,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1002201": {
|
||||
"key": "wind",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1002202": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1002203": {
|
||||
"key": "wind",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1002204": {
|
||||
"key": "def",
|
||||
"value": 5.000000004656613
|
||||
},
|
||||
"1002205": {
|
||||
"key": "wind",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1002206": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1002207": {
|
||||
"key": "wind",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1002208": {
|
||||
"key": "def",
|
||||
"value": 7.499999972060323
|
||||
},
|
||||
"1002209": {
|
||||
"key": "atk",
|
||||
"value": 8.00000000745058
|
||||
},
|
||||
"1002210": {
|
||||
"key": "wind",
|
||||
"value": 6.399999978020787
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"124180": {
|
||||
"id": 124180,
|
||||
"type": "buff",
|
||||
|
Before Width: | Height: | Size: 870 KiB After Width: | Height: | Size: 452 KiB |
@ -377,6 +377,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1106201": {
|
||||
"key": "ice",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1106202": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1106203": {
|
||||
"key": "ice",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1106204": {
|
||||
"key": "effPct",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1106205": {
|
||||
"key": "ice",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1106206": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1106207": {
|
||||
"key": "ice",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1106208": {
|
||||
"key": "effPct",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1106209": {
|
||||
"key": "atk",
|
||||
"value": 8.00000000745058
|
||||
},
|
||||
"1106210": {
|
||||
"key": "ice",
|
||||
"value": 6.399999978020787
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"660958": {
|
||||
"id": 660958,
|
||||
"type": "skill",
|
||||
|
Before Width: | Height: | Size: 855 KiB After Width: | Height: | Size: 534 KiB |
31
resources/meta-sr/character/停云/calc.js
Normal file
@ -0,0 +1,31 @@
|
||||
import { Format } from '#miao'
|
||||
|
||||
export const details = [{
|
||||
title: '普攻伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.a['技能伤害'], 'a')
|
||||
}, {
|
||||
title: 'E赐福提高攻击力上限',
|
||||
dmg: ({ attr, calc, talent }) => {
|
||||
return {
|
||||
avg: calc(attr.atk) * talent.e['攻击力上限']
|
||||
}
|
||||
}
|
||||
}, {
|
||||
title: 'Q伤害提高',
|
||||
dmg: ({ talent }) => {
|
||||
return {
|
||||
avg: Format.percent(talent.q['伤害提高']),
|
||||
type: 'text'
|
||||
}
|
||||
}
|
||||
}]
|
||||
|
||||
export const mainAttr = 'atk,cpct,cdmg'
|
||||
|
||||
export const buffs = [{
|
||||
title: '行迹-止厄:普攻造成的伤害提高40%',
|
||||
tree: 2,
|
||||
data: {
|
||||
aDmg: 40
|
||||
}
|
||||
}]
|
@ -398,6 +398,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1202201": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1202202": {
|
||||
"key": "def",
|
||||
"value": 5.000000004656613
|
||||
},
|
||||
"1202203": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1202204": {
|
||||
"key": "elec",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1202205": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1202206": {
|
||||
"key": "def",
|
||||
"value": 7.499999972060323
|
||||
},
|
||||
"1202207": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1202208": {
|
||||
"key": "elec",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1202209": {
|
||||
"key": "def",
|
||||
"value": 10.000000009313226
|
||||
},
|
||||
"1202210": {
|
||||
"key": "atk",
|
||||
"value": 8.00000000745058
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"264650": {
|
||||
"id": 264650,
|
||||
"type": "buff",
|
||||
|
Before Width: | Height: | Size: 541 KiB After Width: | Height: | Size: 353 KiB |
29
resources/meta-sr/character/克拉拉/calc.js
Normal file
@ -0,0 +1,29 @@
|
||||
export const details = [{
|
||||
title: 'A普攻伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.a['技能伤害'], 'a')
|
||||
}, {
|
||||
title: 'E战技伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.e['技能伤害'], 'e')
|
||||
}, {
|
||||
title: 'E反击伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.e['反击伤害'], 'e')
|
||||
}, {
|
||||
title: 'Q反击伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.q['伤害倍率提高'] + talent.t['反击伤害'], 't')
|
||||
}]
|
||||
|
||||
export const mainAttr = 'atk,cpct,cdmg,speed'
|
||||
|
||||
export const buffs = [{
|
||||
title: '克拉拉2命:施放终结技后攻击力提高30%',
|
||||
cons: 2,
|
||||
data: {
|
||||
atkPct: 30
|
||||
}
|
||||
}, {
|
||||
title: '行迹-复仇:史瓦罗的反击造成的伤害提高30%',
|
||||
tree: 3,
|
||||
data: {
|
||||
tDmg: 30
|
||||
}
|
||||
}]
|
@ -398,6 +398,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1107201": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1107202": {
|
||||
"key": "phy",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1107203": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1107204": {
|
||||
"key": "hp",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1107205": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1107206": {
|
||||
"key": "phy",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1107207": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1107208": {
|
||||
"key": "hp",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1107209": {
|
||||
"key": "phy",
|
||||
"value": 6.399999978020787
|
||||
},
|
||||
"1107210": {
|
||||
"key": "atk",
|
||||
"value": 8.00000000745058
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"864032": {
|
||||
"id": 864032,
|
||||
"type": "buff",
|
||||
|
Before Width: | Height: | Size: 476 KiB After Width: | Height: | Size: 270 KiB |
@ -458,6 +458,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1005201": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1005202": {
|
||||
"key": "stance",
|
||||
"value": 5.299999983981252
|
||||
},
|
||||
"1005203": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1005204": {
|
||||
"key": "hp",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1005205": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1005206": {
|
||||
"key": "stance",
|
||||
"value": 8.00000000745058
|
||||
},
|
||||
"1005207": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1005208": {
|
||||
"key": "hp",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1005209": {
|
||||
"key": "stance",
|
||||
"value": 10.699999961070716
|
||||
},
|
||||
"1005210": {
|
||||
"key": "atk",
|
||||
"value": 8.00000000745058
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"227636": {
|
||||
"id": 227636,
|
||||
"type": "skill",
|
||||
|
Before Width: | Height: | Size: 448 KiB After Width: | Height: | Size: 287 KiB |
46
resources/meta-sr/character/姬子/calc.js
Normal file
@ -0,0 +1,46 @@
|
||||
export const details = [{
|
||||
title: 'A普攻伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.a['技能伤害'], 'a')
|
||||
}, {
|
||||
title: 'E战技主目标伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.e['主目标伤害'], 'e')
|
||||
}, {
|
||||
title: 'Q终结技伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.q['技能伤害'], 'q')
|
||||
}, {
|
||||
title: '天赋追击伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.t['技能伤害'], 't')
|
||||
}]
|
||||
|
||||
export const mainAttr = 'atk,cpct,cdmg,speed'
|
||||
|
||||
export const buffs = [{
|
||||
title: '姬子秘技:释放领域使敌方受到伤害提高10%',
|
||||
data: {
|
||||
dmg: 10
|
||||
}
|
||||
}, {
|
||||
title: '姬子1命:对生命小于50%的敌人伤害提高15%',
|
||||
cons: 1,
|
||||
data: {
|
||||
dmg: 15
|
||||
}
|
||||
}, {
|
||||
title: '希儿2命:释放战技后,2层Buff速度提高50%',
|
||||
cons: 2,
|
||||
data: {
|
||||
speedPct: 50
|
||||
}
|
||||
}, {
|
||||
title: '行迹-灼热:战技对灼烧状态下的敌方目标造成的伤害提高20%',
|
||||
tree: 2,
|
||||
data: {
|
||||
eDmg: 20
|
||||
}
|
||||
}, {
|
||||
title: '行迹-道标:生命值大于80%时提高暴击率15%',
|
||||
tree: 3,
|
||||
data: {
|
||||
cpct: 15
|
||||
}
|
||||
}]
|
@ -377,13 +377,55 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1003201": {
|
||||
"key": "fire",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1003202": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1003203": {
|
||||
"key": "fire",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1003204": {
|
||||
"key": "effDef",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1003205": {
|
||||
"key": "fire",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1003206": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1003207": {
|
||||
"key": "fire",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1003208": {
|
||||
"key": "effDef",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1003209": {
|
||||
"key": "atk",
|
||||
"value": 8.00000000745058
|
||||
},
|
||||
"1003210": {
|
||||
"key": "fire",
|
||||
"value": 6.399999978020787
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"202642": {
|
||||
"id": 202642,
|
||||
"type": "skill",
|
||||
"root": true,
|
||||
"name": "星火",
|
||||
"levelReq": 0,
|
||||
"desc": "施放攻击后,有<nobr>50.0%</nobr>的基础概率使敌方目标陷入灼烧状态,持续<nobr>2</nobr>回合。<br />灼烧状态下,敌方目标每回合开始时受到等同于姬子<nobr>30.0%</nobr>攻击力的<span style=\"color:#F84F36;\">火</span>属性持续伤害。",
|
||||
"desc": "施放攻击后,有<nobr>50.0%</nobr>的基础概率使敌方目标陷入灼烧状态,持续<nobr>2</nobr>回合。<br />灼烧状态下,敌方目标每回合开始时受到等同于姬子<nobr>30.0%</nobr>攻击力的<span>火</span>属性持续伤害。",
|
||||
"cost": {
|
||||
"29328": 5000,
|
||||
"635675": 3,
|
||||
|
Before Width: | Height: | Size: 707 KiB After Width: | Height: | Size: 358 KiB |
@ -440,6 +440,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1105201": {
|
||||
"key": "hp",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1105202": {
|
||||
"key": "effDef",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1105203": {
|
||||
"key": "hp",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1105204": {
|
||||
"key": "def",
|
||||
"value": 5.000000004656613
|
||||
},
|
||||
"1105205": {
|
||||
"key": "hp",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1105206": {
|
||||
"key": "effDef",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1105207": {
|
||||
"key": "hp",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1105208": {
|
||||
"key": "def",
|
||||
"value": 7.499999972060323
|
||||
},
|
||||
"1105209": {
|
||||
"key": "effDef",
|
||||
"value": 8.00000000745058
|
||||
},
|
||||
"1105210": {
|
||||
"key": "hp",
|
||||
"value": 8.00000000745058
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"506326": {
|
||||
"id": 506326,
|
||||
"type": "buff",
|
||||
|
Before Width: | Height: | Size: 460 KiB After Width: | Height: | Size: 328 KiB |
40
resources/meta-sr/character/布洛妮娅/calc.js
Normal file
@ -0,0 +1,40 @@
|
||||
import { Format } from '#miao'
|
||||
|
||||
export const details = [{
|
||||
title: '普攻伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.a['技能伤害'], 'a')
|
||||
}, {
|
||||
title: 'E-Buff加伤',
|
||||
dmg: ({ talent }) => {
|
||||
return {
|
||||
avg: Format.percent(talent.e['伤害提高']),
|
||||
type: 'text'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
title: 'Q-Buff攻击力提高',
|
||||
dmg: ({ talent }) => {
|
||||
return {
|
||||
avg: Format.percent(talent.q['攻击力提高']),
|
||||
type: 'text'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
title: 'Q-Buff爆伤提高',
|
||||
dmg: ({ attr, calc, talent }) => {
|
||||
return {
|
||||
avg: Format.percent(calc(attr.cdmg) * talent.q['百分比暴伤'] / 100 + talent.q['固定暴伤']),
|
||||
type: 'text'
|
||||
}
|
||||
}
|
||||
}]
|
||||
|
||||
export const mainAttr = 'atk,cpct,cdmg'
|
||||
|
||||
export const buffs = [{
|
||||
title: '行迹-军势:布洛妮娅在场时,我方全体造成的伤害提高10%',
|
||||
check: ({ trees }) => trees[103],
|
||||
data: {
|
||||
dmg: 10
|
||||
}
|
||||
}]
|
@ -398,6 +398,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1101201": {
|
||||
"key": "wind",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1101202": {
|
||||
"key": "cdmg",
|
||||
"value": 5.299999983981252
|
||||
},
|
||||
"1101203": {
|
||||
"key": "wind",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1101204": {
|
||||
"key": "effDef",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1101205": {
|
||||
"key": "wind",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1101206": {
|
||||
"key": "cdmg",
|
||||
"value": 8.00000000745058
|
||||
},
|
||||
"1101207": {
|
||||
"key": "wind",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1101208": {
|
||||
"key": "effDef",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1101209": {
|
||||
"key": "cdmg",
|
||||
"value": 10.699999961070716
|
||||
},
|
||||
"1101210": {
|
||||
"key": "wind",
|
||||
"value": 6.399999978020787
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"189034": {
|
||||
"id": 189034,
|
||||
"type": "buff",
|
||||
|
Before Width: | Height: | Size: 690 KiB After Width: | Height: | Size: 408 KiB |
43
resources/meta-sr/character/希儿/calc.js
Normal file
@ -0,0 +1,43 @@
|
||||
export const details = [{
|
||||
title: 'A普攻伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.a['技能伤害'], 'a')
|
||||
}, {
|
||||
title: 'E战技伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.e['技能伤害'], 'e')
|
||||
}, {
|
||||
title: 'Q终结技伤害',
|
||||
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',
|
||||
tree: 2,
|
||||
data: {
|
||||
kx: 20
|
||||
}
|
||||
}]
|
@ -356,6 +356,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1102201": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1102202": {
|
||||
"key": "cdmg",
|
||||
"value": 5.299999983981252
|
||||
},
|
||||
"1102203": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1102204": {
|
||||
"key": "def",
|
||||
"value": 5.000000004656613
|
||||
},
|
||||
"1102205": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1102206": {
|
||||
"key": "cdmg",
|
||||
"value": 8.00000000745058
|
||||
},
|
||||
"1102207": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1102208": {
|
||||
"key": "def",
|
||||
"value": 7.499999972060323
|
||||
},
|
||||
"1102209": {
|
||||
"key": "cdmg",
|
||||
"value": 10.699999961070716
|
||||
},
|
||||
"1102210": {
|
||||
"key": "atk",
|
||||
"value": 8.00000000745058
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"310962": {
|
||||
"id": 310962,
|
||||
"type": "skill",
|
||||
@ -397,7 +439,7 @@
|
||||
"root": true,
|
||||
"name": "割裂",
|
||||
"levelReq": 0,
|
||||
"desc": "增幅状态下希儿的<span style=\"color:#7788ff;\">量子</span>抗性穿透提高<nobr>20.0%</nobr>。",
|
||||
"desc": "增幅状态下希儿的<span>量子</span>抗性穿透提高<nobr>20.0%</nobr>。",
|
||||
"cost": {
|
||||
"29328": 20000,
|
||||
"125435": 1,
|
||||
|
Before Width: | Height: | Size: 802 KiB After Width: | Height: | Size: 477 KiB |
@ -398,6 +398,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1103201": {
|
||||
"key": "cpct",
|
||||
"value": 2.699999953620136
|
||||
},
|
||||
"1103202": {
|
||||
"key": "effPct",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1103203": {
|
||||
"key": "cpct",
|
||||
"value": 2.699999953620136
|
||||
},
|
||||
"1103204": {
|
||||
"key": "effDef",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1103205": {
|
||||
"key": "cpct",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1103206": {
|
||||
"key": "effPct",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1103207": {
|
||||
"key": "cpct",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1103208": {
|
||||
"key": "effDef",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1103209": {
|
||||
"key": "effPct",
|
||||
"value": 8.00000000745058
|
||||
},
|
||||
"1103210": {
|
||||
"key": "cpct",
|
||||
"value": 5.299999983981252
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"514036": {
|
||||
"id": 514036,
|
||||
"type": "buff",
|
||||
|
Before Width: | Height: | Size: 639 KiB After Width: | Height: | Size: 382 KiB |
38
resources/meta-sr/character/彦卿/calc.js
Normal file
@ -0,0 +1,38 @@
|
||||
export const details = [{
|
||||
title: 'A普攻伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.a['技能伤害'], 'a')
|
||||
}, {
|
||||
title: 'E战技伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.e['技能伤害'], 'e')
|
||||
}, {
|
||||
title: 'Q终结技伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.q['技能伤害'], 'q')
|
||||
}]
|
||||
|
||||
export const mainAttr = 'atk,cpct,cdmg'
|
||||
|
||||
export const buffs = [{
|
||||
title: '彦卿天赋:智剑连心提高[cpct]%暴击率和[cdmg]%爆伤',
|
||||
data: {
|
||||
cpct: ({ talent }) => talent.t['暴击率提高'] * 100,
|
||||
cdmg: ({ talent }) => talent.t['爆伤提高'] * 100
|
||||
}
|
||||
}, {
|
||||
title: '彦卿Q:释放终结技提高60%暴击率,智剑连心提高爆伤[qCdmg]%',
|
||||
data: {
|
||||
qCpct: 60,
|
||||
qCdmg: ({ talent }) => talent.q['暴伤提高'] * 100
|
||||
}
|
||||
}, {
|
||||
title: '彦卿4命:生命值大于80%时提高12%的冰抗穿透',
|
||||
cons: 4,
|
||||
data: {
|
||||
kx: 12
|
||||
}
|
||||
}, {
|
||||
title: '行迹-轻吕:触发暴击时,速度提高10%',
|
||||
tree: 3,
|
||||
data: {
|
||||
speedPct: 10
|
||||
}
|
||||
}]
|
@ -197,7 +197,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "技能伤害",
|
||||
"name": "追加攻击概率",
|
||||
"isSame": false,
|
||||
"values": [
|
||||
0.5,
|
||||
@ -461,6 +461,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1209201": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1209202": {
|
||||
"key": "ice",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1209203": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1209204": {
|
||||
"key": "hp",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1209205": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1209206": {
|
||||
"key": "ice",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1209207": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1209208": {
|
||||
"key": "hp",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1209209": {
|
||||
"key": "ice",
|
||||
"value": 6.399999978020787
|
||||
},
|
||||
"1209210": {
|
||||
"key": "atk",
|
||||
"value": 8.00000000745058
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"84865": {
|
||||
"id": 84865,
|
||||
"type": "buff",
|
||||
@ -482,7 +524,7 @@
|
||||
"root": true,
|
||||
"name": "颁冰",
|
||||
"levelReq": 0,
|
||||
"desc": "施放攻击后,对携带<span style=\"color:#47C7FD;\">冰</span>属性弱点的敌方目标造成等同于彦卿<nobr>30.0%</nobr>攻击力的<span style=\"color:#47C7FD;\">冰</span>属性附加伤害。",
|
||||
"desc": "施放攻击后,对携带<span>冰</span>属性弱点的敌方目标造成等同于彦卿<nobr>30.0%</nobr>攻击力的<span>冰</span>属性附加伤害。",
|
||||
"cost": {
|
||||
"29328": 5000,
|
||||
"270195": 1,
|
||||
|
Before Width: | Height: | Size: 874 KiB After Width: | Height: | Size: 545 KiB |
43
resources/meta-sr/character/景元/calc.js
Normal file
@ -0,0 +1,43 @@
|
||||
export const details = [{
|
||||
title: 'A普攻伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.a['技能伤害'], 'a')
|
||||
}, {
|
||||
title: 'E战技伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.e['技能伤害'], 'e')
|
||||
}, {
|
||||
title: 'Q终结技伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.q['技能伤害'], 'q')
|
||||
}, {
|
||||
title: '10层神君单体伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.t['技能伤害'] * 10, 'a3')
|
||||
}]
|
||||
|
||||
export const mainAttr = 'atk,cpct,cdmg,speed'
|
||||
|
||||
export const buffs = [{
|
||||
title: '景元2命:神君行动后,普攻战技及终结技的伤害提高20%',
|
||||
cons: 2,
|
||||
data: {
|
||||
aDmg: 20,
|
||||
eDmg: 20,
|
||||
qDmg: 20
|
||||
}
|
||||
}, {
|
||||
title: '景元6命:神君会使目标陷入易伤状态,使伤害提高12%,最多3层',
|
||||
cons: 6,
|
||||
data: {
|
||||
a3Dmg: (12 + 12 * 2 + 12 * 3 * 7) / 10
|
||||
}
|
||||
}, {
|
||||
title: '行迹-破阵:攻击段数大于等于6段,则其下回合的暴击伤害提高25%',
|
||||
tree: 1,
|
||||
data: {
|
||||
a3Cdmg: 25
|
||||
}
|
||||
}, {
|
||||
title: '行迹-遣将:施放战技后,暴击率提升10%',
|
||||
tree: 3,
|
||||
data: {
|
||||
cpct: 10
|
||||
}
|
||||
}]
|
@ -6,7 +6,6 @@
|
||||
"star": 5,
|
||||
"elem": "雷",
|
||||
"allegiance": "仙舟「罗浮」",
|
||||
"weapon": "智识",
|
||||
"sp": 130,
|
||||
"desc": "仙舟联盟帝弓七天将之一,负责节制罗浮云骑军的「神策将军」。 师从前代「罗浮」剑首,但并不显名于武力。",
|
||||
"cncv": "孙晔",
|
||||
@ -356,6 +355,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1204201": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1204202": {
|
||||
"key": "cpct",
|
||||
"value": 2.699999953620136
|
||||
},
|
||||
"1204203": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1204204": {
|
||||
"key": "def",
|
||||
"value": 5.000000004656613
|
||||
},
|
||||
"1204205": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1204206": {
|
||||
"key": "cpct",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1204207": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1204208": {
|
||||
"key": "def",
|
||||
"value": 7.499999972060323
|
||||
},
|
||||
"1204209": {
|
||||
"key": "cpct",
|
||||
"value": 5.299999983981252
|
||||
},
|
||||
"1204210": {
|
||||
"key": "atk",
|
||||
"value": 8.00000000745058
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"56195": {
|
||||
"id": 56195,
|
||||
"type": "skill",
|
||||
|
Before Width: | Height: | Size: 621 KiB After Width: | Height: | Size: 348 KiB |
23
resources/meta-sr/character/杰帕德/calc.js
Normal file
@ -0,0 +1,23 @@
|
||||
export const details = [{
|
||||
title: '普攻伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.a['技能伤害'], 'a')
|
||||
}, {
|
||||
title: '战技伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.e['技能伤害'], 'e')
|
||||
}, {
|
||||
title: 'Q护盾量',
|
||||
dmg: ({ attr, calc, talent }, { shield }) => shield(calc(attr.def) * talent.q['百分比防御力'] + talent.q['固定数值'])
|
||||
}, {
|
||||
title: '秘技护盾量',
|
||||
dmg: ({ attr, calc, talent }, { shield }) => shield(calc(attr.def) * 0.24 + 150)
|
||||
}]
|
||||
|
||||
export const mainAttr = 'atk,cpct,cdmg,def'
|
||||
|
||||
export const buffs = [{
|
||||
title: '行迹-战意:基于防御值提高攻击力[atkPlus]',
|
||||
tree: 3,
|
||||
data: {
|
||||
atkPlus: ({ calc, attr }) => calc(attr.def) * 0.35
|
||||
}
|
||||
}]
|
@ -398,6 +398,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1104201": {
|
||||
"key": "ice",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1104202": {
|
||||
"key": "effDef",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1104203": {
|
||||
"key": "ice",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1104204": {
|
||||
"key": "def",
|
||||
"value": 5.000000004656613
|
||||
},
|
||||
"1104205": {
|
||||
"key": "ice",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1104206": {
|
||||
"key": "effDef",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1104207": {
|
||||
"key": "ice",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1104208": {
|
||||
"key": "def",
|
||||
"value": 7.499999972060323
|
||||
},
|
||||
"1104209": {
|
||||
"key": "effDef",
|
||||
"value": 8.00000000745058
|
||||
},
|
||||
"1104210": {
|
||||
"key": "ice",
|
||||
"value": 6.399999978020787
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"303252": {
|
||||
"id": 303252,
|
||||
"type": "skill",
|
||||
|
Before Width: | Height: | Size: 507 KiB After Width: | Height: | Size: 327 KiB |
@ -377,13 +377,55 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1108201": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1108202": {
|
||||
"key": "effPct",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1108203": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1108204": {
|
||||
"key": "effDef",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1108205": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1108206": {
|
||||
"key": "effPct",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1108207": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1108208": {
|
||||
"key": "effDef",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1108209": {
|
||||
"key": "effPct",
|
||||
"value": 8.00000000745058
|
||||
},
|
||||
"1108210": {
|
||||
"key": "atk",
|
||||
"value": 8.00000000745058
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"285968": {
|
||||
"id": 285968,
|
||||
"type": "skill",
|
||||
"root": true,
|
||||
"name": "圈套",
|
||||
"levelReq": 0,
|
||||
"desc": "天赋使敌方陷入<span style=\"color:#00FF9C;\">风</span>化状态的持续时间延长<nobr>1</nobr>回合。",
|
||||
"desc": "天赋使敌方陷入<span>风</span>化状态的持续时间延长<nobr>1</nobr>回合。",
|
||||
"cost": {
|
||||
"29328": 4000,
|
||||
"270195": 1,
|
||||
@ -400,7 +442,7 @@
|
||||
"root": true,
|
||||
"name": "加料",
|
||||
"levelReq": 0,
|
||||
"desc": "<span style=\"color:#00FF9C;\">风</span>化状态下的敌方目标对桑博造成的伤害降低<nobr>15.0%</nobr>。",
|
||||
"desc": "<span>风</span>化状态下的敌方目标对桑博造成的伤害降低<nobr>15.0%</nobr>。",
|
||||
"cost": {
|
||||
"29328": 128000,
|
||||
"125435": 1,
|
||||
|
Before Width: | Height: | Size: 517 KiB After Width: | Height: | Size: 338 KiB |
30
resources/meta-sr/character/瓦尔特/calc.js
Normal file
@ -0,0 +1,30 @@
|
||||
export const details = [{
|
||||
title: '普攻伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.a['技能伤害'], 'a')
|
||||
}, {
|
||||
title: 'E战技主目标伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.e['技能伤害'], 'e')
|
||||
}, {
|
||||
title: 'Q终结技伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.q['技能伤害'], 'q')
|
||||
}, {
|
||||
title: '天赋附加伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.t['附加伤害'], 't')
|
||||
}]
|
||||
|
||||
export const mainAttr = 'atk,cpct,cdmg'
|
||||
|
||||
export const buffs = [{
|
||||
title: '行迹-惩戒:施放终结技提高敌人受到伤害12%',
|
||||
tree: 1,
|
||||
data: {
|
||||
dmg: 12
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '行迹-裁决:弱点击破的敌方目标造成的伤害提高20%',
|
||||
tree: 3,
|
||||
data: {
|
||||
dmg: 20
|
||||
}
|
||||
}]
|
@ -398,6 +398,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1004201": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1004202": {
|
||||
"key": "imaginary",
|
||||
"value": 3.1999999890103936
|
||||
},
|
||||
"1004203": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1004204": {
|
||||
"key": "effDef",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1004205": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1004206": {
|
||||
"key": "imaginary",
|
||||
"value": 4.799999948590994
|
||||
},
|
||||
"1004207": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1004208": {
|
||||
"key": "effDef",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1004209": {
|
||||
"key": "imaginary",
|
||||
"value": 6.399999978020787
|
||||
},
|
||||
"1004210": {
|
||||
"key": "atk",
|
||||
"value": 8.00000000745058
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"149174": {
|
||||
"id": 149174,
|
||||
"type": "buff",
|
||||
|
Before Width: | Height: | Size: 680 KiB After Width: | Height: | Size: 389 KiB |
35
resources/meta-sr/character/白露/calc.js
Normal file
@ -0,0 +1,35 @@
|
||||
export const details = [{
|
||||
title: '普攻伤害',
|
||||
dmg: ({ talent }, dmg) => dmg(talent.a['技能伤害'], 'a')
|
||||
}, {
|
||||
title: 'E主目标生命恢复',
|
||||
dmg: ({ calc, attr, talent }, { heal }) => heal(calc(attr.hp) * talent.e['百分比生命'] + talent.e['固定值'])
|
||||
}, {
|
||||
title: 'Q生命恢复',
|
||||
dmg: ({ calc, attr, talent }, { heal }) => heal(calc(attr.hp) * talent.q['百分比生命'] + talent.q['固定值'])
|
||||
}, {
|
||||
title: '天赋生息恢复',
|
||||
dmg: ({ calc, attr, talent }, { heal }) => heal(calc(attr.hp) * talent.t['生息·百分比生命'] + talent.t['生息·固定值'])
|
||||
}]
|
||||
|
||||
export const mainAttr = 'atk,cpct,cdmg,hp'
|
||||
|
||||
export const buffs = [{
|
||||
title: '白露2命:释放终结技后治疗提高15%',
|
||||
cons: 2,
|
||||
data: {
|
||||
heal: 15
|
||||
}
|
||||
}, {
|
||||
title: '希儿2命:释放战技后,2层Buff速度提高50%',
|
||||
cons: 2,
|
||||
data: {
|
||||
speedPct: 50
|
||||
}
|
||||
}, {
|
||||
title: '行迹-夜行:抗性穿透提高20',
|
||||
tree: 2,
|
||||
data: {
|
||||
kx: 20
|
||||
}
|
||||
}]
|
@ -461,6 +461,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1211201": {
|
||||
"key": "hp",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1211202": {
|
||||
"key": "def",
|
||||
"value": 5.000000004656613
|
||||
},
|
||||
"1211203": {
|
||||
"key": "hp",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1211204": {
|
||||
"key": "effDef",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1211205": {
|
||||
"key": "hp",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1211206": {
|
||||
"key": "def",
|
||||
"value": 7.499999972060323
|
||||
},
|
||||
"1211207": {
|
||||
"key": "hp",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1211208": {
|
||||
"key": "effDef",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1211209": {
|
||||
"key": "def",
|
||||
"value": 10.000000009313226
|
||||
},
|
||||
"1211210": {
|
||||
"key": "hp",
|
||||
"value": 8.00000000745058
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"671251": {
|
||||
"id": 671251,
|
||||
"type": "skill",
|
||||
|
Before Width: | Height: | Size: 634 KiB After Width: | Height: | Size: 410 KiB |
@ -376,6 +376,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1206201": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1206202": {
|
||||
"key": "hp",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1206203": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1206204": {
|
||||
"key": "def",
|
||||
"value": 5.000000004656613
|
||||
},
|
||||
"1206205": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1206206": {
|
||||
"key": "hp",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1206207": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1206208": {
|
||||
"key": "def",
|
||||
"value": 7.499999972060323
|
||||
},
|
||||
"1206209": {
|
||||
"key": "hp",
|
||||
"value": 8.00000000745058
|
||||
},
|
||||
"1206210": {
|
||||
"key": "atk",
|
||||
"value": 8.00000000745058
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"614646": {
|
||||
"id": 614646,
|
||||
"type": "buff",
|
||||
|
Before Width: | Height: | Size: 727 KiB After Width: | Height: | Size: 424 KiB |
@ -395,6 +395,48 @@
|
||||
}
|
||||
},
|
||||
"tree": {
|
||||
"1203201": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1203202": {
|
||||
"key": "hp",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1203203": {
|
||||
"key": "atk",
|
||||
"value": 4.00000000372529
|
||||
},
|
||||
"1203204": {
|
||||
"key": "def",
|
||||
"value": 5.000000004656613
|
||||
},
|
||||
"1203205": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1203206": {
|
||||
"key": "hp",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1203207": {
|
||||
"key": "atk",
|
||||
"value": 6.0000000055879354
|
||||
},
|
||||
"1203208": {
|
||||
"key": "def",
|
||||
"value": 7.499999972060323
|
||||
},
|
||||
"1203209": {
|
||||
"key": "hp",
|
||||
"value": 8.00000000745058
|
||||
},
|
||||
"1203210": {
|
||||
"key": "atk",
|
||||
"value": 8.00000000745058
|
||||
}
|
||||
},
|
||||
"treeData": {
|
||||
"343112": {
|
||||
"id": 343112,
|
||||
"type": "skill",
|
||||
|