diff --git a/apps/profile.js b/apps/profile.js index eb1e7fdd..876aef28 100644 --- a/apps/profile.js +++ b/apps/profile.js @@ -24,7 +24,7 @@ app.reg({ profileDetail: { name: '角色面板', fn: ProfileDetail.detail, - rule: /^#*([^#]+)\s*(详细|详情|面板|面版|圣遗物|武器[1-7]?|伤害[1-7]?)\s*(\d{9})*(.*[换变改].*)?$/ + rule: /^#*([^#]+)\s*(详细|详情|面板|面版|圣遗物|武器[1-7]?|伤害([1-9]+\d*)?)\s*(\d{9})*(.*[换变改].*)?$/ }, profileChange: { diff --git a/apps/profile/ProfileDetail.js b/apps/profile/ProfileDetail.js index 640a08fe..4f4bb765 100644 --- a/apps/profile/ProfileDetail.js +++ b/apps/profile/ProfileDetail.js @@ -48,8 +48,8 @@ let ProfileDetail = { let name = msg.replace(/#|老婆|老公|星铁|原神/g, '').trim() msg = msg.replace('面版', '面板') - let dmgRet = /(?:伤害|武器)(\d?)$/.exec(name) - let dmgIdx = 0 + let dmgRet = /(?:伤害|武器)(\d*)$/.exec(name) + let dmgIdx = 0, idxIsInput = false if (/(最强|最高|最高分|最牛|第一)/.test(msg)) { mode = /(分|圣遗物|评分|ACE)/.test(msg) ? 'rank-mark' : 'rank-dmg' name = name.replace(/(最强|最高分|第一|最高|最牛|圣遗物|评分|群)/g, '') @@ -60,9 +60,11 @@ let ProfileDetail = { } else if (dmgRet) { // mode = /武器/.test(msg) ? 'weapon' : 'dmg' mode = 'dmg' - name = name.replace(/(伤害|武器)+[0-7]?/, '').trim() + name = name.replace(/(伤害|武器)+\d*/, '').trim() if (dmgRet[1]) { dmgIdx = dmgRet[1] * 1 + // 标识是用户指定的序号 + idxIsInput = true } } else if (/(详情|详细|面板)更新$/.test(msg) || (/更新/.test(msg) && /(详情|详细|面板)$/.test(msg))) { mode = 'refresh' @@ -104,7 +106,7 @@ let ProfileDetail = { } if (mode === 'profile' || mode === 'dmg' || mode === 'weapon') { - return ProfileDetail.render(e, char, mode, { dmgIdx }) + return ProfileDetail.render(e, char, mode, { dmgIdx, idxIsInput }) } else if (mode === 'refresh') { await ProfileList.refresh(e) return true diff --git a/components/App.js b/components/App.js index c2cc9eac..707df89f 100644 --- a/components/App.js +++ b/components/App.js @@ -1,6 +1,6 @@ import lodash from 'lodash' import Plugin from './common/Plugin.js' -import { Version } from '#miao' +import { Version, MiaoError } from '#miao' class App { constructor (cfg) { @@ -91,7 +91,17 @@ class App { e.msg = '#poke#' } e.original_msg = e.original_msg || e.msg - return await app.fn.call(this, e) + try { + return await app.fn.call(this, e) + } catch (err) { + if (err?.message && (err instanceof MiaoError)) { + // 处理 MiaoError + return e.reply(err.message) + } else { + // 其他错误抛出 + throw err + } + } } if (app.yzRule && app.yzCheck) { diff --git a/components/MiaoError.js b/components/MiaoError.js new file mode 100644 index 00000000..0baff7a6 --- /dev/null +++ b/components/MiaoError.js @@ -0,0 +1,17 @@ +export default class MiaoError extends Error { + + constructor(message) { + // 允许返回特殊消息,需传递数组,例如 [segment.image()] + if (Array.isArray(message)) { + super() + this._message = message + } else { + super(message); + } + } + + get message() { + return this._message ? this._message : super.message; + } + +} \ No newline at end of file diff --git a/components/index.js b/components/index.js index 84f165e6..1fc0a357 100644 --- a/components/index.js +++ b/components/index.js @@ -4,5 +4,6 @@ import Common from './Common.js' import Cfg from './Cfg.js' import Version from './Version.js' import App from './App.js' +import MiaoError from './MiaoError.js' -export { Data, Cfg, Format, Common, Version, App } +export { Data, Cfg, Format, Common, Version, App, MiaoError } diff --git a/models/ProfileData.js b/models/ProfileData.js index 305ac2ae..5a5175a2 100644 --- a/models/ProfileData.js +++ b/models/ProfileData.js @@ -94,13 +94,13 @@ export default class ProfileData extends AvatarData { } // 计算当前profileData的伤害信息 - async calcDmg ({ enemyLv = 91, mode = 'profile', dmgIdx = 0 }) { + async calcDmg ({ enemyLv = 91, mode = 'profile', dmgIdx = 0, idxIsInput = false }) { if (!this.dmg) { 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.game) } - return await this.dmg.calcData({ enemyLv, mode, dmgIdx }) + return await this.dmg.calcData({ enemyLv, mode, dmgIdx, idxIsInput }) } } diff --git a/models/ProfileDmg.js b/models/ProfileDmg.js index 692abc35..25ab922c 100644 --- a/models/ProfileDmg.js +++ b/models/ProfileDmg.js @@ -7,7 +7,7 @@ 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' +import {Common, MiaoError} from '#miao' export default class ProfileDmg extends Base { constructor (profile = {}, game = 'gs') { @@ -98,7 +98,7 @@ export default class ProfileDmg extends Base { return false } - async calcData ({ enemyLv = 91, mode = 'profile', dmgIdx = 0 }) { + async calcData ({ enemyLv = 91, mode = 'profile', dmgIdx = 0, idxIsInput = false }) { if (!this.char || !this.profile) { return false } @@ -129,12 +129,19 @@ export default class ProfileDmg extends Base { buffs = this.getBuffs(buffs) let { msg } = DmgAttr.calcAttr({ originalAttr, buffs, meta, params: defParams || {} }) + let msgList = [] let ret = [] let detailMap = [] let dmgRet = [] let dmgDetail = {} + // 用户手动输入伤害序号 + if (idxIsInput) { + // 从1开始,所以需要 - 1 + dmgIdx = --dmgIdx < 0 ? 0 : dmgIdx + } + if (mode === 'single') { dmgIdx = defDmgIdx > -1 ? defDmgIdx : 0 } @@ -156,7 +163,7 @@ export default class ProfileDmg extends Base { detail = detail({ ...ds, attr, profile }) } let params = lodash.merge({}, defParams, detail?.params || {}) - let { attr } = DmgAttr.calcAttr({ originalAttr, buffs, meta, params, talent: detail.talent || '' }) + let { attr, msg } = DmgAttr.calcAttr({ originalAttr, buffs, meta, params, talent: detail.talent || '' }) if (detail.isStatic) { return } @@ -180,12 +187,16 @@ export default class ProfileDmg extends Base { ...basicDmgRet }) } + msgList.push(msg) }) if (mode === 'dmg') { let detail - if (dmgIdx && detailMap[dmgIdx - 1]) { - detail = detailMap[dmgIdx - 1] + if (idxIsInput && detailMap[dmgIdx]) { + detail = detailMap[dmgIdx] + } else if (idxIsInput) { + // 当用户输入的下标错误时,提示错误 + throw new MiaoError(`序号输入错误:${this.char.name}最多只支持${detailMap.length}种伤害计算哦`) } else if (!lodash.isUndefined(defDmgIdx) && details[defDmgIdx]) { detail = details[defDmgIdx] } else { @@ -247,7 +258,9 @@ export default class ProfileDmg extends Base { } return { ret, - msg, + // 根据当前计算的伤害,显示对应的buff列表 + msg: msgList[idxIsInput ? dmgIdx : (defDmgIdx > -1 ? defDmgIdx : dmgIdx)] || msg, + msgList, dmgRet, enemyName, dmgCfg: dmgDetail, diff --git a/resources/meta/character/妮露/calc_auto.js b/resources/meta/character/妮露/calc_auto.js index 64454425..022f6468 100644 --- a/resources/meta/character/妮露/calc_auto.js +++ b/resources/meta/character/妮露/calc_auto.js @@ -1,3 +1,6 @@ +// 纳西妲、妮露、艾尔海森、心海 +const team2 = createTeam('海妮心妲', ['纳西妲', '艾尔海森', '心海']) + export const details = [{ title: '水月伤害', params: { sy: true ,team:false}, @@ -29,26 +32,41 @@ export const details = [{ title: 'Q两段蒸发总伤害', params: { team:false }, dmg: ({ talent, calc, attr }, { basic }) => basic(calc(attr.hp) * (talent.q['技能伤害'] + talent.q['永世流沔伤害']) / 100, 'q', '蒸发') -}, { - title: '夜万妮香Q总蒸发伤害', - params: { team:true }, - dmg: ({ talent, calc, attr }, { basic }) => basic(calc(attr.hp) * (talent.q['技能伤害'] + talent.q['永世流沔伤害']) / 100, 'q', '蒸发') }, { title: '丰穰之核伤害', params: { bloom:true ,team:false }, dmg: ({calc, attr}, { reaction }) => { - return reaction('bloom')} + return reaction('bloom')} +}, { + title: '海妮心二妲·丰穰之核', + params: {team: false, bloom: true, ...team2.params}, + dmg: ({}, {reaction}) => { + // 草神二命固定暴击率20%、暴击伤害100% + const cpctNum = 20 / 100, cdmgNum = 100 / 100 + // 计算丰穰之核非暴击伤害 + const {avg} = reaction('bloom') + return { + // 暴击伤害 + dmg: avg * (1 + cdmgNum), + // 平均伤害 + avg: avg * (1 + cpctNum * cdmgNum) + } + } +}, { + title: '夜万妮香Q总蒸发伤害', + params: { team:true }, + dmg: ({ talent, calc, attr }, { basic }) => basic(calc(attr.hp) * (talent.q['技能伤害'] + talent.q['永世流沔伤害']) / 100, 'q', '蒸发') }] export const mainAttr = 'hp,atk,cpct,cdmg,mastery' export const defDmgIdx = 6 - export const defParams = { team:true, } -export const buffs = [{check: ({ params }) => params.team === false, +export const buffs = [{ + check: ({ params }) => params.team === false || team2.is(params), title: '妮露天赋:丰穰之核增伤[bloom]%,元素精通提升100点', data: { bloom: ({ calc, attr }) => Math.min(400,(calc(attr.hp)-30000)/1000*9), @@ -61,14 +79,14 @@ export const buffs = [{check: ({ params }) => params.team === false, eDmg: ({ params }) => params.sy ? 65 : 0 } }, { - check: ({params }) => params.team === false, + check: ({params }) => params.team === false || team2.is(params), title: '妮露2命:金杯的丰馈下降低敌人35%水抗与草抗', cons: 2, data: { kx: 35 } }, { - check: ({ cons,params }) => cons <= 1 && params.team === true, + check: ({ cons,params }) => cons <= 1 && params.team === true && team2.not(params), title: '精1苍古0命万叶:获得[dmg]%增伤(苍古普攻16增伤),增加[atkPct]%攻击,减抗[kx]%', data: { aDmg:16, @@ -79,7 +97,7 @@ export const buffs = [{check: ({ params }) => params.team === false, kx:40, } }, { - check: ({ cons,params }) => ((cons < 6 && cons >1) && params.team === true), + check: ({ cons,params }) => ((cons < 6 && cons >1) && params.team === true && team2.not(params)), title: '精1苍古2命万叶:获得[dmg]%增伤(苍古普攻16增伤),增加[atkPct]%攻击,减抗[kx]%,精通[mastery]', data: { aDmg:16, @@ -91,7 +109,7 @@ export const buffs = [{check: ({ params }) => params.team === false, mastery:200 } }, { - check: ({ cons,params }) => (cons >= 6 && params.team === true), + check: ({ cons,params }) => (cons >= 6 && params.team === true && team2.not(params)), title: '精5苍古6命万叶:获得[dmg]%增伤(苍古普攻32增伤),增加[atkPct]%攻击,减抗[kx]%,精通[mastery]', data: { aDmg:32, @@ -103,14 +121,14 @@ export const buffs = [{check: ({ params }) => params.team === false, mastery:200 } }, { - check: ({ cons,params }) => (cons >= 4 && params.team === true), + check: ({ cons,params }) => (cons >= 4 && params.team === true && team2.not(params)), title: '双水夜兰2层4命:双水,夜兰4命[hpPct]%生命值,[dmg]增伤', data: { hpPct: 45, dmg:30 } }, { - check: ({ cons,params }) => (cons < 4 && params.team === true), + check: ({ cons,params }) => (cons < 4 && params.team === true && team2.not(params)), title: '双水夜兰:双水[hpPct]%生命值,[dmg]增伤', data: { hpPct: 25, @@ -129,4 +147,50 @@ export const buffs = [{check: ({ params }) => params.team === false, cpct: ({ calc, attr }) => Math.min(30, calc(attr.hp) / 1000 * 0.6), cdmg: ({ calc, attr }) => Math.min(60, calc(attr.hp) / 1000 * 1.2) } +}, { + check: ({params}) => team2.is(params), + title: '双水双草共鸣:双水提升[hpPct]%生命值上限;双草提升精通50点,触发绽放再提升30点,共提升[mastery]点', + data: { + hpPct: 25, + mastery: 50 + 30, + } +}, { + check: ({params}) => team2.is(params), + title: '千精草套纳西妲开Q:增加[mastery]点精通,减[kx]%草抗', + data: { + mastery: 1000 * 0.25, + kx: 30 + } +}, { + check: ({params}) => team2.is(params), + title: '精1千夜浮梦:队伍中装备者以外的角色元素精通提升[mastery]点', + data: { + mastery: 40, + } +}, { + check: ({params}) => team2.is(params), + title: '纳西妲2命:提供绽放反应固定20%暴击率和100%的暴击伤害', + data: {} }, 'vaporize'] + +/** + * 创建队伍 + * @param name 队伍名 + * @param members 队员 + * @return {{name, members, params, go, is, not}} + */ +function createTeam(name, members) { + const team = {name, members} + // 队伍出战 + team.go = () => { + const params = {} + team.members.forEach(k => params[name + '_' + k] = true); + return params + } + team.params = team.go() + // 是否是当前配队 + team.is = (params) => members.filter(k => params[name + '_' + k] === true).length === members.length + // 是否不是当前配队 + team.not = (params) => !team.is(params) + return team +}