From 52b9a5b1b338c7c9ebba3a243979bd74b0831ce9 Mon Sep 17 00:00:00 2001 From: bietiaop <1527109126@qq.com> Date: Fri, 26 Jul 2024 16:45:15 +0800 Subject: [PATCH] =?UTF-8?q?rebase:=20=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E7=A7=BB=E5=8A=A8=E6=A8=A1=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/panel.js | 8 - lib/convert/property.js | 26 +++ model/avatar.js | 192 ++++++++++++++----- model/damage/avatar.js | 282 +++++++++++++++++----------- model/damage/base.js | 93 ---------- model/damage/relice.js | 73 ++++---- model/damage/role.js | 381 ++++++++++++++++++++++++-------------- model/damage/weapon.js | 43 ++--- model/equip.js | 10 + resources/panel/card.html | 4 +- 10 files changed, 653 insertions(+), 459 deletions(-) delete mode 100644 model/damage/base.js diff --git a/apps/panel.js b/apps/panel.js index 2e0d9c6..f6b08d2 100644 --- a/apps/panel.js +++ b/apps/panel.js @@ -2,7 +2,6 @@ import { ZZZPlugin } from '../lib/plugin.js'; import render from '../lib/render.js'; import { rulePrefix } from '../lib/common.js'; import { getPanelList, refreshPanel, getPanel } from '../lib/avatar.js'; -import { getDamage } from '../model/damage/base.js'; import settings from '../lib/settings.js'; import _ from 'lodash'; import { getMapData } from '../utils/file.js'; @@ -92,12 +91,6 @@ export class Panel extends ZZZPlugin { await this.reply(`未找到角色${name}的面板信息,请先刷新面板`); return; } - let damagelist = []; - if (skilldict[data.id]){ - damagelist = await getDamage(data); - }else{ - damagelist = 0 - } const timer = setTimeout(() => { if (this?.reply) { this.reply('查询成功,正在下载图片资源,请稍候。'); @@ -108,7 +101,6 @@ export class Panel extends ZZZPlugin { const finalData = { uid: uid, charData: data, - damagelist: damagelist, }; await render(this.e, 'panel/card.html', finalData); } diff --git a/lib/convert/property.js b/lib/convert/property.js index 2336d84..d4da2fb 100644 --- a/lib/convert/property.js +++ b/lib/convert/property.js @@ -1,3 +1,5 @@ +import { getMapData } from '../../utils/file.js'; +const propertyData = getMapData('Property2Name'); const prop_id = { 111: 'hpmax', 121: 'attack', @@ -39,3 +41,27 @@ export function idToClassName(_id) { if (!propIcon) return null; return propIcon; } + +/** + * 获取属性标识 + * @param {string} _id 属性id + * @returns {string | null} + */ +export const idToSignName = _id => { + const id = _id.toString(); + const result = propertyData[id]; + if (!result) return null; + return result[0]; +}; + +/** + * 获取属性名称 + * @param {string} _id 属性id + * @returns {string | null} + */ +export const idToName = _id => { + const id = _id.toString(); + const result = propertyData[id]; + if (!result) return null; + return result[1]; +}; diff --git a/model/avatar.js b/model/avatar.js index fc1d1de..e5b38de 100644 --- a/model/avatar.js +++ b/model/avatar.js @@ -1,9 +1,13 @@ -import { element } from '../lib/convert.js'; +import { element, property } from '../lib/convert.js'; import { getRoleImage, getSquareAvatar } from '../lib/download.js'; import { imageResourcesPath } from '../lib/path.js'; import { Equip, Weapon } from './equip.js'; import { Property } from './property.js'; import { Skill } from './skill.js'; +import { relice_ability } from './damage/relice.js'; +import { weapon_ability } from './damage/weapon.js'; +import { avatar_ability } from './damage/avatar.js'; +import _ from 'lodash'; import fs from 'fs'; import path from 'path'; @@ -185,42 +189,6 @@ export class ZZZAvatarInfo { * }} data */ constructor(data) { - // 类型标注 - /** @type {number} */ - this.id; - /** @type {number} */ - this.level; - /** @type {string} */ - this.name_mi18n; - /** @type {string} */ - this.full_name_mi18n; - /** @type {number} */ - this.element_type; - /** @type {string} */ - this.camp_name_mi18n; - /** @type {number} */ - this.avatar_profession; - /** @type {string} */ - this.rarity; - /** @type {string} */ - this.group_icon_path; - /** @type {string} */ - this.hollow_icon_path; - /** @type {Equip[]} */ - this.equip; - /** @type {Weapon} */ - this.weapon; - /** @type {Property[]} */ - this.properties; - /** @type {Skill[]} */ - this.skills; - /** @type {number} */ - this.rank; - /** @type {Rank[]} */ - this.ranks; - /** @type {boolean} */ - this.isNew; - const { id, level, @@ -240,31 +208,50 @@ export class ZZZAvatarInfo { ranks, isNew, } = data; + logger.debug('ZZZAvatarInfo', data); + /** @type {number} */ this.id = id; + /** @type {number} */ this.level = level; + /** @type {string} */ this.name_mi18n = name_mi18n; + /** @type {string} */ this.full_name_mi18n = full_name_mi18n; + /** @type {number} */ this.element_type = element_type; + /** @type {string} */ this.camp_name_mi18n = camp_name_mi18n; + /** @type {number} */ this.avatar_profession = avatar_profession; + /** @type {string} */ this.rarity = rarity; + /** @type {string} */ this.group_icon_path = group_icon_path; + /** @type {string} */ this.hollow_icon_path = hollow_icon_path; + /** @type {Equip[]} */ this.equip = - equip && - (Array.isArray(equip) - ? equip.map(equip => new Equip(equip)) - : new Equip(equip)); + (equip && + (Array.isArray(equip) + ? equip.map(equip => new Equip(equip)) + : new Equip(equip))) || + []; + /** @type {Weapon} */ this.weapon = weapon ? new Weapon(weapon) : null; + /** @type {Property[]} */ this.properties = properties && properties.map(property => new Property(property)); + /** @type {Skill[]} */ this.skills = skills && skills.map(skill => new Skill(skill)); + /** @type {number} */ this.rank = rank; + /** @type {Rank[]} */ this.ranks = ranks && ranks.map(rank => new Rank(rank)); - + /** @type {number} */ this.ranks_num = this.ranks.filter(rank => rank.is_unlocked).length; - + /** @type {string} */ this.element_str = element.IDToElement(element_type); + /** @type {boolean} */ this.isNew = isNew; } @@ -272,6 +259,18 @@ export class ZZZAvatarInfo { return this.properties.find(property => property.property_name === name); } + /** @type {{ + * hpmax: Property; + * attack: Property; + * def: Property; + * breakstun: Property; + * crit: Property; + * critdam: Property; + * elementabnormalpower: Property; + * elementmystery: Property; + * penratio: Property; + * sprecover: Property; + * }} */ get basic_properties() { const data = { hpmax: this.getProperty('生命值'), @@ -289,8 +288,113 @@ export class ZZZAvatarInfo { return data; } + /** @type {{ + * base_detail: { + * hp: number; + * attack: number; + * defence: number; + * ImpactRatio: number; + * CriticalChanceBase: number; + * CriticalDamageBase: number; + * ElementAbnormalPower: number; + * ElementMystery: number; + * PenRatioBase: number; + * SpGetRatio: number; + * } + * bonus_detail: Record; + * set_detail: Record; + * }} */ + get damage_basic_properties() { + const base_detail = { + hp: Number(this.basic_properties.hpmax.final), + attack: Number(this.basic_properties.attack.final), + defence: Number(this.basic_properties.def.final), + ImpactRatio: Number(this.basic_properties.breakstun.final), + CriticalChanceBase: + Number(this.basic_properties.crit.final.replace('%', '')) / 100, + CriticalDamageBase: + Number(this.basic_properties.critdam.final.replace('%', '')) / 100, + ElementAbnormalPower: Number( + this.basic_properties.elementabnormalpower.final + ), + ElementMystery: Number(this.basic_properties.elementmystery.final), + PenRatioBase: + Number(this.basic_properties.penratio.final.replace('%', '')) / 100, + SpGetRatio: Number(this.basic_properties.sprecover.final), + }; + /** 计算伤害加成与穿透值 + * 穿透值23203 + * 伤害加成31503-31703 + */ + const bonus_detail = {}; + /** 计算套装数量 */ + const set_detail = {}; + for (const equip_detail of this.equip) { + bonus_detail['PenDelta'] = + _.get(bonus_detail, 'PenDelta', 0) + equip_detail.get_property(23203); + if (equip_detail.equipment_type == 5) { + const propname = property.idToName( + equip_detail.main_properties[0].property_id + ); + if (propname.includes('属性伤害提高')) { + const propenname = property.idToSignName( + equip_detail.main_properties[0].property_id + ); + bonus_detail[propenname] = + _.get(bonus_detail, propenname, 0) + + Number(equip_detail.main_properties[0].base.replace('%', '')) / 100; + } + } + const suit_id = String(equip_detail.equip_suit.suit_id); + set_detail[suit_id] = _.get(set_detail, suit_id, 0) + 1; + } + logger.debug('base_detail', base_detail); + logger.debug('bonus_detail', bonus_detail); + logger.debug('set_detail', set_detail); + const retuan_detail = { + base_detail: base_detail, + bonus_detail: bonus_detail, + set_detail: set_detail, + }; + return retuan_detail; + } + + /** @type {{ + * title: string; + * value: {name: string, value: number}[] + * }[]} */ + get damages() { + /** 处理基础数据 */ + let base_detail = this.damage_basic_properties.base_detail; + let bonus_detail = this.damage_basic_properties.bonus_detail; + let set_detail = this.damage_basic_properties.set_detail; + + /** 处理驱动盘套装加成 */ + let set_detailkeys = Object.keys(set_detail); + for (const set_id of set_detailkeys) { + const set_num = set_detail[set_id]; + if (set_num >= 2) + bonus_detail = relice_ability( + set_id, + set_num, + base_detail, + bonus_detail + ); + } + logger.debug('bonus_detail', bonus_detail); + + /** 处理音频加成 */ + bonus_detail = weapon_ability(this.weapon, base_detail, bonus_detail); + logger.debug('bonus_detail', bonus_detail); + + /** 处理角色加成 */ + const damagelist = avatar_ability(this, base_detail, bonus_detail); + return damagelist; + } + async get_basic_assets() { const result = await getSquareAvatar(this.id); + /** @type {string} */ this.square_icon = result; } @@ -312,7 +416,7 @@ export class ZZZAvatarInfo { if (!role_icon) { role_icon = await getRoleImage(this.id); } - + /** @type {string} */ this.role_icon = role_icon; await this?.weapon?.get_assets?.(); for (const equip of this.equip) { diff --git a/model/damage/avatar.js b/model/damage/avatar.js index 4c18d7d..402fefc 100644 --- a/model/damage/avatar.js +++ b/model/damage/avatar.js @@ -1,119 +1,177 @@ +import _ from 'lodash'; import { getMapData } from '../../utils/file.js'; import { calculate_damage } from './role.js'; +import { ZZZAvatarInfo } from '../avatar.js'; const skilldict = getMapData('SkillData'); +/** + * 角色加成 + * @param {ZZZAvatarInfo} data 角色信息 + * @param {ZZZAvatarInfo['damage_basic_properties']['base_detail']} base_detail 基础属性 + * @param {ZZZAvatarInfo['damage_basic_properties']['bonus_detail']} bonus_detail 套装加成 + * @returns {{ + * title: string, + * value: {name: string, value: number}[] + * }[]} 伤害列表 + */ +export const avatar_ability = (data, base_detail, bonus_detail) => { + const damagelist = []; + if (data.id == 1191) { + /** 处理命座加成 */ + if (data.rank >= 1) { + const CriticalChanceBase = _.get(bonus_detail, 'CriticalChanceBase', 0); + bonus_detail['CriticalChanceBase'] = CriticalChanceBase + 0.12; + } + if (data.rank >= 2) { + const ES_CriticalDamageBase = _.get( + bonus_detail, + 'ES_CriticalDamageBase', + 0 + ); + bonus_detail['ES_CriticalDamageBase'] = ES_CriticalDamageBase + 0.6; + const EH_CriticalDamageBase = _.get( + bonus_detail, + 'EH_CriticalDamageBase', + 0 + ); + bonus_detail['EH_CriticalDamageBase'] = EH_CriticalDamageBase + 0.6; + } + if (data.rank >= 6) { + const PenRatio = _.get(bonus_detail, 'PenRatioBase', 0); + bonus_detail['PenRatioBase'] = PenRatio + 0.2; -export const get_let_value = async (let_list, name) => { - if (let_list[name]) { - return let_list[name] - } - return 0 -} + const C_DmgAdd = _.get(bonus_detail, 'C_DmgAdd', 0); + bonus_detail['C_DmgAdd'] = C_DmgAdd + 2.5; + } -export const Avatar = async (data, base_detail, bonus_detail) => { - let damagelist = [] - if (data.id == 1191){ - /** 处理命座加成 */ - if (data.rank >= 1){ - let CriticalChanceBase = await get_let_value(bonus_detail, 'CriticalChanceBase'); - bonus_detail['CriticalChanceBase'] = CriticalChanceBase + 0.12; - } - if (data.rank >= 2){ - let ES_CriticalDamageBase = await get_let_value(bonus_detail, 'ES_CriticalDamageBase'); - bonus_detail['ES_CriticalDamageBase'] = ES_CriticalDamageBase + 0.6; - let EH_CriticalDamageBase = await get_let_value(bonus_detail, 'EH_CriticalDamageBase'); - bonus_detail['EH_CriticalDamageBase'] = EH_CriticalDamageBase + 0.6; - } - if (data.rank >= 6){ - let PenRatio = await get_let_value(bonus_detail, 'PenRatioBase'); - bonus_detail['PenRatioBase'] = PenRatio + 0.2; - - let C_DmgAdd = await get_let_value(bonus_detail, 'C_DmgAdd'); - bonus_detail['C_DmgAdd'] = C_DmgAdd + 2.5; - } - - /** 处理天赋加成 */ - /** 获取天赋等级与加成倍率 */ - let CDB = await getskilllevelnum(data.id, data.skills, 'T', 'T') - let C_CriticalDamageBase = await get_let_value(bonus_detail, 'C_CriticalDamageBase'); - bonus_detail['C_CriticalDamageBase'] = C_CriticalDamageBase + CDB; - let A_CriticalDamageBase = await get_let_value(bonus_detail, 'A_CriticalDamageBase'); - bonus_detail['A_CriticalDamageBase'] = A_CriticalDamageBase + CDB; - - let IceDmgAdd = await get_let_value(bonus_detail, 'Ice_DmgAdd'); - bonus_detail['Ice_DmgAdd'] = IceDmgAdd + 0.3; - - /** 计算伤害 */ - /** 计算普攻伤害 */ - let skill_multiplier1 = await getskilllevelnum(data.id, data.skills, 'A', 'A') - let damagelist1 = await calculate_damage(base_detail, bonus_detail, "A", "A", "Ice", skill_multiplier1, data.level) - let damage1 = { - title: '普通攻击:急冻修剪法', - value: damagelist1 - } - damagelist.push(damage1) - - /** 计算冲刺伤害 */ - let skill_multiplier2 = await getskilllevelnum(data.id, data.skills, 'C', 'C') - let damagelist2 = await calculate_damage(base_detail, bonus_detail, "C", "C", "Ice", skill_multiplier2, data.level) - let damage2 = { - title: '冲刺攻击:冰渊潜袭', - value: damagelist2 - } - damagelist.push(damage2) - - /** 计算特殊技伤害 */ - let skill_multiplier3 = await getskilllevelnum(data.id, data.skills, 'E', 'EH') - let damagelist3 = await calculate_damage(base_detail, bonus_detail, "E", "EH", "Ice", skill_multiplier3, data.level) - let damage3 = { - title: '强化特殊技:横扫', - value: damagelist3 - } - damagelist.push(damage3) - - let skill_multiplier4 = await getskilllevelnum(data.id, data.skills, 'E', 'ES') - let damagelist4 = await calculate_damage(base_detail, bonus_detail, "E", "ES", "Ice", skill_multiplier4, data.level) - let damage4 = { - title: '强化特殊技:鲨卷风', - value: damagelist4 - } - damagelist.push(damage4) - - /** 计算连携技伤害 */ - let skill_multiplier5 = await getskilllevelnum(data.id, data.skills, 'R', 'RL') - let damagelist5 = await calculate_damage(base_detail, bonus_detail, "RL", "RL", "Ice", skill_multiplier5, data.level) - let damage5 = { - title: '连携技:雪崩', - value: damagelist5 - } - damagelist.push(damage5) - - /** 计算终结技伤害 */ - let skill_multiplier6 = await getskilllevelnum(data.id, data.skills, 'R', 'R') - let damagelist6 = await calculate_damage(base_detail, bonus_detail, "R", "R", "Ice", skill_multiplier6, data.level) - let damage6 = { - title: '终结技:永冬狂宴', - value: damagelist6 - } - damagelist.push(damage6) - - logger.debug('伤害', damagelist); - } - return damagelist; + /** 处理天赋加成 */ + /** 获取天赋等级与加成倍率 */ + const CDB = getskilllevelnum(data.id, data.skills, 'T', 'T'); + const C_CriticalDamageBase = _.get(bonus_detail, 'C_CriticalDamageBase', 0); + bonus_detail['C_CriticalDamageBase'] = C_CriticalDamageBase + CDB; + const A_CriticalDamageBase = _.get(bonus_detail, 'A_CriticalDamageBase', 0); + bonus_detail['A_CriticalDamageBase'] = A_CriticalDamageBase + CDB; + + const IceDmgAdd = _.get(bonus_detail, 'Ice_DmgAdd', 0); + bonus_detail['Ice_DmgAdd'] = IceDmgAdd + 0.3; + + /** 计算伤害 */ + /** 计算普攻伤害 */ + const skill_multiplier1 = getskilllevelnum(data.id, data.skills, 'A', 'A'); + const damagelist1 = calculate_damage( + base_detail, + bonus_detail, + 'A', + 'A', + 'Ice', + skill_multiplier1, + data.level + ); + const damage1 = { + title: '普通攻击:急冻修剪法', + value: damagelist1, + }; + damagelist.push(damage1); + + /** 计算冲刺伤害 */ + const skill_multiplier2 = getskilllevelnum(data.id, data.skills, 'C', 'C'); + const damagelist2 = calculate_damage( + base_detail, + bonus_detail, + 'C', + 'C', + 'Ice', + skill_multiplier2, + data.level + ); + const damage2 = { + title: '冲刺攻击:冰渊潜袭', + value: damagelist2, + }; + damagelist.push(damage2); + + /** 计算特殊技伤害 */ + const skill_multiplier3 = getskilllevelnum(data.id, data.skills, 'E', 'EH'); + const damagelist3 = calculate_damage( + base_detail, + bonus_detail, + 'E', + 'EH', + 'Ice', + skill_multiplier3, + data.level + ); + const damage3 = { + title: '强化特殊技:横扫', + value: damagelist3, + }; + damagelist.push(damage3); + + const skill_multiplier4 = getskilllevelnum(data.id, data.skills, 'E', 'ES'); + const damagelist4 = calculate_damage( + base_detail, + bonus_detail, + 'E', + 'ES', + 'Ice', + skill_multiplier4, + data.level + ); + const damage4 = { + title: '强化特殊技:鲨卷风', + value: damagelist4, + }; + damagelist.push(damage4); + + /** 计算连携技伤害 */ + const skill_multiplier5 = getskilllevelnum(data.id, data.skills, 'R', 'RL'); + const damagelist5 = calculate_damage( + base_detail, + bonus_detail, + 'RL', + 'RL', + 'Ice', + skill_multiplier5, + data.level + ); + const damage5 = { + title: '连携技:雪崩', + value: damagelist5, + }; + damagelist.push(damage5); + + /** 计算终结技伤害 */ + const skill_multiplier6 = getskilllevelnum(data.id, data.skills, 'R', 'R'); + const damagelist6 = calculate_damage( + base_detail, + bonus_detail, + 'R', + 'R', + 'Ice', + skill_multiplier6, + data.level + ); + const damage6 = { + title: '终结技:永冬狂宴', + value: damagelist6, + }; + damagelist.push(damage6); + + logger.debug('伤害', damagelist); + } + return damagelist; }; -export const avatar_ability = async (data, base_detail, bonus_detail) => { - const damagelist = await Avatar(data, base_detail, bonus_detail); - return damagelist; -} - -export const getskilllevelnum = async (avatarId, skills, skilltype, skillname) => { - let skill_typeid = 0 - if (skilltype == 'A') skill_typeid = 0; - else if(skilltype == 'C') skill_typeid = 2; - else if(skilltype == 'E') skill_typeid = 1; - else if(skilltype == 'R') skill_typeid = 3; - else if(skilltype == 'L') skill_typeid = 6; - else if(skilltype == 'T') skill_typeid = 5; - let skilllevel = Number(skills.find(property => property.skill_type === skill_typeid)?.level || 1) - 1; - return skilldict[avatarId][skillname][skilllevel]; -} +export const getskilllevelnum = (avatarId, skills, skilltype, skillname) => { + let skill_typeid = 0; + if (skilltype == 'A') skill_typeid = 0; + else if (skilltype == 'C') skill_typeid = 2; + else if (skilltype == 'E') skill_typeid = 1; + else if (skilltype == 'R') skill_typeid = 3; + else if (skilltype == 'L') skill_typeid = 6; + else if (skilltype == 'T') skill_typeid = 5; + let skilllevel = + Number( + skills.find(property => property.skill_type === skill_typeid)?.level || 1 + ) - 1; + return skilldict[avatarId][skillname][skilllevel]; +}; diff --git a/model/damage/base.js b/model/damage/base.js deleted file mode 100644 index 80638ba..0000000 --- a/model/damage/base.js +++ /dev/null @@ -1,93 +0,0 @@ -import { getMapData } from '../../utils/file.js'; -import { relice_ability } from './relice.js'; -import { weapon_ability } from './weapon.js'; -import { avatar_ability } from './avatar.js'; -const propertyData = getMapData('Property2Name'); -const elementData = getMapData('Avatarid2Element'); - -/** - * 获取某个角色的伤害 - * @param {ZZZAvatarInfo} data - * @returns {Promise} - logger.debug(xxx) - */ -export const getDamage = async (data) => { - /** 处理基础数据 */ - const retuan_detail = await get_base_info(data.properties,data.equip); - let base_detail = retuan_detail['base_detail']; - let bonus_detail = retuan_detail['bonus_detail']; - let set_detail = retuan_detail['set_detail']; - - /** 处理驱动盘套装加成 */ - let set_detailkeys = Object.keys(set_detail) - for (const set_id of set_detailkeys){ - let set_num = Number(set_detail[set_id]) - if (set_num >= 2)( - bonus_detail = await relice_ability(set_id, set_num, base_detail, bonus_detail) - ) - } - logger.debug('bonus_detail', bonus_detail); - - /** 处理音频加成 */ - bonus_detail = await weapon_ability(data.weapon, base_detail, bonus_detail) - logger.debug('bonus_detail', bonus_detail); - - /** 处理角色加成 */ - let damagelist = await avatar_ability(data, base_detail, bonus_detail) - return damagelist -}; - -/** - * 获取某个角色面包数据 - * @param {ZZZAvatarInfo} properties_l - * @param {ZZZAvatarInfo} equip - * @returns base_detail - */ -export const get_base_info = async (properties_l, equip) => { - let retuan_detail = {} - let base_detail = {} - base_detail['hp'] = Number(properties_l.find(property => property.property_name === '生命值').final); - base_detail['attack'] = Number(properties_l.find(property => property.property_name === '攻击力').final); - base_detail['defence'] = Number(properties_l.find(property => property.property_name === '防御力').final); - base_detail['ImpactRatio'] = Number(properties_l.find(property => property.property_name === '冲击力').final); - base_detail['CriticalChanceBase'] = Number(properties_l.find(property => property.property_name === '暴击率').final.replace('%', ''))/100; - base_detail['CriticalDamageBase'] = Number(properties_l.find(property => property.property_name === '暴击伤害').final.replace('%', ''))/100; - base_detail['ElementAbnormalPower'] = Number(properties_l.find(property => property.property_name === '异常掌控').final); - base_detail['ElementMystery'] = Number(properties_l.find(property => property.property_name === '异常精通').final); - base_detail['PenRatioBase'] = Number(properties_l.find(property => property.property_name === '穿透率').final.replace('%', ''))/100; - base_detail['SpGetRatio'] = Number(properties_l.find(property => property.property_name === '能量自动回复').final); - logger.debug('base_detail', base_detail); - retuan_detail['base_detail'] = base_detail - - /** 计算伤害加成与穿透值 - * 穿透值23203 - * 伤害加成31503-31703 - */ - let bonus_detail = {} - /** 计算套装数量 */ - let set_detail = {} - for (let equip_detail of equip){ - bonus_detail['PenDelta'] = await get_let_value(bonus_detail, 'PenDelta') + Number(equip_detail.properties.find(property => property.property_id === 23203)?.base || 0); - if (equip_detail.equipment_type == 5){ - let propname = propertyData[String(equip_detail.main_properties[0].property_id)][1]; - if (propname.includes('属性伤害提高')) { - let propenname = propertyData[String(equip_detail.main_properties[0].property_id)][0]; - bonus_detail[propenname] = await get_let_value(bonus_detail, propenname) + Number(equip_detail.main_properties[0].base.replace('%', ''))/100; - } - } - let suit_id = String(equip_detail.equip_suit.suit_id) - set_detail[suit_id] = await get_let_value(set_detail, suit_id) + 1 - } - logger.debug('bonus_detail', bonus_detail); - retuan_detail['bonus_detail'] = bonus_detail - logger.debug('set_detail', set_detail); - retuan_detail['set_detail'] = set_detail - return retuan_detail; -} - -export const get_let_value = async (let_list, name) => { - if (let_list[name]) { - return let_list[name] - } - return 0 -} \ No newline at end of file diff --git a/model/damage/relice.js b/model/damage/relice.js index 219863f..14d5a25 100644 --- a/model/damage/relice.js +++ b/model/damage/relice.js @@ -1,38 +1,37 @@ -export const get_let_value = async (let_list, name) => { - if (let_list[name]) { - return let_list[name] - } - return 0 -} +import _ from 'lodash'; +import { ZZZAvatarInfo } from '../avatar.js'; -export const Relic = async (set_id, set_num, base_detail, bonus_detail) => { - if (set_id == '31100'){ - if (set_num >= 4){ - let R_DmgAdd = await get_let_value(bonus_detail, 'R_DmgAdd'); - bonus_detail['R_DmgAdd'] = R_DmgAdd + 0.2; - let AttackAddedRatio = await get_let_value(bonus_detail, 'AttackAddedRatio'); - bonus_detail['AttackAddedRatio'] = AttackAddedRatio + 0.15; - logger.debug('relicGetter,4,R_DmgAdd'); - } - }else if(set_id == '32500'){ - if (set_num >= 2){ - let IceDmgAdd = await get_let_value(bonus_detail, 'Ice_DmgAdd'); - bonus_detail['Ice_DmgAdd'] = IceDmgAdd + 0.1; - logger.debug('32500,2,Ice_DmgAdd'); - } - if (set_num >= 4){ - let A_DmgAdd = await get_let_value(bonus_detail, 'A_DmgAdd'); - bonus_detail['A_DmgAdd'] = A_DmgAdd + 0.4; - let C_DmgAdd = await get_let_value(bonus_detail, 'C_DmgAdd'); - bonus_detail['C_DmgAdd'] = C_DmgAdd + 0.4; - logger.debug('32500,4,A_DmgAdd'); - logger.debug('32500,4,C_DmgAdd'); - } - } - return bonus_detail; -} - -export const relice_ability = async (set_id, set_num, base_detail, bonus_detail) => { - bonus_detail = await Relic(set_id, set_num, base_detail, bonus_detail); - return bonus_detail; -} +/** + * + * @param {string} set_id 套装id + * @param {number} set_num 套装数量 + * @param {ZZZAvatarInfo['damage_basic_properties']['base_detail']} base_detail 基础属性 + * @param {ZZZAvatarInfo['damage_basic_properties']['bonus_detail']} bonus_detail 套装加成 + * @returns {ZZZAvatarInfo['damage_basic_properties']['bonus_detail']} 套装加成 + */ +export const relice_ability = (set_id, set_num, base_detail, bonus_detail) => { + if (set_id == '31100') { + if (set_num >= 4) { + let R_DmgAdd = _.get(bonus_detail, 'R_DmgAdd', 0); + bonus_detail['R_DmgAdd'] = R_DmgAdd + 0.2; + let AttackAddedRatio = _.get(bonus_detail, 'AttackAddedRatio', 0); + bonus_detail['AttackAddedRatio'] = AttackAddedRatio + 0.15; + logger.debug('relicGetter,4,R_DmgAdd'); + } + } else if (set_id == '32500') { + if (set_num >= 2) { + let IceDmgAdd = _.get(bonus_detail, 'Ice_DmgAdd', 0); + bonus_detail['Ice_DmgAdd'] = IceDmgAdd + 0.1; + logger.debug('32500,2,Ice_DmgAdd'); + } + if (set_num >= 4) { + let A_DmgAdd = _.get(bonus_detail, 'A_DmgAdd', 0); + bonus_detail['A_DmgAdd'] = A_DmgAdd + 0.4; + let C_DmgAdd = _.get(bonus_detail, 'C_DmgAdd', 0); + bonus_detail['C_DmgAdd'] = C_DmgAdd + 0.4; + logger.debug('32500,4,A_DmgAdd'); + logger.debug('32500,4,C_DmgAdd'); + } + } + return bonus_detail; +}; diff --git a/model/damage/role.js b/model/damage/role.js index 094d406..adf4f9d 100644 --- a/model/damage/role.js +++ b/model/damage/role.js @@ -1,150 +1,247 @@ -export const get_let_value = async (let_list, name) => { - if (let_list[name]) { - return let_list[name] - } - return 0 -} +import _ from 'lodash'; -export const calculate_damage = async (base_detail, bonus_detail, skill_type, add_skill_type, avatar_element, skill_multiplier, level) => { - let merged_attr = await merge_attribute(base_detail, bonus_detail) - logger.debug('merged_attr', merged_attr); - - let attack = merged_attr.attack - logger.debug('攻击区', attack); - - let defence_multiplier = await get_defence_multiplier(merged_attr, level); - logger.debug('防御区', defence_multiplier); - - let injury_area = await get_injury_area(merged_attr, skill_type, add_skill_type, avatar_element); - logger.debug('增伤区', injury_area); - - let damage_ratio = await get_damage_ratio(merged_attr, skill_type, add_skill_type, avatar_element); - logger.debug('易伤区', damage_ratio); - - let critical_damage_base = await get_critical_damage_base(merged_attr, skill_type, add_skill_type, avatar_element); - logger.debug('爆伤区', critical_damage_base); - - let critical_chance_base = await get_critical_chance_base(merged_attr, skill_type, add_skill_type, avatar_element); - logger.debug('暴击区', critical_chance_base); - - let qiwang_damage = critical_chance_base * critical_damage_base - logger.debug('暴击期望', qiwang_damage); - - let damagelist = {} - let damage_cd = attack * skill_multiplier * defence_multiplier * injury_area * damage_ratio * critical_damage_base * 1.2 * 1.5 - let damage_qw = attack * skill_multiplier * defence_multiplier * injury_area * damage_ratio * qiwang_damage * 1.2 * 1.5 - damagelist['cd'] = damage_cd - damagelist['qw'] = damage_qw - return damagelist +export const calculate_damage = ( + base_detail, + bonus_detail, + skill_type, + add_skill_type, + avatar_element, + skill_multiplier, + level +) => { + const merged_attr = merge_attribute(base_detail, bonus_detail); + logger.debug('merged_attr', merged_attr); + + const attack = merged_attr.attack; + logger.debug('攻击区', attack); + + const defence_multiplier = get_defence_multiplier(merged_attr, level); + logger.debug('防御区', defence_multiplier); + + const injury_area = get_injury_area( + merged_attr, + skill_type, + add_skill_type, + avatar_element + ); + logger.debug('增伤区', injury_area); + + const damage_ratio = get_damage_ratio( + merged_attr, + skill_type, + add_skill_type, + avatar_element + ); + logger.debug('易伤区', damage_ratio); + + const critical_damage_base = get_critical_damage_base( + merged_attr, + skill_type, + add_skill_type, + avatar_element + ); + logger.debug('爆伤区', critical_damage_base); + + const critical_chance_base = get_critical_chance_base( + merged_attr, + skill_type, + add_skill_type, + avatar_element + ); + logger.debug('暴击区', critical_chance_base); + + const qiwang_damage = critical_chance_base * critical_damage_base; + logger.debug('暴击期望', qiwang_damage); + + const damage_cd = + attack * + skill_multiplier * + defence_multiplier * + injury_area * + damage_ratio * + critical_damage_base * + 1.2 * + 1.5; + const damage_qw = + attack * + skill_multiplier * + defence_multiplier * + injury_area * + damage_ratio * + qiwang_damage * + 1.2 * + 1.5; + + const damagelist = { + cd: damage_cd, + qw: damage_qw, + }; + return damagelist; }; -export const get_critical_chance_base = async (merged_attr, skill_type, add_skill_type, avatar_element) => { - let critical_chance_base = await get_let_value(merged_attr, 'CriticalChanceBase') - let merged_attrkey = Object.keys(merged_attr) - for (const attr of merged_attrkey){ - if (attr.search('_CriticalChanceBase') != -1) { - let attr_name = attr.split('_CriticalChanceBase')[0] - if ([skill_type, add_skill_type, 'All', avatar_element].includes(attr_name)) { - logger.debug(attr + '对' + attr_name + '有' + merged_attr[attr] + '暴击加成') - critical_chance_base = critical_chance_base + merged_attr[attr] - } - } - } - critical_chance_base = Math.min(1, critical_chance_base) - return critical_chance_base -} - -export const get_critical_damage_base = async (merged_attr, skill_type, add_skill_type, avatar_element) => { - let critical_damage_base = await get_let_value(merged_attr, 'CriticalDamageBase') - let merged_attrkey = Object.keys(merged_attr) - for (const attr of merged_attrkey){ - if (attr.search('_CriticalDamageBase') != -1) { - let attr_name = attr.split('_CriticalDamageBase')[0] - if ([skill_type, add_skill_type, 'All', avatar_element].includes(attr_name)) { - logger.debug(attr + '对' + attr_name + '有' + merged_attr[attr] + '爆伤加成') - critical_damage_base = critical_damage_base + merged_attr[attr] - } - } - } - return critical_damage_base + 1 -} - -export const get_damage_ratio = async (merged_attr, skill_type, add_skill_type, avatar_element) => { - let damage_ratio = await get_let_value(merged_attr, 'DmgRatio') - let merged_attrkey = Object.keys(merged_attr) - for (const attr of merged_attrkey){ - if (attr.search('_DmgRatio') != -1) { - let attr_name = attr.split('_DmgRatio')[0] - if ([skill_type, add_skill_type, 'All', avatar_element].includes(attr_name)) { - logger.debug(attr + '对' + attr_name + '有' + merged_attr[attr] + '易伤加成') - damage_ratio = damage_ratio + merged_attr[attr] - } - } - } - return damage_ratio + 1 -} - -export const get_injury_area = async (merged_attr, skill_type, add_skill_type, avatar_element) => { - let injury_area = 1.0 - let merged_attrkey = Object.keys(merged_attr) - for (const attr of merged_attrkey){ - if (attr.search('_DmgAdd') != -1) { - let attr_name = attr.split('_DmgAdd')[0] - if ([skill_type, add_skill_type, 'All', avatar_element].includes(attr_name)) { - logger.debug(attr + '对' + attr_name + '有' + merged_attr[attr] + '增伤') - injury_area = injury_area + merged_attr[attr] - } - } - if (attr.search('AddedRatio') != -1) { - let attr_name = attr.split('AddedRatio')[0] - if ([avatar_element, 'AllDamage'].includes(attr_name)) { - logger.debug(attr + '对' + attr_name + '有' + merged_attr[attr] + '增伤') - injury_area = injury_area + merged_attr[attr] - } +export const get_critical_chance_base = ( + merged_attr, + skill_type, + add_skill_type, + avatar_element +) => { + let critical_chance_base = _.get(merged_attr, 'CriticalChanceBase', 0); + const merged_attrkey = Object.keys(merged_attr); + for (const attr of merged_attrkey) { + if (attr.search('_CriticalChanceBase') != -1) { + const attr_name = attr.split('_CriticalChanceBase')[0]; + if ( + [skill_type, add_skill_type, 'All', avatar_element].includes(attr_name) + ) { + logger.debug( + attr + '对' + attr_name + '有' + merged_attr[attr] + '暴击加成' + ); + critical_chance_base = critical_chance_base + merged_attr[attr]; } - } - return injury_area -} - -export const get_defence_multiplier = async (merged_attr, level) => { - /** 计算防御基础值 */ - let defadd = (0.155 * (level * level)) + (3.12 * level) + 46.95 - /** 计算降防 */ - let ignore_defence = 1.0 - if (merged_attr.ignore_defence) { - ignore_defence = 1 - merged_attr.ignore_defence } - /** 计算穿透率 */ - let penratio = 1.0 - if (merged_attr.PenRatioBase) { - penratio = 1 - merged_attr.PenRatioBase + } + critical_chance_base = Math.min(1, critical_chance_base); + return critical_chance_base; +}; + +export const get_critical_damage_base = ( + merged_attr, + skill_type, + add_skill_type, + avatar_element +) => { + let critical_damage_base = _.get(merged_attr, 'CriticalDamageBase', 0); + const merged_attrkey = Object.keys(merged_attr); + for (const attr of merged_attrkey) { + if (attr.search('_CriticalDamageBase') != -1) { + const attr_name = attr.split('_CriticalDamageBase')[0]; + if ( + [skill_type, add_skill_type, 'All', avatar_element].includes(attr_name) + ) { + logger.debug( + attr + '对' + attr_name + '有' + merged_attr[attr] + '爆伤加成' + ); + critical_damage_base = critical_damage_base + merged_attr[attr]; + } } - /** 计算穿透值 */ - let pendelta = await get_let_value(merged_attr, 'PenDelta') - /** 计算防御乘区 */ - let defence_multiplier = defadd / (defadd + ((defadd * ignore_defence) * penratio - pendelta)) - return defence_multiplier - -} + } + return critical_damage_base + 1; +}; -export const merge_attribute = async (base_detail, bonus_detail) => { - let merged_attr = {} - let bonus_detailkey = Object.keys(bonus_detail) - for (const merged of bonus_detailkey){ - if (merged.search('Attack') != -1 || merged.search('Defence') != -1 || merged.search('HP') != -1) { - continue - } else if (merged.search('Base') != -1) { - merged_attr[merged] = await get_let_value(base_detail, merged) + await get_let_value(bonus_detail, merged) - } else { - merged_attr[merged] = await get_let_value(bonus_detail, merged) - } - } - merged_attr['hp'] = await get_let_value(bonus_detail, 'HPDelta') + await get_let_value(base_detail, 'hp') * (await get_let_value(bonus_detail, 'HPAddedRatio') + 1) - merged_attr['attack'] = await get_let_value(bonus_detail, 'AttackDelta') + await get_let_value(base_detail, 'attack') * (await get_let_value(bonus_detail, 'AttackAddedRatio') + 1) - merged_attr['defence'] = await get_let_value(bonus_detail, 'DefenceDelta') + await get_let_value(base_detail, 'defence') * (await get_let_value(bonus_detail, 'DefenceAddedRatio') + 1) - merged_attr['CriticalChanceBase'] = await get_let_value(bonus_detail, 'CriticalChanceBase') + await get_let_value(base_detail, 'CriticalChanceBase') - merged_attr['CriticalDamageBase'] = await get_let_value(bonus_detail, 'CriticalDamageBase') + await get_let_value(base_detail, 'CriticalDamageBase') - merged_attr['PenRatioBase'] = await get_let_value(bonus_detail, 'PenRatioBase') + await get_let_value(base_detail, 'PenRatioBase') - return merged_attr -} +export const get_damage_ratio = ( + merged_attr, + skill_type, + add_skill_type, + avatar_element +) => { + let damage_ratio = _.get(merged_attr, 'DmgRatio', 0); + const merged_attrkey = Object.keys(merged_attr); + for (const attr of merged_attrkey) { + if (attr.search('_DmgRatio') != -1) { + const attr_name = attr.split('_DmgRatio')[0]; + if ( + [skill_type, add_skill_type, 'All', avatar_element].includes(attr_name) + ) { + logger.debug( + attr + '对' + attr_name + '有' + merged_attr[attr] + '易伤加成' + ); + damage_ratio = damage_ratio + merged_attr[attr]; + } + } + } + return damage_ratio + 1; +}; +export const get_injury_area = ( + merged_attr, + skill_type, + add_skill_type, + avatar_element +) => { + let injury_area = 1.0; + const merged_attrkey = Object.keys(merged_attr); + for (const attr of merged_attrkey) { + if (attr.search('_DmgAdd') != -1) { + const attr_name = attr.split('_DmgAdd')[0]; + if ( + [skill_type, add_skill_type, 'All', avatar_element].includes(attr_name) + ) { + logger.debug( + attr + '对' + attr_name + '有' + merged_attr[attr] + '增伤' + ); + injury_area = injury_area + merged_attr[attr]; + } + } + if (attr.search('AddedRatio') != -1) { + const attr_name = attr.split('AddedRatio')[0]; + if ([avatar_element, 'AllDamage'].includes(attr_name)) { + logger.debug( + attr + '对' + attr_name + '有' + merged_attr[attr] + '增伤' + ); + injury_area = injury_area + merged_attr[attr]; + } + } + } + return injury_area; +}; + +export const get_defence_multiplier = (merged_attr, level) => { + /** 计算防御基础值 */ + const defadd = 0.155 * (level * level) + 3.12 * level + 46.95; + /** 计算降防 */ + let ignore_defence = 1.0; + if (merged_attr.ignore_defence) { + ignore_defence = 1 - merged_attr.ignore_defence; + } + /** 计算穿透率 */ + let penratio = 1.0; + if (merged_attr.PenRatioBase) { + penratio = 1 - merged_attr.PenRatioBase; + } + /** 计算穿透值 */ + const pendelta = _.get(merged_attr, 'PenDelta', 0); + /** 计算防御乘区 */ + const defence_multiplier = + defadd / (defadd + (defadd * ignore_defence * penratio - pendelta)); + return defence_multiplier; +}; + +export const merge_attribute = (base_detail, bonus_detail) => { + const merged_attr = {}; + const bonus_detailkey = Object.keys(bonus_detail); + for (const merged of bonus_detailkey) { + if ( + merged.search('Attack') != -1 || + merged.search('Defence') != -1 || + merged.search('HP') != -1 + ) { + continue; + } else if (merged.search('Base') != -1) { + merged_attr[merged] = + _.get(base_detail, merged, 0) + _.get(bonus_detail, merged, 0); + } else { + merged_attr[merged] = _.get(bonus_detail, merged, 0); + } + } + merged_attr['hp'] = + _.get(bonus_detail, 'HPDelta', 0) + + _.get(base_detail, 'hp', 0) * (_.get(bonus_detail, 'HPAddedRatio', 0) + 1); + merged_attr['attack'] = + _.get(bonus_detail, 'AttackDelta', 0) + + _.get(base_detail, 'attack', 0) * + (_.get(bonus_detail, 'AttackAddedRatio', 0) + 1); + merged_attr['defence'] = + _.get(bonus_detail, 'DefenceDelta', 0) + + _.get(base_detail, 'defence', 0) * + (_.get(bonus_detail, 'DefenceAddedRatio', 0) + 1); + merged_attr['CriticalChanceBase'] = + _.get(bonus_detail, 'CriticalChanceBase', 0) + + _.get(base_detail, 'CriticalChanceBase', 0); + merged_attr['CriticalDamageBase'] = + _.get(bonus_detail, 'CriticalDamageBase', 0) + + _.get(base_detail, 'CriticalDamageBase', 0); + merged_attr['PenRatioBase'] = + _.get(bonus_detail, 'PenRatioBase', 0) + + _.get(base_detail, 'PenRatioBase', 0); + return merged_attr; +}; diff --git a/model/damage/weapon.js b/model/damage/weapon.js index 752aead..b8c7909 100644 --- a/model/damage/weapon.js +++ b/model/damage/weapon.js @@ -1,26 +1,27 @@ +import _ from 'lodash'; import { getMapData } from '../../utils/file.js'; +import { ZZZAvatarInfo } from '../avatar.js'; const weapon_effect = getMapData('weapon_effect'); -export const get_let_value = async (let_list, name) => { - if (let_list[name]) { - return let_list[name] - } - return 0 -} +/** + * 武器加成 + * @param {ZZZAvatarInfo['weapon']} equipment 武器 + * @param {ZZZAvatarInfo['damage_basic_properties']['base_detail']} base_detail 基础属性 + * @param {ZZZAvatarInfo['damage_basic_properties']['bonus_detail']} bonus_detail 套装加成 + * @returns {ZZZAvatarInfo['damage_basic_properties']['bonus_detail']} 套装加成 + */ +export const weapon_ability = (equipment, base_detail, bonus_detail) => { + if (equipment.id == 14119) { + let IceDmgAdd = _.get(bonus_detail, 'Ice_DmgAdd', 0); + bonus_detail['Ice_DmgAdd'] = + IceDmgAdd + + weapon_effect['14119']['Param']['IceDmgAdd'][equipment.star - 1]; + logger.debug('14119,IceDmgAdd'); -export const Weapon = async (equipment, base_detail, bonus_detail) => { - if (equipment.id == 14119){ - let IceDmgAdd = await get_let_value(bonus_detail, 'Ice_DmgAdd'); - bonus_detail['Ice_DmgAdd'] = IceDmgAdd + weapon_effect['14119']['Param']['IceDmgAdd'][equipment.star - 1]; - logger.debug('14119,IceDmgAdd'); - - let CriticalChanceBase = await get_let_value(bonus_detail, 'CriticalChanceBase'); - bonus_detail['CriticalChanceBase'] = CriticalChanceBase + weapon_effect['14119']['Param']['CriticalChanceBase'][equipment.star - 1]; - } - return bonus_detail; + let CriticalChanceBase = _.get(bonus_detail, 'CriticalChanceBase', 0); + bonus_detail['CriticalChanceBase'] = + CriticalChanceBase + + weapon_effect['14119']['Param']['CriticalChanceBase'][equipment.star - 1]; + } + return bonus_detail; }; - -export const weapon_ability = async (equipment, base_detail, bonus_detail) => { - bonus_detail = await Weapon(equipment, base_detail, bonus_detail); - return bonus_detail; -} diff --git a/model/equip.js b/model/equip.js index 0f0fe2e..914f2e3 100644 --- a/model/equip.js +++ b/model/equip.js @@ -145,6 +145,16 @@ export class Equip { this.equipment_type = equipment_type; } + /** + * @param {number} id + * @returns {EquipProperty} + */ + get_property(id) { + const result = + this.properties.find(item => item.property_id === id)?.base || '0'; + return Number(result); + } + async get_assets() { const result = await getSuitImage(this.id); this.suit_icon = result; diff --git a/resources/panel/card.html b/resources/panel/card.html index 55a1c87..ce55c24 100644 --- a/resources/panel/card.html +++ b/resources/panel/card.html @@ -177,7 +177,7 @@ <% } %> - {{if damagelist}} + {{if charData.damages && charData.damages.length}}
<% include(sys.specialTitle, {en: 'DAMAGE' , cn: '伤害统计' }) %>
@@ -190,7 +190,7 @@ - {{each damagelist damage}} + {{each charData.damages damage}} {{damage.title}} {{damage.value.cd.toFixed(0)}}