From f0348841a34f56128410ca2e108d1186f047d9e9 Mon Sep 17 00:00:00 2001 From: Kokomi <102026640+yoimiya-kokomi@users.noreply.github.com> Date: Wed, 22 Feb 2023 03:49:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BE=AE=E8=B0=83=E9=9D=A2=E6=9D=BF=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/profile.js | 8 +- apps/profile/ProfileDetail.js | 388 +++++++++++++----------- apps/profile/ProfileRank.js | 6 +- models/Artifact.js | 5 +- models/ProfileData.js | 4 + models/ProfileDmg.js | 5 +- models/ProfileReq.js | 11 +- models/Weapon.js | 87 +++++- models/profile/ArtisMark.js | 8 +- models/profile/AttrCalc.js | 32 +- resources/character/profile-detail.css | 6 +- resources/character/profile-detail.html | 337 ++++++++++---------- resources/character/profile-detail.less | 29 +- 13 files changed, 512 insertions(+), 414 deletions(-) diff --git a/apps/profile.js b/apps/profile.js index 72fbd79b..85f0c361 100644 --- a/apps/profile.js +++ b/apps/profile.js @@ -1,7 +1,7 @@ import { App, Cfg } from '../components/index.js' import { profileHelp } from './profile/ProfileCommon.js' import { profileArtisList } from './profile/ProfileArtis.js' -import { profileDetail } from './profile/ProfileDetail.js' +import ProfileDetail from './profile/ProfileDetail.js' import ProfileStat from './profile/ProfileStat.js' import ProfileList from './profile/ProfileList.js' import { uploadCharacterImg, delProfileImg, profileImgList } from './character/ImgUpload.js' @@ -16,13 +16,13 @@ let app = App.init({ app.reg({ profileDetail: { name: '角色面板', - fn: profileDetail, - rule: /^#*([^#]+)\s*(详细|详情|面板|面版|圣遗物|伤害[1-7]?)\s*(\d{9})*(.*[换变改].*)?$/ + fn: ProfileDetail.detail, + rule: /^#*([^#]+)\s*(详细|详情|面板|面版|圣遗物|武器[1-7]?|伤害[1-7]?)\s*(\d{9})*(.*[换变改].*)?$/ }, profileChange: { name: '角色面板计算', - fn: profileDetail, + fn: ProfileDetail.detail, rule: /^#.+换.+$/ }, diff --git a/apps/profile/ProfileDetail.js b/apps/profile/ProfileDetail.js index 9caa3ee6..e1607820 100644 --- a/apps/profile/ProfileDetail.js +++ b/apps/profile/ProfileDetail.js @@ -2,210 +2,228 @@ import lodash from 'lodash' import { getTargetUid, getProfileRefresh } from './ProfileCommon.js' import ProfileList from './ProfileList.js' import { Cfg, Common, Format } from '../../components/index.js' -import { MysApi, ProfileRank, ProfileArtis, Player, Character } from '../../models/index.js' +import { MysApi, ProfileRank, ProfileArtis, Character, Weapon } from '../../models/index.js' import ProfileChange from './ProfileChange.js' import { profileArtis } from './ProfileArtis.js' // 查看当前角色 -export async function profileDetail (e) { - let msg = e.original_msg || e.msg - if (!msg) { - return false - } - if (!/详细|详情|面板|面版|圣遗物|伤害|换/.test(msg)) { - return false - } - let mode = 'profile' - let profileChange = false - let changeMsg = msg - let pc = ProfileChange.matchMsg(msg) - if (pc && pc.char && pc.change) { - if (!Cfg.get('profileChange')) { - e.reply('面板替换功能已禁用...') +let ProfileDetail = { + async detail (e) { + let msg = e.original_msg || e.msg + if (!msg) { + return false + } + if (!/详细|详情|面板|面版|圣遗物|伤害|武器|换/.test(msg)) { + return false + } + let mode = 'profile' + let profileChange = false + let changeMsg = msg + let pc = ProfileChange.matchMsg(msg) + if (pc && pc.char && pc.change) { + if (!Cfg.get('profileChange')) { + e.reply('面板替换功能已禁用...') + return true + } + e.uid = pc.uid || e.runtime.uid + profileChange = ProfileChange.getProfile(e.uid, pc.char, pc.change) + 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], '') + } + + let name = msg.replace(/#|老婆|老公/g, '').trim() + msg = msg.replace('面版', '面板') + let dmgRet = /(?:伤害|武器)(\d?)$/.exec(name) + let dmgIdx = 0 + 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' + name = name.replace(/(伤害|武器)+[0-7]?/, '').trim() + if (dmgRet[1]) { + dmgIdx = dmgRet[1] * 1 + } + } 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 // 面板开关关闭 + } + let char = Character.get(name.trim()) + if (!char) { + return false + } + + let uid = e.uid || await getTargetUid(e) + if (!uid) { return true } - e.uid = pc.uid || e.runtime.uid - profileChange = ProfileChange.getProfile(e.uid, pc.char, pc.change) - 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], '') - } + e.uid = uid + e.avatar = char.id - let name = msg.replace(/#|老婆|老公/g, '').trim() - msg = msg.replace('面版', '面板') - let dmgRet = /伤害(\d?)$/.exec(name) - let dmgIdx = 0 - 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 = 'dmg' - name = name.replace(/伤害[0-5]?/, '').trim() - if (dmgRet[1]) { - dmgIdx = dmgRet[1] * 1 - } - } 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 // 面板开关关闭 - } - let char = Character.get(name.trim()) - if (!char) { - return false - } - - let uid = e.uid || await getTargetUid(e) - if (!uid) { - return true - } - e.uid = uid - e.avatar = char.id - - if (char.isCustom) { - e.reply('自定义角色暂不支持此功能') - return true - } - if (!char.isRelease) { - if (!profileChange) { - e.reply('角色尚未实装') - return true - } else if (Cfg.get('notReleasedData') === false) { - e.reply('未实装角色面板已禁用...') + if (char.isCustom) { + e.reply('自定义角色暂不支持此功能') return true } - } + if (!char.isRelease) { + if (!profileChange) { + e.reply('角色尚未实装') + return true + } else if (Cfg.get('notReleasedData') === false) { + e.reply('未实装角色面板已禁用...') + return true + } + } - if (mode === 'profile' || mode === 'dmg') { - return renderProfile(e, char, mode, { dmgIdx }) - } else if (mode === 'refresh') { - await ProfileList.refresh(e) + if (mode === 'profile' || mode === 'dmg' || mode === 'weapon') { + return ProfileDetail.render(e, char, mode, { dmgIdx }) + } else if (mode === 'refresh') { + await ProfileList.refresh(e) + return true + } else if (mode === 'artis') { + return profileArtis(e) + } return true - } else if (mode === 'artis') { - return profileArtis(e) - } - return true -} + }, -export async function renderProfile (e, char, mode = 'profile', params = {}) { - let selfUser = await MysApi.initUser(e) + async render (e, char, mode = 'profile', params = {}) { + let selfUser = await MysApi.initUser(e) - if (!selfUser) { - e.reply('尚未绑定UID') + if (!selfUser) { + e.reply('尚未绑定UID') + return true + } + + let { uid } = e + + if (char.isCustom) { + e.reply(`暂不支持自定义角色${char.name}的面板信息查看`) + return true + } + + let profile = e._profile || await getProfileRefresh(e, char.id) + if (!profile) { + return true + } + char = profile.char || char + let a = profile.attr + let c = Format.comma + let p = Format.pct + let attr = { + hp: c(a.hp), + hpPlus: c(a.hp - a.hpBase), + atk: c(a.atk), + atkPlus: c(a.atk - a.atkBase), + def: c(a.def), + defPlus: c(a.def - a.defBase), + cpct: p(a.cpct), + cdmg: p(a.cdmg), + mastery: c(a.mastery), + recharge: p(a.recharge), + dmg: p(Math.max(a.dmg * 1 || 0, a.phy * 1 || 0)) + } + + let weapon = Weapon.get(profile.weapon.name) + let w = profile.weapon + let wCfg = {} + if (mode === 'weapon') { + wCfg = weapon.calcAttr(w.level, w.promote) + wCfg.info = weapon.getAffixInfo(weapon.affix) + } + + let enemyLv = await selfUser.getCfg('char.enemyLv', 91) + 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() + let artisKeyTitle = ProfileArtis.getArtisKeyTitle() + let costumeSplash = profile.costumeSplash + // 渲染图像 + let msgRes = await Common.render('character/profile-detail', { + save_id: uid, + uid, + data: profile.getData('name,abbr,cons,level,weapon,talent,dataSource,updateTime,imgs,costumeSplash'), + attr, + elem: char.elem, + dmgCalc, + artisDetail, + artisKeyTitle, + bodyClass: `char-${char.name}`, + mode, + wCfg, + changeProfile: e._profileMsg + }, { e, scale: 1.6, retMsgId: true }) + if (msgRes && msgRes.message_id) { + // 如果消息发送成功,就将message_id和图片路径存起来,3小时过期 + await redis.set(`miao:original-picture:${msgRes.message_id}`, JSON.stringify({ + type: 'profile', + img: costumeSplash + }), { EX: 3600 * 3 }) + } return true - } + }, - let { uid } = e - - if (char.isCustom) { - e.reply(`暂不支持自定义角色${char.name}的面板信息查看`) - return true - } - - let profile = e._profile || await getProfileRefresh(e, char.id) - if (!profile) { - return true - } - char = profile.char || char - let a = profile.attr - let c = Format.comma - let p = Format.pct - let attr = { - hp: c(a.hp), - hpPlus: c(a.hp - a.hpBase), - atk: c(a.atk), - atkPlus: c(a.atk - a.atkBase), - def: c(a.def), - defPlus: c(a.def - a.defBase), - cpct: p(a.cpct), - cdmg: p(a.cdmg), - mastery: c(a.mastery), - recharge: p(a.recharge), - dmg: p(Math.max(a.dmg * 1 || 0, a.phy * 1 || 0)) - } - - let enemyLv = await selfUser.getCfg('char.enemyLv', 91) - let dmgMsg = [] - let dmgData = [] - let dmgCalc = await profile.calcDmg({ - enemyLv, - mode, - ...params - }) - if (dmgCalc && dmgCalc.ret) { - lodash.forEach(dmgCalc.ret, (ds) => { - ds.dmg = Format.comma(ds.dmg, 0) - ds.avg = Format.comma(ds.avg, 0) - dmgData.push(ds) + async getProfileDmgCalc ({ profile, enemyLv, mode, params }) { + let dmgMsg = [] + let dmgData = [] + let dmgCalc = await profile.calcDmg({ + enemyLv, + mode, + ...params }) - lodash.forEach(dmgCalc.msg, (msg) => { - msg.replace(':', ':') - dmgMsg.push(msg.split(':')) - }) - } - - 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) + if (dmgCalc && dmgCalc.ret) { + lodash.forEach(dmgCalc.ret, (ds) => { ds.dmg = Format.comma(ds.dmg, 0) ds.avg = Format.comma(ds.avg, 0) + dmgData.push(ds) + }) + lodash.forEach(dmgCalc.msg, (msg) => { + msg.replace(':', ':') + dmgMsg.push(msg.split(':')) }) - }) - basic.dmg = Format.comma(basic.dmg) - basic.avg = Format.comma(basic.avg) - } - 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() - let artisKeyTitle = ProfileArtis.getArtisKeyTitle() - let imgs = char.getImgs(profile.costume) - let costumeSplash = profile.costumeSplash - // 渲染图像 - let msgRes = await Common.render('character/profile-detail', { - save_id: uid, - uid, - data: profile.getData('name,abbr,cons,level,weapon,talent,dataSource,updateTime'), - attr, - elem: char.elem, - dmgData, - dmgMsg, - dmgRet: dmgCalc.dmgRet || false, - dmgCfg: dmgCalc.dmgCfg || false, - artisDetail, - artisKeyTitle, - enemyLv, - imgs, - costumeSplash, - enemyName: dmgCalc.enemyName || '小宝', - talentMap: { a: '普攻', e: '战技', q: '爆发' }, - bodyClass: `char-${char.name}`, - mode, - changeProfile: e._profileMsg - }, { e, scale: 1.6, retMsgId: true }) - if (msgRes && msgRes.message_id) { - // 如果消息发送成功,就将message_id和图片路径存起来,3小时过期 - await redis.set(`miao:original-picture:${msgRes.message_id}`, JSON.stringify({ type: 'profile', img: costumeSplash }), { EX: 3600 * 3 }) + dmgCalc.dmgMsg = dmgMsg + dmgCalc.dmgData = dmgData + } + + 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 } - return true } + +export default ProfileDetail diff --git a/apps/profile/ProfileRank.js b/apps/profile/ProfileRank.js index 26ffcd53..b2ffbdd2 100644 --- a/apps/profile/ProfileRank.js +++ b/apps/profile/ProfileRank.js @@ -1,5 +1,5 @@ import { Character, ProfileRank, ProfileDmg, Player } from '../../models/index.js' -import { renderProfile } from './ProfileDetail.js' +import ProfileDetail from './ProfileDetail.js' import { Data, Common, Format } from '../../components/index.js' import lodash from 'lodash' @@ -32,7 +32,7 @@ export async function groupRank (e) { let player = Player.create(100000000) if (player.getProfile(char.id)) { e.uid = 100000000 - return await renderProfile(e, char) + return await ProfileDetail.render(e, char) } else { return true } @@ -51,7 +51,7 @@ export async function groupRank (e) { let uid = await ProfileRank.getGroupMaxUid(groupId, char.id, mode) if (uid) { e.uid = uid - return await renderProfile(e, char) + return await ProfileDetail.render(e, char) } else { if (mode === 'dmg' && !ProfileDmg.dmgRulePath(char.name)) { e.reply(`暂无排名:${char.name}暂不支持伤害计算,无法进行排名..`) diff --git a/models/Artifact.js b/models/Artifact.js index 3e4097bf..d2dfe700 100644 --- a/models/Artifact.js +++ b/models/Artifact.js @@ -75,7 +75,6 @@ class Artifact extends Base { static getAttrsByIds (ids, star = 5) { let ret = [] let tmp = {} - let starEff = { 1: 0.21, 2: 0.36, 3: 0.6, 4: 0.8, 5: 1 } lodash.forEach(ids, (id) => { let cfg = attrIdMap[id] if (!cfg) { @@ -85,14 +84,12 @@ class Artifact extends Base { if (!tmp[key]) { tmp[key] = { key, - eff: 0, upNum: 0, value: 0 } ret.push(tmp[key]) } - tmp[key].eff += value / attrMap[key].value * starEff[star] - tmp[key].value += value * (attrMap[key].format === 'pct' ? 100 : 1) * starEff[star] + tmp[key].value += value * (attrMap[key].format === 'pct' ? 100 : 1) tmp[key].upNum++ }) return ret diff --git a/models/ProfileData.js b/models/ProfileData.js index b20ff8af..1a7020be 100644 --- a/models/ProfileData.js +++ b/models/ProfileData.js @@ -18,6 +18,10 @@ export default class ProfileData extends AvatarData { return this.isProfile } + get imgs(){ + return this.char.getImgs(this.costume) + } + get costumeSplash () { let costume = this._costume costume = this.char.checkCostume(costume) ? '2' : '' diff --git a/models/ProfileDmg.js b/models/ProfileDmg.js index 02e0d410..6882c811 100644 --- a/models/ProfileDmg.js +++ b/models/ProfileDmg.js @@ -21,7 +21,7 @@ export default class ProfileDmg extends Base { static dmgRulePath (name) { const _path = process.cwd() let path = `${_path}/plugins/miao-plugin/resources/meta/character/${name}/calc_auto.js` - if (fs.existsSync(path)&&Common.cfg('teamCalc')) { + if (fs.existsSync(path) && Common.cfg('teamCalc')) { return path } path = `${_path}/plugins/miao-plugin/resources/meta/character/${name}/calc.js` @@ -243,7 +243,8 @@ export default class ProfileDmg extends Base { msg, dmgRet, enemyName, - dmgCfg: dmgDetail + dmgCfg: dmgDetail, + enemyLv } } } diff --git a/models/ProfileReq.js b/models/ProfileReq.js index 29701290..80917581 100644 --- a/models/ProfileReq.js +++ b/models/ProfileReq.js @@ -56,7 +56,12 @@ export default class ProfileReq extends Base { } } + log (msg) { + logger.mark(`${logger.cyan(`【面板】${this.uid}`)} :${msg}`) + } + async requestProfile (player, serv) { + let self = this this.serv = serv let uid = this.uid let reqParam = await serv.getReqParam(uid) @@ -65,7 +70,6 @@ export default class ProfileReq extends Base { return this.err(`请求过快,请${cdTime}秒后重试..`) } await this.setCd(20) - let self = this // 若3秒后还未响应则返回提示 setTimeout(() => { if (self._isReq) { @@ -73,7 +77,8 @@ export default class ProfileReq extends Base { } }, 3000) // 发起请求 - logger.mark(`面板请求UID:${uid},面板服务:${serv.name}...`) + this.log(`${logger.yellow('开始请求数据')},面板服务:${serv.name}...`) + const startTime = new Date() * 1 let data = {} try { let params = reqParam.params || {} @@ -82,6 +87,8 @@ export default class ProfileReq extends Base { let req = await fetch(reqParam.url, params) data = await req.text() self._isReq = false + const reqTime = new Date() * 1 - startTime + this.log(`${logger.green(`请求结束,请求用时${reqTime}ms`)},面板服务:${serv.name}...`) if (data[0] === '<') { let titleRet = /