2022-07-23 20:32:10 +00:00
|
|
|
|
import lodash from 'lodash'
|
2023-02-13 19:47:22 +00:00
|
|
|
|
import { getTargetUid, getProfileRefresh } from './ProfileCommon.js'
|
|
|
|
|
import ProfileList from './ProfileList.js'
|
2023-05-22 19:19:45 +00:00
|
|
|
|
import { Cfg, Common, Data, Format } from '#miao'
|
2023-10-18 19:53:48 +00:00
|
|
|
|
import { MysApi, ProfileRank, Character, Weapon, Artifact } from '#miao.models'
|
2023-02-09 18:54:51 +00:00
|
|
|
|
import ProfileChange from './ProfileChange.js'
|
|
|
|
|
import { profileArtis } from './ProfileArtis.js'
|
2023-04-12 19:44:56 +00:00
|
|
|
|
import { ProfileWeapon } from './ProfileWeapon.js'
|
2023-02-09 18:54:51 +00:00
|
|
|
|
|
2023-05-22 19:19:45 +00:00
|
|
|
|
let { diyCfg } = await Data.importCfg('profile')
|
|
|
|
|
|
2023-02-09 18:54:51 +00:00
|
|
|
|
// 查看当前角色
|
2023-02-21 19:49:49 +00:00
|
|
|
|
let ProfileDetail = {
|
|
|
|
|
async detail (e) {
|
|
|
|
|
let msg = e.original_msg || e.msg
|
|
|
|
|
if (!msg) {
|
|
|
|
|
return false
|
2023-02-09 18:54:51 +00:00
|
|
|
|
}
|
2023-02-21 19:49:49 +00:00
|
|
|
|
if (!/详细|详情|面板|面版|圣遗物|伤害|武器|换/.test(msg)) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
let mode = 'profile'
|
|
|
|
|
let profileChange = false
|
|
|
|
|
let changeMsg = msg
|
|
|
|
|
let pc = ProfileChange.matchMsg(msg)
|
2023-10-13 20:02:21 +00:00
|
|
|
|
|
2023-02-21 19:49:49 +00:00
|
|
|
|
if (pc && pc.char && pc.change) {
|
|
|
|
|
if (!Cfg.get('profileChange')) {
|
|
|
|
|
e.reply('面板替换功能已禁用...')
|
|
|
|
|
return true
|
2023-05-26 21:37:06 +00:00
|
|
|
|
}
|
2023-10-13 20:02:21 +00:00
|
|
|
|
e.game = pc.game
|
|
|
|
|
e.isSr = e.game === 'sr'
|
2023-10-14 15:02:20 +00:00
|
|
|
|
e.uid = ''
|
|
|
|
|
e.msg = '#喵喵面板变换'
|
2023-10-13 20:02:21 +00:00
|
|
|
|
e.uid = pc.uid || await getTargetUid(e)
|
2023-05-26 21:37:06 +00:00
|
|
|
|
profileChange = ProfileChange.getProfile(e.uid, pc.char, pc.change, pc.game)
|
2023-02-21 19:49:49 +00:00
|
|
|
|
if (profileChange && profileChange.char) {
|
|
|
|
|
msg = `#${profileChange.char?.name}${pc.mode || '面板'}`
|
|
|
|
|
e._profile = profileChange
|
|
|
|
|
e._profileMsg = changeMsg
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
let uidRet = /[0-9]{9}/.exec(msg)
|
|
|
|
|
if (uidRet) {
|
|
|
|
|
e.uid = uidRet[0]
|
|
|
|
|
msg = msg.replace(uidRet[0], '')
|
2023-02-09 18:54:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-05-16 05:04:43 +00:00
|
|
|
|
let name = msg.replace(/#|老婆|老公|星铁|原神/g, '').trim()
|
2023-02-21 19:49:49 +00:00
|
|
|
|
msg = msg.replace('面版', '面板')
|
2023-06-11 19:20:56 +00:00
|
|
|
|
let dmgRet = /(?:伤害|武器)(\d*)$/.exec(name)
|
|
|
|
|
let dmgIdx = 0, idxIsInput = false
|
2023-02-21 19:49:49 +00:00
|
|
|
|
if (/(最强|最高|最高分|最牛|第一)/.test(msg)) {
|
|
|
|
|
mode = /(分|圣遗物|评分|ACE)/.test(msg) ? 'rank-mark' : 'rank-dmg'
|
|
|
|
|
name = name.replace(/(最强|最高分|第一|最高|最牛|圣遗物|评分|群)/g, '')
|
|
|
|
|
}
|
|
|
|
|
if (/(详情|详细|面板|面版)\s*$/.test(msg) && !/更新|录入|输入/.test(msg)) {
|
|
|
|
|
mode = 'profile'
|
|
|
|
|
name = name.replace(/(详情|详细|面板)/, '').trim()
|
|
|
|
|
} else if (dmgRet) {
|
|
|
|
|
// mode = /武器/.test(msg) ? 'weapon' : 'dmg'
|
|
|
|
|
mode = 'dmg'
|
2023-06-11 19:20:56 +00:00
|
|
|
|
name = name.replace(/(伤害|武器)+\d*/, '').trim()
|
2023-02-21 19:49:49 +00:00
|
|
|
|
if (dmgRet[1]) {
|
|
|
|
|
dmgIdx = dmgRet[1] * 1
|
2023-06-11 19:20:56 +00:00
|
|
|
|
// 标识是用户指定的序号
|
|
|
|
|
idxIsInput = true
|
2023-02-21 19:49:49 +00:00
|
|
|
|
}
|
|
|
|
|
} else if (/(详情|详细|面板)更新$/.test(msg) || (/更新/.test(msg) && /(详情|详细|面板)$/.test(msg))) {
|
|
|
|
|
mode = 'refresh'
|
|
|
|
|
name = name.replace(/详情|详细|面板|更新/g, '').trim()
|
|
|
|
|
} else if (/圣遗物/.test(msg)) {
|
|
|
|
|
mode = 'artis'
|
|
|
|
|
name = name.replace('圣遗物', '').trim()
|
|
|
|
|
}
|
|
|
|
|
if (!Common.cfg('avatarProfile')) {
|
|
|
|
|
return false // 面板开关关闭
|
|
|
|
|
}
|
2023-10-23 14:14:09 +00:00
|
|
|
|
let char = Character.get(name.trim(), e.game)
|
2023-02-21 19:49:49 +00:00
|
|
|
|
if (!char) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
2023-05-20 13:51:44 +00:00
|
|
|
|
if (/星铁/.test(msg) || char.isSr) {
|
2023-10-23 14:14:09 +00:00
|
|
|
|
e.game = 'sr'
|
2023-05-20 13:51:44 +00:00
|
|
|
|
e.isSr = true
|
|
|
|
|
}
|
2023-02-09 18:54:51 +00:00
|
|
|
|
|
2023-02-21 19:49:49 +00:00
|
|
|
|
let uid = e.uid || await getTargetUid(e)
|
|
|
|
|
if (!uid) {
|
2023-02-09 18:54:51 +00:00
|
|
|
|
return true
|
2023-02-21 19:49:49 +00:00
|
|
|
|
}
|
|
|
|
|
e.uid = uid
|
|
|
|
|
e.avatar = char.id
|
|
|
|
|
|
|
|
|
|
if (char.isCustom) {
|
|
|
|
|
e.reply('自定义角色暂不支持此功能')
|
2023-02-09 18:54:51 +00:00
|
|
|
|
return true
|
|
|
|
|
}
|
2023-02-21 19:49:49 +00:00
|
|
|
|
if (!char.isRelease) {
|
2023-10-02 18:08:22 +00:00
|
|
|
|
// 预设面板支持未实装角色
|
|
|
|
|
if (!profileChange && Number(e.uid) > 100000006) {
|
2023-02-21 19:49:49 +00:00
|
|
|
|
e.reply('角色尚未实装')
|
|
|
|
|
return true
|
2023-10-08 12:43:48 +00:00
|
|
|
|
}
|
|
|
|
|
// 但仅在未实装开启时展示
|
|
|
|
|
if (Cfg.get('notReleasedData') === false) {
|
2023-02-21 19:49:49 +00:00
|
|
|
|
e.reply('未实装角色面板已禁用...')
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-09 18:54:51 +00:00
|
|
|
|
|
2023-02-21 19:49:49 +00:00
|
|
|
|
if (mode === 'profile' || mode === 'dmg' || mode === 'weapon') {
|
2023-06-11 19:20:56 +00:00
|
|
|
|
return ProfileDetail.render(e, char, mode, { dmgIdx, idxIsInput })
|
2023-02-21 19:49:49 +00:00
|
|
|
|
} else if (mode === 'refresh') {
|
|
|
|
|
await ProfileList.refresh(e)
|
|
|
|
|
return true
|
|
|
|
|
} else if (mode === 'artis') {
|
|
|
|
|
return profileArtis(e)
|
|
|
|
|
}
|
2023-02-09 18:54:51 +00:00
|
|
|
|
return true
|
2023-02-21 19:49:49 +00:00
|
|
|
|
},
|
2022-06-25 23:45:43 +00:00
|
|
|
|
|
2023-02-21 19:49:49 +00:00
|
|
|
|
async render (e, char, mode = 'profile', params = {}) {
|
|
|
|
|
let selfUser = await MysApi.initUser(e)
|
2022-06-25 23:45:43 +00:00
|
|
|
|
|
2023-02-21 19:49:49 +00:00
|
|
|
|
if (!selfUser) {
|
|
|
|
|
e.reply('尚未绑定UID')
|
|
|
|
|
return true
|
|
|
|
|
}
|
2022-09-27 02:25:31 +00:00
|
|
|
|
|
2023-02-21 19:49:49 +00:00
|
|
|
|
let { uid } = e
|
2022-06-25 23:45:43 +00:00
|
|
|
|
|
2023-02-21 19:49:49 +00:00
|
|
|
|
if (char.isCustom) {
|
|
|
|
|
e.reply(`暂不支持自定义角色${char.name}的面板信息查看`)
|
|
|
|
|
return true
|
|
|
|
|
}
|
2022-06-25 23:45:43 +00:00
|
|
|
|
|
2023-02-21 19:49:49 +00:00
|
|
|
|
let profile = e._profile || await getProfileRefresh(e, char.id)
|
|
|
|
|
if (!profile) {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
char = profile.char || char
|
|
|
|
|
let a = profile.attr
|
2023-03-05 07:21:44 +00:00
|
|
|
|
let base = profile.base
|
|
|
|
|
let attr = {}
|
2023-05-18 20:23:19 +00:00
|
|
|
|
let game = char.game
|
2023-05-21 18:13:38 +00:00
|
|
|
|
let isGs = game === 'gs'
|
2023-09-23 19:55:58 +00:00
|
|
|
|
let isSr = !isGs
|
2023-05-18 20:23:19 +00:00
|
|
|
|
|
2023-05-21 18:13:38 +00:00
|
|
|
|
lodash.forEach((isGs ? 'hp,def,atk,mastery' : 'hp,def,atk,speed').split(','), (key) => {
|
2023-03-05 07:41:47 +00:00
|
|
|
|
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])
|
2023-03-05 07:21:44 +00:00
|
|
|
|
})
|
2023-09-21 20:03:01 +00:00
|
|
|
|
lodash.forEach((isGs ? 'cpct,cdmg,recharge,dmg' : 'cpct,cdmg,recharge,dmg,effPct,effDef,heal,stance').split(','), (key) => {
|
2023-03-05 07:41:47 +00:00
|
|
|
|
let fn = Format.pct
|
|
|
|
|
let key2 = key
|
2023-05-19 18:50:39 +00:00
|
|
|
|
if (key === 'dmg') {
|
2023-05-21 18:13:38 +00:00
|
|
|
|
if (isGs) {
|
2023-05-19 18:50:39 +00:00
|
|
|
|
if (a.phy > a.dmg) {
|
|
|
|
|
key2 = 'phy'
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-03-05 07:41:47 +00:00
|
|
|
|
}
|
|
|
|
|
attr[key] = fn(a[key2])
|
|
|
|
|
attr[`${key}Base`] = fn(base[key2])
|
|
|
|
|
attr[`${key}Plus`] = fn(a[key2] - base[key2])
|
2023-03-05 07:21:44 +00:00
|
|
|
|
})
|
|
|
|
|
|
2023-05-28 18:49:36 +00:00
|
|
|
|
let weapon = Weapon.get(profile?.weapon?.name, game)
|
2023-02-21 19:49:49 +00:00
|
|
|
|
let w = profile.weapon
|
|
|
|
|
let wCfg = {}
|
|
|
|
|
if (mode === 'weapon') {
|
|
|
|
|
wCfg = weapon.calcAttr(w.level, w.promote)
|
2023-04-12 19:44:56 +00:00
|
|
|
|
wCfg.weapons = await ProfileWeapon.calc(profile)
|
2023-02-21 19:49:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-05-21 18:13:38 +00:00
|
|
|
|
let enemyLv = isGs ? (await selfUser.getCfg('char.enemyLv', 91)) : profile.level
|
2023-02-21 19:49:49 +00:00
|
|
|
|
let dmgCalc = await ProfileDetail.getProfileDmgCalc({ profile, enemyLv, mode, params })
|
|
|
|
|
|
|
|
|
|
let rank = false
|
|
|
|
|
if (e.group_id && !e._profile) {
|
|
|
|
|
rank = await ProfileRank.create({ group: e.group_id, uid, qq: e.user_id })
|
|
|
|
|
await rank.getRank(profile, true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let artisDetail = profile.getArtisMark()
|
2023-10-23 20:01:15 +00:00
|
|
|
|
// 处理一下allAttr,确保都有9个内容,以获得比较好展示效果
|
|
|
|
|
let allAttr = profile.artis.getAllAttr() || []
|
|
|
|
|
allAttr = lodash.slice(allAttr, 0, 9)
|
|
|
|
|
for (let idx = allAttr.length; idx < 9; idx++) {
|
|
|
|
|
allAttr[idx] = {}
|
|
|
|
|
}
|
|
|
|
|
artisDetail.allAttr = allAttr
|
|
|
|
|
|
2023-10-18 13:19:12 +00:00
|
|
|
|
let artisKeyTitle = Artifact.getArtisKeyTitle(game)
|
2023-05-19 18:50:39 +00:00
|
|
|
|
let data = profile.getData('name,abbr,cons,level,talent,dataSource,updateTime,imgs,costumeSplash')
|
2023-09-23 19:55:58 +00:00
|
|
|
|
if (isSr) {
|
|
|
|
|
let treeData = []
|
|
|
|
|
let treeMap = {}
|
|
|
|
|
// 属性
|
|
|
|
|
lodash.forEach('0113355778'.split(''), (pos, idx) => {
|
|
|
|
|
treeData[pos] = treeData[pos] || []
|
|
|
|
|
let tmp = { type: 'tree', img: `/meta-sr/public/icons/tree-cpct.webp` }
|
|
|
|
|
treeData[pos].push(tmp)
|
|
|
|
|
treeMap[idx + 201 + ''] = tmp
|
|
|
|
|
})
|
|
|
|
|
// 能力
|
|
|
|
|
lodash.forEach([2, 4, 6], (pos, idx) => {
|
|
|
|
|
let tmp = { type: 'talent', img: data.imgs[`tree${idx + 1}`] }
|
|
|
|
|
treeData[pos] = tmp
|
|
|
|
|
treeMap[idx + 101 + ''] = tmp
|
|
|
|
|
})
|
|
|
|
|
lodash.forEach(profile.trees, (id) => {
|
|
|
|
|
let ret = /([12][01][0-9])$/.exec(id + '')
|
|
|
|
|
if (ret && ret[1]) {
|
|
|
|
|
let treeId = ret[1]
|
|
|
|
|
if (treeMap?.[treeId]) {
|
|
|
|
|
treeMap[treeId].value = 1
|
|
|
|
|
}
|
|
|
|
|
if (treeId[0] === '2') {
|
|
|
|
|
treeMap[treeId].img = `/meta-sr/public/icons/tree-${char.detail?.tree?.[id]?.key}.webp`
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
data.treeData = treeData
|
|
|
|
|
}
|
2023-05-19 18:50:39 +00:00
|
|
|
|
data.weapon = profile.getWeaponDetail()
|
2023-02-22 17:48:44 +00:00
|
|
|
|
let renderData = {
|
2023-02-21 19:49:49 +00:00
|
|
|
|
save_id: uid,
|
|
|
|
|
uid,
|
2023-05-18 20:23:19 +00:00
|
|
|
|
game,
|
2023-05-19 18:50:39 +00:00
|
|
|
|
data,
|
2023-02-21 19:49:49 +00:00
|
|
|
|
attr,
|
|
|
|
|
elem: char.elem,
|
|
|
|
|
dmgCalc,
|
|
|
|
|
artisDetail,
|
|
|
|
|
artisKeyTitle,
|
|
|
|
|
bodyClass: `char-${char.name}`,
|
|
|
|
|
mode,
|
|
|
|
|
wCfg,
|
|
|
|
|
changeProfile: e._profileMsg
|
2023-02-22 17:48:44 +00:00
|
|
|
|
}
|
|
|
|
|
// 渲染图像
|
|
|
|
|
let msgRes = await Common.render('character/profile-detail', renderData, { e, scale: 1.6, retMsgId: true })
|
2023-07-20 00:31:09 +00:00
|
|
|
|
if (msgRes) {
|
2023-02-21 19:49:49 +00:00
|
|
|
|
// 如果消息发送成功,就将message_id和图片路径存起来,3小时过期
|
2023-07-20 00:31:09 +00:00
|
|
|
|
const message_id = [e.message_id]
|
|
|
|
|
if (Array.isArray(msgRes.message_id)) {
|
|
|
|
|
message_id.push(...msgRes.message_id)
|
|
|
|
|
} else {
|
|
|
|
|
message_id.push(msgRes.message_id)
|
|
|
|
|
}
|
|
|
|
|
for (const i of message_id) {
|
|
|
|
|
await redis.set(`miao:original-picture:${i}`, JSON.stringify({
|
|
|
|
|
type: 'profile',
|
|
|
|
|
img: renderData?.data?.costumeSplash
|
|
|
|
|
}), { EX: 3600 * 3 })
|
|
|
|
|
}
|
2023-02-21 19:49:49 +00:00
|
|
|
|
}
|
2022-07-23 20:32:10 +00:00
|
|
|
|
return true
|
2023-02-21 19:49:49 +00:00
|
|
|
|
},
|
2022-06-25 23:45:43 +00:00
|
|
|
|
|
2023-02-21 19:49:49 +00:00
|
|
|
|
async getProfileDmgCalc ({ profile, enemyLv, mode, params }) {
|
|
|
|
|
let dmgMsg = []
|
|
|
|
|
let dmgData = []
|
|
|
|
|
let dmgCalc = await profile.calcDmg({
|
|
|
|
|
enemyLv,
|
|
|
|
|
mode,
|
|
|
|
|
...params
|
2022-06-25 23:45:43 +00:00
|
|
|
|
})
|
2023-02-21 19:49:49 +00:00
|
|
|
|
if (dmgCalc && dmgCalc.ret) {
|
|
|
|
|
lodash.forEach(dmgCalc.ret, (ds) => {
|
2023-05-22 19:19:45 +00:00
|
|
|
|
if (ds.type !== 'text') {
|
|
|
|
|
ds.dmg = Format.comma(ds.dmg, 0)
|
|
|
|
|
ds.avg = Format.comma(ds.avg, 0)
|
|
|
|
|
}
|
2023-02-21 19:49:49 +00:00
|
|
|
|
dmgData.push(ds)
|
2022-06-25 23:45:43 +00:00
|
|
|
|
})
|
2023-02-21 19:49:49 +00:00
|
|
|
|
lodash.forEach(dmgCalc.msg, (msg) => {
|
|
|
|
|
msg.replace(':', ':')
|
|
|
|
|
dmgMsg.push(msg.split(':'))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
dmgCalc.dmgMsg = dmgMsg
|
|
|
|
|
dmgCalc.dmgData = dmgData
|
|
|
|
|
}
|
2022-11-23 20:26:07 +00:00
|
|
|
|
|
2023-02-21 19:49:49 +00:00
|
|
|
|
if (mode === 'dmg' && dmgCalc.dmgRet) {
|
|
|
|
|
let basic = dmgCalc?.dmgCfg?.basicRet
|
|
|
|
|
lodash.forEach(dmgCalc.dmgRet, (row) => {
|
|
|
|
|
lodash.forEach(row, (ds) => {
|
|
|
|
|
ds.val = (ds.avg > basic.avg ? '+' : '') + Format.comma(ds.avg - basic.avg)
|
|
|
|
|
ds.dmg = Format.comma(ds.dmg, 0)
|
|
|
|
|
ds.avg = Format.comma(ds.avg, 0)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
basic.dmg = Format.comma(basic.dmg)
|
|
|
|
|
basic.avg = Format.comma(basic.avg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dmgCalc
|
2022-12-03 19:45:50 +00:00
|
|
|
|
}
|
2022-07-23 20:32:10 +00:00
|
|
|
|
}
|
2023-02-21 19:49:49 +00:00
|
|
|
|
|
|
|
|
|
export default ProfileDetail
|