新增露西伤害计算等

This commit is contained in:
UCPr 2025-01-15 23:05:54 +08:00
parent 208cb0ae05
commit cecc33b24d
7 changed files with 265 additions and 133 deletions

View file

@ -9,7 +9,7 @@ export class Calculator {
avatar; avatar;
skills = []; skills = [];
cache = {}; cache = {};
damageCache = {}; props = {};
defaultSkill = {}; defaultSkill = {};
enemy; enemy;
constructor(buffM) { constructor(buffM) {
@ -54,8 +54,8 @@ export class Calculator {
return; return;
return this.calc_skill(MySkill); return this.calc_skill(MySkill);
} }
if (!skill.banCache && this.damageCache[skill.type]) if (!skill.banCache && this.cache[skill.type])
return this.damageCache[skill.type]; return this.cache[skill.type];
if (skill.check && !skill.check({ avatar: this.avatar, buffM: this.buffM, calc: this })) if (skill.check && !skill.check({ avatar: this.avatar, buffM: this.buffM, calc: this }))
return; return;
logger.debug(`${logger.green(skill.type)}${skill.name}伤害计算:`); logger.debug(`${logger.green(skill.type)}${skill.name}伤害计算:`);
@ -64,71 +64,74 @@ export class Calculator {
logger.debug('自定义计算最终伤害:', dmg.result); logger.debug('自定义计算最终伤害:', dmg.result);
return dmg; return dmg;
} }
this.cache = {}; const props = this.props = skill.props || {};
/** 缩小筛选范围 */ /** 缩小筛选范围 */
const usefulBuffs = this.buffM.filter({ const usefulBuffs = this.buffM.filter({
element: skill.element, element: skill.element,
range: skill.redirect ? [skill.type, skill.redirect] : [skill.type] range: skill.redirect ? [skill.type, skill.redirect] : [skill.type]
}, this); }, this);
const detail = {}; const areas = {};
if (skill.before) if (skill.before)
skill.before({ avatar: this.avatar, calc: this, detail, skill, usefulBuffs, }); skill.before({ avatar: this.avatar, calc: this, usefulBuffs, skill, props, areas });
const isAnomaly = typeof anomalyEnum[skill.type] === 'number'; const isAnomaly = typeof anomalyEnum[skill.type] === 'number';
if (!detail.BasicArea) { if (!areas.BasicArea) {
if (!detail.Multiplier) { let Multiplier = props.倍率;
if (!Multiplier) {
if (skill.fixedMultiplier) { if (skill.fixedMultiplier) {
detail.Multiplier = skill.fixedMultiplier; Multiplier = skill.fixedMultiplier;
} }
else if (isAnomaly) { else if (isAnomaly) {
detail.Multiplier = (skill.type === '紊乱' ? Multiplier = (skill.type === '紊乱' ?
this.get_DiscoverMultiplier(skill) : this.get_DiscoverMultiplier(skill) :
this.get_AnomalyMultiplier(skill, usefulBuffs, skill.name.includes('每') ? 1 : 0)) || 0; this.get_AnomalyMultiplier(skill, usefulBuffs, skill.name.includes('每') ? 1 : 0)) || 0;
} }
else { else {
if (skill.skillMultiplier) if (skill.skillMultiplier)
detail.Multiplier = skill.skillMultiplier[this.get_SkillLevel(skill.type[0]) - 1]; Multiplier = skill.skillMultiplier[this.get_SkillLevel(skill.type[0]) - 1];
else else
detail.Multiplier = this.get_Multiplier(skill.type); Multiplier = this.get_SkillMultiplier(skill.type);
} }
const ExtraMultiplier = this.get_ExtraMultiplier(skill, usefulBuffs); const ExtraMultiplier = this.get_ExtraMultiplier(skill, usefulBuffs);
detail.Multiplier += ExtraMultiplier; Multiplier += ExtraMultiplier;
if (!detail.Multiplier) if (!Multiplier)
return logger.warn('技能倍率缺失:', skill); return logger.warn('技能倍率缺失:', skill);
if (ExtraMultiplier) if (ExtraMultiplier)
logger.debug(`最终倍率:${detail.Multiplier}`); logger.debug(`最终倍率:${Multiplier}`);
} }
detail.ATK ??= this.get_ATK(skill, usefulBuffs); props.倍率 = Multiplier;
this.get_ATK(skill, usefulBuffs);
areas.BasicArea = props.攻击力 * props.倍率;
} }
detail.BasicArea ??= detail.ATK * detail.Multiplier; logger.debug(`基础伤害区:${areas.BasicArea}`);
logger.debug(`基础伤害区:${detail.BasicArea}`);
if (isAnomaly) { if (isAnomaly) {
detail.AnomalyProficiencyArea ??= this.get_AnomalyProficiencyArea(skill, usefulBuffs); areas.AnomalyProficiencyArea ??= this.get_AnomalyProficiencyArea(skill, usefulBuffs);
detail.AnomalyBoostArea ??= this.get_AnomalyBoostArea(skill, usefulBuffs); areas.AnomalyBoostArea ??= this.get_AnomalyBoostArea(skill, usefulBuffs);
detail.LevelArea ??= this.get_LevelArea(); areas.LevelArea ??= this.get_LevelArea();
detail.AnomalyCRITRate ??= this.get_AnomalyCRITRate(skill, usefulBuffs); this.get_AnomalyCRITRate(skill, usefulBuffs);
detail.AnomalyCRITDMG ??= this.get_AnomalyCRITDMG(skill, usefulBuffs); this.get_AnomalyCRITDMG(skill, usefulBuffs);
detail.CriticalArea ??= 1 + detail.AnomalyCRITRate * (detail.AnomalyCRITDMG - 1); areas.CriticalArea ??= 1 + props.异常暴击率 * (props.异常暴击伤害 - 1);
} }
else { else {
detail.CRITRate ??= this.get_CRITRate(skill, usefulBuffs); this.get_CRITRate(skill, usefulBuffs);
detail.CRITDMG ??= this.get_CRITDMG(skill, usefulBuffs); this.get_CRITDMG(skill, usefulBuffs);
detail.CriticalArea ??= 1 + detail.CRITRate * (detail.CRITDMG - 1); areas.CriticalArea ??= 1 + props.暴击率 * (props.暴击伤害 - 1);
} }
logger.debug(`暴击期望:${detail.CriticalArea}`); logger.debug(`暴击期望:${areas.CriticalArea}`);
detail.BoostArea ??= this.get_BoostArea(skill, usefulBuffs); areas.BoostArea ??= this.get_BoostArea(skill, usefulBuffs);
detail.VulnerabilityArea ??= this.get_VulnerabilityArea(skill, usefulBuffs); areas.VulnerabilityArea ??= this.get_VulnerabilityArea(skill, usefulBuffs);
detail.ResistanceArea ??= this.get_ResistanceArea(skill, usefulBuffs); areas.ResistanceArea ??= this.get_ResistanceArea(skill, usefulBuffs);
detail.DefenceArea ??= this.get_DefenceArea(skill, usefulBuffs); areas.DefenceArea ??= this.get_DefenceArea(skill, usefulBuffs);
const { BasicArea, CRITDMG, CriticalArea, BoostArea, VulnerabilityArea, ResistanceArea, DefenceArea, AnomalyProficiencyArea, LevelArea, AnomalyBoostArea, AnomalyCRITRate, AnomalyCRITDMG } = detail; const { BasicArea, CriticalArea, BoostArea, VulnerabilityArea, ResistanceArea, DefenceArea, AnomalyProficiencyArea, LevelArea, AnomalyBoostArea } = areas;
const { 暴击伤害, 异常暴击伤害 } = props;
const result = isAnomaly ? const result = isAnomaly ?
{ {
critDMG: AnomalyCRITRate ? BasicArea * AnomalyCRITDMG * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea * AnomalyProficiencyArea * LevelArea * AnomalyBoostArea : 0, critDMG: (CriticalArea !== 1) ? BasicArea * 异常暴击伤害 * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea * AnomalyProficiencyArea * LevelArea * AnomalyBoostArea : 0,
expectDMG: BasicArea * CriticalArea * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea * AnomalyProficiencyArea * LevelArea * AnomalyBoostArea expectDMG: BasicArea * CriticalArea * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea * AnomalyProficiencyArea * LevelArea * AnomalyBoostArea
} : { } : {
critDMG: BasicArea * CRITDMG * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea, critDMG: BasicArea * 暴击伤害 * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea,
expectDMG: BasicArea * CriticalArea * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea expectDMG: BasicArea * CriticalArea * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea
}; };
const damage = { skill, detail, result }; const damage = { skill, props, areas, result };
if (skill.after) { if (skill.after) {
damage.add = (d) => { damage.add = (d) => {
if (typeof d === 'string') if (typeof d === 'string')
@ -145,11 +148,12 @@ export class Calculator {
logger.debug('伤害系数:' + n); logger.debug('伤害系数:' + n);
damage.fnc(v => v * n); damage.fnc(v => v * n);
}; };
skill.after({ avatar: this.avatar, damage, calc: this, usefulBuffs }); skill.after({ avatar: this.avatar, calc: this, usefulBuffs, skill, damage });
} }
logger.debug('最终伤害:', result); logger.debug('最终伤害:', result);
if (!skill.banCache) if (!skill.banCache)
this.damageCache[skill.type] = damage; this.cache[skill.type] = damage;
// console.log(damage)
return damage; return damage;
} }
calc() { calc() {
@ -188,10 +192,10 @@ export class Calculator {
* 获取技能倍率 * 获取技能倍率
* @param type 参见技能命名标准 * @param type 参见技能命名标准
*/ */
get_Multiplier(type) { get_SkillMultiplier(type) {
const skillLevel = this.get_SkillLevel(type[0]); const SkillLevel = this.get_SkillLevel(type[0]);
logger.debug(`${type[0]}等级:${skillLevel}`); logger.debug(`${type[0]}等级:${SkillLevel}`);
const Multiplier = charData[this.avatar.id].skill[type]?.[skillLevel - 1]; const Multiplier = charData[this.avatar.id].skill[type]?.[SkillLevel - 1];
logger.debug(`技能倍率:${Multiplier}`); logger.debug(`技能倍率:${Multiplier}`);
return Multiplier; return Multiplier;
} }
@ -258,7 +262,7 @@ export class Calculator {
* @param isRatio 是否支持buff.value为数值类型且<1时按初始数值百分比提高处理 * @param isRatio 是否支持buff.value为数值类型且<1时按初始数值百分比提高处理
*/ */
get(type, initial, skill, usefulBuffs = this.buffM.buffs, isRatio = false) { get(type, initial, skill, usefulBuffs = this.buffM.buffs, isRatio = false) {
return this.cache[type] ??= this.buffM._filter(usefulBuffs, { return this.props[type] ??= this.buffM._filter(usefulBuffs, {
element: skill?.element, element: skill?.element,
range: skill?.redirect ? [skill.type, skill.redirect] : [skill?.type], range: skill?.redirect ? [skill.type, skill.redirect] : [skill?.type],
type type
@ -322,18 +326,24 @@ export class Calculator {
logger.debug(`抗性区:${ResistanceArea}`); logger.debug(`抗性区:${ResistanceArea}`);
return ResistanceArea; return ResistanceArea;
} }
/** 无视防御 */
get_IgnoreDEF(skill, usefulBuffs) {
const IgnoreDEF = this.get('无视防御', 0, skill, usefulBuffs);
IgnoreDEF && logger.debug(`无视防御:${IgnoreDEF}`);
return IgnoreDEF;
}
/** 穿透值 */ /** 穿透值 */
get_Pen(skill, usefulBuffs) { get_Pen(skill, usefulBuffs) {
let Pen = this.get('穿透值', this.initial_properties.Pen, skill, usefulBuffs); let Pen = this.get('穿透值', this.initial_properties.Pen, skill, usefulBuffs);
Pen = Math.max(0, Math.min(Pen, 1000)); Pen = Math.max(0, Math.min(Pen, 1000));
logger.debug(`穿透值:${Pen}`); Pen && logger.debug(`穿透值:${Pen}`);
return Pen; return Pen;
} }
/** 穿透率 */ /** 穿透率 */
get_PenRatio(skill, usefulBuffs) { get_PenRatio(skill, usefulBuffs) {
let PenRatio = this.get('穿透率', this.initial_properties.PenRatio, skill, usefulBuffs); let PenRatio = this.get('穿透率', this.initial_properties.PenRatio, skill, usefulBuffs);
PenRatio = Math.max(0, Math.min(PenRatio, 2)); PenRatio = Math.max(0, Math.min(PenRatio, 2));
logger.debug(`穿透率:${PenRatio}`); PenRatio && logger.debug(`穿透率:${PenRatio}`);
return PenRatio; return PenRatio;
} }
/** 防御区 */ /** 防御区 */
@ -343,11 +353,11 @@ export class Calculator {
const base = get_base(this.avatar.level); const base = get_base(this.avatar.level);
/** 基础防御 */ /** 基础防御 */
const DEF = this.enemy.basicDEF / 50 * get_base(this.enemy.level); const DEF = this.enemy.basicDEF / 50 * get_base(this.enemy.level);
const ignore_defence = this.get('无视防御', 0, skill, usefulBuffs); const IgnoreDEF = this.get_IgnoreDEF(skill, usefulBuffs);
const Pen = this.get_Pen(skill, usefulBuffs); const Pen = this.get_Pen(skill, usefulBuffs);
const PenRatio = this.get_PenRatio(skill, usefulBuffs); const PenRatio = this.get_PenRatio(skill, usefulBuffs);
/** 防御 */ /** 防御 */
const defence = DEF * (1 - ignore_defence); const defence = DEF * (1 - IgnoreDEF);
/** 有效防御 */ /** 有效防御 */
const effective_defence = Math.max(0, defence * (1 - PenRatio) - Pen); const effective_defence = Math.max(0, defence * (1 - PenRatio) - Pen);
const DefenceArea = base / (effective_defence + base); const DefenceArea = base / (effective_defence + base);
@ -377,21 +387,21 @@ export class Calculator {
/** 异常增伤区 */ /** 异常增伤区 */
get_AnomalyBoostArea(skill, usefulBuffs) { get_AnomalyBoostArea(skill, usefulBuffs) {
const AnomalyBoostArea = this.get('异常增伤', 1, skill, usefulBuffs); const AnomalyBoostArea = this.get('异常增伤', 1, skill, usefulBuffs);
logger.debug(`异常增伤区:${AnomalyBoostArea}`); AnomalyBoostArea && logger.debug(`异常增伤区:${AnomalyBoostArea}`);
return AnomalyBoostArea; return AnomalyBoostArea;
} }
/** 异常暴击率 */ /** 异常暴击率 */
get_AnomalyCRITRate(skill, usefulBuffs) { get_AnomalyCRITRate(skill, usefulBuffs) {
let AnomalyCRITRate = this.get('异常暴击率', 0, skill, usefulBuffs); let AnomalyCRITRate = this.get('异常暴击率', 0, skill, usefulBuffs);
AnomalyCRITRate = Math.max(0, Math.min(AnomalyCRITRate, 1)); AnomalyCRITRate = Math.max(0, Math.min(AnomalyCRITRate, 1));
logger.debug(`异常暴击率:${AnomalyCRITRate}`); AnomalyCRITRate && logger.debug(`异常暴击率:${AnomalyCRITRate}`);
return AnomalyCRITRate; return AnomalyCRITRate;
} }
/** 异常暴击伤害 */ /** 异常暴击伤害 */
get_AnomalyCRITDMG(skill, usefulBuffs) { get_AnomalyCRITDMG(skill, usefulBuffs) {
let AnomalyCRITDMG = this.get('异常暴击伤害', 1, skill, usefulBuffs); let AnomalyCRITDMG = this.get('异常暴击伤害', 1, skill, usefulBuffs);
AnomalyCRITDMG = Math.max(0, Math.min(AnomalyCRITDMG, 5)); AnomalyCRITDMG = Math.max(0, Math.min(AnomalyCRITDMG, 5));
logger.debug(`异常暴击伤害:${AnomalyCRITDMG}`); AnomalyCRITDMG && logger.debug(`异常暴击伤害:${AnomalyCRITDMG}`);
return AnomalyCRITDMG; return AnomalyCRITDMG;
} }
/** 异常持续时间 */ /** 异常持续时间 */

View file

@ -1,4 +1,4 @@
import type { BuffManager, anomaly, buff, element } from './BuffManager.ts' import type { BuffManager, anomaly, buff, buffType, element } from './BuffManager.ts'
import type { ZZZAvatarInfo } from '../avatar.js' import type { ZZZAvatarInfo } from '../avatar.js'
import { getMapData } from '../../utils/file.js' import { getMapData } from '../../utils/file.js'
import { elementEnum, anomalyEnum } from './BuffManager.js' import { elementEnum, anomalyEnum } from './BuffManager.js'
@ -15,10 +15,10 @@ export interface skill {
element: element element: element
/** 技能倍率数组于character/角色名/data.json中自动获取该json中不存在相应数据时可填写该值以填写值为准 */ /** 技能倍率数组于character/角色名/data.json中自动获取该json中不存在相应数据时可填写该值以填写值为准 */
skillMultiplier?: number[] skillMultiplier?: number[]
/** 指定固定技能倍率 */ /** 指定常数倍率(可吃倍率增益) */
fixedMultiplier?: number fixedMultiplier?: number
/** 角色面板伤害统计中是否隐藏显示 */ /** 指定局内固定属性 */
isHide?: boolean props?: { [key in buffType]?: number }
/** /**
* *
* *
@ -26,6 +26,8 @@ export interface skill {
* *
*/ */
redirect?: string redirect?: string
/** 角色面板伤害统计中是否隐藏显示 */
isHide?: boolean
/** 禁用伤害计算cache */ /** 禁用伤害计算cache */
banCache?: boolean banCache?: boolean
/** 是否计算该技能 */ /** 是否计算该技能 */
@ -36,19 +38,23 @@ export interface skill {
}) => boolean) }) => boolean)
/** 自定义计算逻辑 */ /** 自定义计算逻辑 */
dmg?: (calc: Calculator) => damage dmg?: (calc: Calculator) => damage
/** 额外处理 */ /** 伤害计算前调用,可自由定义各属性等 */
before?: ({ avatar, calc, usefulBuffs, detail, skill }: { before?: ({ avatar, calc, usefulBuffs, skill, props, areas }: {
avatar: ZZZAvatarInfo avatar: ZZZAvatarInfo
calc: Calculator calc: Calculator
detail: damage['detail']
usefulBuffs: buff[] usefulBuffs: buff[]
/** 技能自身 */ /** 技能自身 */
skill: skill skill: skill
props: damage['props']
areas: damage['areas']
}) => void }) => void
after?: ({ avatar, calc, usefulBuffs, damage }: { /** 伤害计算后调用,可对结果进行修改等 */
after?: ({ avatar, calc, usefulBuffs, skill, damage }: {
avatar: ZZZAvatarInfo avatar: ZZZAvatarInfo
calc: Calculator calc: Calculator
usefulBuffs: buff[] usefulBuffs: buff[]
/** 技能自身 */
skill: skill
damage: damage damage: damage
}) => void }) => void
} }
@ -56,18 +62,12 @@ export interface skill {
export interface damage { export interface damage {
/** 技能类型 */ /** 技能类型 */
skill: skill skill: skill
/** 各乘区详细数据 */ /** 技能属性 */
detail: { props?: skill['props']
/** 伤害倍率 */ /** 各乘区数据 */
Multiplier: number areas: {
/** 攻击力 */
ATK: number
/** 基础伤害区 */ /** 基础伤害区 */
BasicArea: number BasicArea: number
/** 暴击率 */
CRITRate: number
/** 暴伤伤害 */
CRITDMG: number
/** 暴击区期望 */ /** 暴击区期望 */
CriticalArea: number CriticalArea: number
/** 增伤区 */ /** 增伤区 */
@ -78,10 +78,6 @@ export interface damage {
ResistanceArea: number ResistanceArea: number
/** 防御区 */ /** 防御区 */
DefenceArea: number DefenceArea: number
/** 异常暴击率 */
AnomalyCRITRate: number
/** 异常暴击伤害 */
AnomalyCRITDMG: number
/** 异常精通区 */ /** 异常精通区 */
AnomalyProficiencyArea: number AnomalyProficiencyArea: number
/** 异常增伤区 */ /** 异常增伤区 */
@ -122,7 +118,7 @@ interface enemy {
level: number level: number
/** 1级基础防御力 */ /** 1级基础防御力 */
basicDEF: number basicDEF: number
/** 抗性 */ /** 抗性区常量 */
resistance: number resistance: number
} }
@ -130,8 +126,8 @@ export class Calculator {
readonly buffM: BuffManager readonly buffM: BuffManager
readonly avatar: ZZZAvatarInfo readonly avatar: ZZZAvatarInfo
readonly skills: skill[] = [] readonly skills: skill[] = []
private cache: { [key in buff['type']]?: number } = {} private cache: { [type: string]: damage } = {}
private damageCache: { [type: string]: damage } = {} private props: damage['props'] = {}
defaultSkill: { [key in keyof skill]?: skill[key] } = {} defaultSkill: { [key in keyof skill]?: skill[key] } = {}
enemy: enemy enemy: enemy
@ -194,7 +190,7 @@ export class Calculator {
if (!MySkill) return if (!MySkill) return
return this.calc_skill(MySkill) return this.calc_skill(MySkill)
} }
if (!skill.banCache && this.damageCache[skill.type]) return this.damageCache[skill.type] if (!skill.banCache && this.cache[skill.type]) return this.cache[skill.type]
if (skill.check && !skill.check({ avatar: this.avatar, buffM: this.buffM, calc: this })) return if (skill.check && !skill.check({ avatar: this.avatar, buffM: this.buffM, calc: this })) return
logger.debug(`${logger.green(skill.type)}${skill.name}伤害计算:`) logger.debug(`${logger.green(skill.type)}${skill.name}伤害计算:`)
if (skill.dmg) { if (skill.dmg) {
@ -202,68 +198,71 @@ export class Calculator {
logger.debug('自定义计算最终伤害:', dmg.result) logger.debug('自定义计算最终伤害:', dmg.result)
return dmg return dmg
} }
this.cache = {} const props = this.props = skill.props || {}
/** 缩小筛选范围 */ /** 缩小筛选范围 */
const usefulBuffs = this.buffM.filter({ const usefulBuffs = this.buffM.filter({
element: skill.element, element: skill.element,
range: skill.redirect ? [skill.type, skill.redirect] : [skill.type] range: skill.redirect ? [skill.type, skill.redirect] : [skill.type]
}, this) }, this)
const detail = {} as damage['detail'] const areas = {} as damage['areas']
if (skill.before) skill.before({ avatar: this.avatar, calc: this, detail, skill, usefulBuffs, }) if (skill.before) skill.before({ avatar: this.avatar, calc: this, usefulBuffs, skill, props, areas })
const isAnomaly = typeof anomalyEnum[skill.type as anomaly] === 'number' const isAnomaly = typeof anomalyEnum[skill.type as anomaly] === 'number'
if (!detail.BasicArea) { if (!areas.BasicArea) {
if (!detail.Multiplier) { let Multiplier = props.
if (!Multiplier) {
if (skill.fixedMultiplier) { if (skill.fixedMultiplier) {
detail.Multiplier = skill.fixedMultiplier Multiplier = skill.fixedMultiplier
} else if (isAnomaly) { } else if (isAnomaly) {
detail.Multiplier = ( Multiplier = (
skill.type === '紊乱' ? skill.type === '紊乱' ?
this.get_DiscoverMultiplier(skill) : this.get_DiscoverMultiplier(skill) :
this.get_AnomalyMultiplier(skill, usefulBuffs, skill.name.includes('每') ? 1 : 0) this.get_AnomalyMultiplier(skill, usefulBuffs, skill.name.includes('每') ? 1 : 0)
) || 0 ) || 0
} else { } else {
if (skill.skillMultiplier) detail.Multiplier = skill.skillMultiplier[this.get_SkillLevel(skill.type[0]) - 1] if (skill.skillMultiplier) Multiplier = skill.skillMultiplier[this.get_SkillLevel(skill.type[0]) - 1]
else detail.Multiplier = this.get_Multiplier(skill.type) else Multiplier = this.get_SkillMultiplier(skill.type)
} }
const ExtraMultiplier = this.get_ExtraMultiplier(skill, usefulBuffs) const ExtraMultiplier = this.get_ExtraMultiplier(skill, usefulBuffs)
detail.Multiplier += ExtraMultiplier Multiplier += ExtraMultiplier
if (!detail.Multiplier) return logger.warn('技能倍率缺失:', skill) if (!Multiplier) return logger.warn('技能倍率缺失:', skill)
if (ExtraMultiplier) logger.debug(`最终倍率:${detail.Multiplier}`) if (ExtraMultiplier) logger.debug(`最终倍率:${Multiplier}`)
} }
detail.ATK ??= this.get_ATK(skill, usefulBuffs) props. = Multiplier
this.get_ATK(skill, usefulBuffs)
areas.BasicArea = props.! * props.
} }
detail.BasicArea ??= detail.ATK * detail.Multiplier logger.debug(`基础伤害区:${areas.BasicArea}`)
logger.debug(`基础伤害区:${detail.BasicArea}`)
if (isAnomaly) { if (isAnomaly) {
detail.AnomalyProficiencyArea ??= this.get_AnomalyProficiencyArea(skill, usefulBuffs) areas.AnomalyProficiencyArea ??= this.get_AnomalyProficiencyArea(skill, usefulBuffs)
detail.AnomalyBoostArea ??= this.get_AnomalyBoostArea(skill, usefulBuffs) areas.AnomalyBoostArea ??= this.get_AnomalyBoostArea(skill, usefulBuffs)
detail.LevelArea ??= this.get_LevelArea() areas.LevelArea ??= this.get_LevelArea()
detail.AnomalyCRITRate ??= this.get_AnomalyCRITRate(skill, usefulBuffs) this.get_AnomalyCRITRate(skill, usefulBuffs)
detail.AnomalyCRITDMG ??= this.get_AnomalyCRITDMG(skill, usefulBuffs) this.get_AnomalyCRITDMG(skill, usefulBuffs)
detail.CriticalArea ??= 1 + detail.AnomalyCRITRate * (detail.AnomalyCRITDMG - 1) areas.CriticalArea ??= 1 + props.! * (props.! - 1)
} else { } else {
detail.CRITRate ??= this.get_CRITRate(skill, usefulBuffs) this.get_CRITRate(skill, usefulBuffs)
detail.CRITDMG ??= this.get_CRITDMG(skill, usefulBuffs) this.get_CRITDMG(skill, usefulBuffs)
detail.CriticalArea ??= 1 + detail.CRITRate * (detail.CRITDMG - 1) areas.CriticalArea ??= 1 + props.! * (props.! - 1)
} }
logger.debug(`暴击期望:${detail.CriticalArea}`) logger.debug(`暴击期望:${areas.CriticalArea}`)
detail.BoostArea ??= this.get_BoostArea(skill, usefulBuffs) areas.BoostArea ??= this.get_BoostArea(skill, usefulBuffs)
detail.VulnerabilityArea ??= this.get_VulnerabilityArea(skill, usefulBuffs) areas.VulnerabilityArea ??= this.get_VulnerabilityArea(skill, usefulBuffs)
detail.ResistanceArea ??= this.get_ResistanceArea(skill, usefulBuffs) areas.ResistanceArea ??= this.get_ResistanceArea(skill, usefulBuffs)
detail.DefenceArea ??= this.get_DefenceArea(skill, usefulBuffs) areas.DefenceArea ??= this.get_DefenceArea(skill, usefulBuffs)
const { const {
BasicArea, CRITDMG, CriticalArea, BoostArea, VulnerabilityArea, ResistanceArea, DefenceArea, BasicArea, CriticalArea, BoostArea, VulnerabilityArea, ResistanceArea, DefenceArea,
AnomalyProficiencyArea, LevelArea, AnomalyBoostArea, AnomalyCRITRate, AnomalyCRITDMG AnomalyProficiencyArea, LevelArea, AnomalyBoostArea
} = detail } = areas
const { , } = props
const result: damage['result'] = isAnomaly ? const result: damage['result'] = isAnomaly ?
{ {
critDMG: AnomalyCRITRate ? BasicArea * AnomalyCRITDMG * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea * AnomalyProficiencyArea * LevelArea * AnomalyBoostArea : 0, critDMG: (CriticalArea !== 1) ? BasicArea * ! * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea * AnomalyProficiencyArea * LevelArea * AnomalyBoostArea : 0,
expectDMG: BasicArea * CriticalArea * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea * AnomalyProficiencyArea * LevelArea * AnomalyBoostArea expectDMG: BasicArea * CriticalArea * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea * AnomalyProficiencyArea * LevelArea * AnomalyBoostArea
} : { } : {
critDMG: BasicArea * CRITDMG * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea, critDMG: BasicArea * ! * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea,
expectDMG: BasicArea * CriticalArea * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea expectDMG: BasicArea * CriticalArea * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea
} }
const damage: damage = { skill, detail, result } const damage: damage = { skill, props, areas, result }
if (skill.after) { if (skill.after) {
damage.add = (d) => { damage.add = (d) => {
if (typeof d === 'string') d = this.calc_skill(d) if (typeof d === 'string') d = this.calc_skill(d)
@ -279,10 +278,11 @@ export class Calculator {
logger.debug('伤害系数:' + n) logger.debug('伤害系数:' + n)
damage.fnc!(v => v * n) damage.fnc!(v => v * n)
} }
skill.after({ avatar: this.avatar, damage, calc: this, usefulBuffs }) skill.after({ avatar: this.avatar, calc: this, usefulBuffs, skill, damage })
} }
logger.debug('最终伤害:', result) logger.debug('最终伤害:', result)
if (!skill.banCache) this.damageCache[skill.type] = damage if (!skill.banCache) this.cache[skill.type] = damage
// console.log(damage)
return damage return damage
} }
@ -330,10 +330,10 @@ export class Calculator {
* *
* @param type * @param type
*/ */
get_Multiplier(type: string) { get_SkillMultiplier(type: string) {
const skillLevel = this.get_SkillLevel(type[0]) const SkillLevel = this.get_SkillLevel(type[0])
logger.debug(`${type[0]}等级:${skillLevel}`) logger.debug(`${type[0]}等级:${SkillLevel}`)
const Multiplier = charData[this.avatar.id].skill[type]?.[skillLevel - 1] const Multiplier = charData[this.avatar.id].skill[type]?.[SkillLevel - 1]
logger.debug(`技能倍率:${Multiplier}`) logger.debug(`技能倍率:${Multiplier}`)
return Multiplier return Multiplier
} }
@ -399,7 +399,7 @@ export class Calculator {
* @param isRatio buff.value为数值类型且<1时按初始数值百分比提高处理 * @param isRatio buff.value为数值类型且<1时按初始数值百分比提高处理
*/ */
get(type: buff['type'], initial: number, skill: skill, usefulBuffs: buff[] = this.buffM.buffs, isRatio = false): number { get(type: buff['type'], initial: number, skill: skill, usefulBuffs: buff[] = this.buffM.buffs, isRatio = false): number {
return this.cache[type] ??= this.buffM._filter(usefulBuffs, { return this.props![type] ??= this.buffM._filter(usefulBuffs, {
element: skill?.element, element: skill?.element,
range: skill?.redirect ? [skill.type, skill.redirect] : [skill?.type], range: skill?.redirect ? [skill.type, skill.redirect] : [skill?.type],
type type
@ -470,11 +470,18 @@ export class Calculator {
return ResistanceArea return ResistanceArea
} }
/** 无视防御 */
get_IgnoreDEF(skill: skill, usefulBuffs: buff[]) {
const IgnoreDEF = this.get('无视防御', 0, skill, usefulBuffs)
IgnoreDEF && logger.debug(`无视防御:${IgnoreDEF}`)
return IgnoreDEF
}
/** 穿透值 */ /** 穿透值 */
get_Pen(skill: skill, usefulBuffs: buff[]) { get_Pen(skill: skill, usefulBuffs: buff[]) {
let Pen = this.get('穿透值', this.initial_properties.Pen, skill, usefulBuffs) let Pen = this.get('穿透值', this.initial_properties.Pen, skill, usefulBuffs)
Pen = Math.max(0, Math.min(Pen, 1000)) Pen = Math.max(0, Math.min(Pen, 1000))
logger.debug(`穿透值:${Pen}`) Pen && logger.debug(`穿透值:${Pen}`)
return Pen return Pen
} }
@ -482,7 +489,7 @@ export class Calculator {
get_PenRatio(skill: skill, usefulBuffs: buff[]) { get_PenRatio(skill: skill, usefulBuffs: buff[]) {
let PenRatio = this.get('穿透率', this.initial_properties.PenRatio, skill, usefulBuffs) let PenRatio = this.get('穿透率', this.initial_properties.PenRatio, skill, usefulBuffs)
PenRatio = Math.max(0, Math.min(PenRatio, 2)) PenRatio = Math.max(0, Math.min(PenRatio, 2))
logger.debug(`穿透率:${PenRatio}`) PenRatio && logger.debug(`穿透率:${PenRatio}`)
return PenRatio return PenRatio
} }
@ -493,11 +500,11 @@ export class Calculator {
const base = get_base(this.avatar.level) const base = get_base(this.avatar.level)
/** 基础防御 */ /** 基础防御 */
const DEF = this.enemy.basicDEF / 50 * get_base(this.enemy.level) const DEF = this.enemy.basicDEF / 50 * get_base(this.enemy.level)
const ignore_defence = this.get('无视防御', 0, skill, usefulBuffs) const IgnoreDEF = this.get_IgnoreDEF(skill, usefulBuffs)
const Pen = this.get_Pen(skill, usefulBuffs) const Pen = this.get_Pen(skill, usefulBuffs)
const PenRatio = this.get_PenRatio(skill, usefulBuffs) const PenRatio = this.get_PenRatio(skill, usefulBuffs)
/** 防御 */ /** 防御 */
const defence = DEF * (1 - ignore_defence) const defence = DEF * (1 - IgnoreDEF)
/** 有效防御 */ /** 有效防御 */
const effective_defence = Math.max(0, defence * (1 - PenRatio) - Pen) const effective_defence = Math.max(0, defence * (1 - PenRatio) - Pen)
const DefenceArea = base / (effective_defence + base) const DefenceArea = base / (effective_defence + base)
@ -531,7 +538,7 @@ export class Calculator {
/** 异常增伤区 */ /** 异常增伤区 */
get_AnomalyBoostArea(skill: skill, usefulBuffs: buff[]) { get_AnomalyBoostArea(skill: skill, usefulBuffs: buff[]) {
const AnomalyBoostArea = this.get('异常增伤', 1, skill, usefulBuffs) const AnomalyBoostArea = this.get('异常增伤', 1, skill, usefulBuffs)
logger.debug(`异常增伤区:${AnomalyBoostArea}`) AnomalyBoostArea && logger.debug(`异常增伤区:${AnomalyBoostArea}`)
return AnomalyBoostArea return AnomalyBoostArea
} }
@ -539,7 +546,7 @@ export class Calculator {
get_AnomalyCRITRate(skill: skill, usefulBuffs: buff[]) { get_AnomalyCRITRate(skill: skill, usefulBuffs: buff[]) {
let AnomalyCRITRate = this.get('异常暴击率', 0, skill, usefulBuffs) let AnomalyCRITRate = this.get('异常暴击率', 0, skill, usefulBuffs)
AnomalyCRITRate = Math.max(0, Math.min(AnomalyCRITRate, 1)) AnomalyCRITRate = Math.max(0, Math.min(AnomalyCRITRate, 1))
logger.debug(`异常暴击率:${AnomalyCRITRate}`) AnomalyCRITRate && logger.debug(`异常暴击率:${AnomalyCRITRate}`)
return AnomalyCRITRate return AnomalyCRITRate
} }
@ -547,7 +554,7 @@ export class Calculator {
get_AnomalyCRITDMG(skill: skill, usefulBuffs: buff[]) { get_AnomalyCRITDMG(skill: skill, usefulBuffs: buff[]) {
let AnomalyCRITDMG = this.get('异常暴击伤害', 1, skill, usefulBuffs) let AnomalyCRITDMG = this.get('异常暴击伤害', 1, skill, usefulBuffs)
AnomalyCRITDMG = Math.max(0, Math.min(AnomalyCRITDMG, 5)) AnomalyCRITDMG = Math.max(0, Math.min(AnomalyCRITDMG, 5))
logger.debug(`异常暴击伤害:${AnomalyCRITDMG}`) AnomalyCRITDMG && logger.debug(`异常暴击伤害:${AnomalyCRITDMG}`)
return AnomalyCRITDMG return AnomalyCRITDMG
} }

View file

@ -138,7 +138,7 @@ export function set_buff(equip, buffM) {
}); });
} }
} }
const suit_name = String(equip_detail.equip_suit.name); const suit_name = equip_detail.equip_suit.name;
setCount[suit_name] = (setCount[suit_name] || 0) + 1; setCount[suit_name] = (setCount[suit_name] || 0) + 1;
} }
buffM.setCount = setCount; buffM.setCount = setCount;

View file

@ -163,7 +163,7 @@ export function set_buff(equip: ZZZAvatarInfo['equip'], buffM: BuffManager) {
}) })
} }
} }
const suit_name = String(equip_detail.equip_suit.name) const suit_name = equip_detail.equip_suit.name
setCount[suit_name] = (setCount[suit_name] || 0) + 1 setCount[suit_name] = (setCount[suit_name] || 0) + 1
} }
buffM.setCount = setCount buffM.setCount = setCount

View file

@ -77,14 +77,14 @@ export const skills = [
name: '强化E极性紊乱', name: '强化E极性紊乱',
type: '紊乱', type: '紊乱',
banCache: true, banCache: true,
before: ({ calc, detail }) => { before: ({ calc, areas }) => {
const skill = { type: '紊乱' } const skill = { type: '紊乱' }
const DiscoverMultiplier = calc.get_DiscoverMultiplier(skill) const DiscoverMultiplier = calc.get_DiscoverMultiplier(skill)
const n = calc.get('倍率', 0.15, { type: '强化E极性紊乱' }) const n = calc.get('倍率', 0.15, { type: '强化E极性紊乱' })
const ATK = calc.get_ATK(skill) const ATK = calc.get_ATK(skill)
const AnomalyProficiency = calc.get_AnomalyProficiency(skill) const AnomalyProficiency = calc.get_AnomalyProficiency(skill)
const skillMultiplier = calc.get_Multiplier('E极性紊乱') const skillMultiplier = calc.get_SkillMultiplier('E极性紊乱')
detail.BasicArea = DiscoverMultiplier * ATK * n + AnomalyProficiency * skillMultiplier areas.BasicArea = DiscoverMultiplier * ATK * n + AnomalyProficiency * skillMultiplier
} }
}, },
{ name: '连携技:星月相随', type: 'RL' }, { name: '连携技:星月相随', type: 'RL' },
@ -93,14 +93,14 @@ export const skills = [
name: '终结技极性紊乱', name: '终结技极性紊乱',
type: '紊乱', type: '紊乱',
banCache: true, banCache: true,
before: ({ calc, detail }) => { before: ({ calc, areas }) => {
const skill = { type: '紊乱' } const skill = { type: '紊乱' }
const DiscoverMultiplier = calc.get_DiscoverMultiplier(skill) const DiscoverMultiplier = calc.get_DiscoverMultiplier(skill)
const n = calc.get('倍率', 0.15, { type: '终结技极性紊乱' }) const n = calc.get('倍率', 0.15, { type: '终结技极性紊乱' })
const ATK = calc.get_ATK(skill) const ATK = calc.get_ATK(skill)
const AnomalyProficiency = calc.get_AnomalyProficiency(skill) const AnomalyProficiency = calc.get_AnomalyProficiency(skill)
const skillMultiplier = calc.get_Multiplier('R极性紊乱') const skillMultiplier = calc.get_SkillMultiplier('R极性紊乱')
detail.BasicArea = DiscoverMultiplier * ATK * n + AnomalyProficiency * skillMultiplier areas.BasicArea = DiscoverMultiplier * ATK * n + AnomalyProficiency * skillMultiplier
} }
} }
] ]

View file

@ -0,0 +1,76 @@
/** @type {import('../../BuffManager.ts').BuffManager['buffs']} */
export const buffs = [
{
name: '4影',
type: '暴击伤害',
value: 0.1
},
{
name: '技能:加油!',
type: '攻击力',
value: ({ calc }) => {
const ratio = calc.calc_value('E1')
const fixed = calc.calc_value('E2')
return Math.min(600, calc.initial_properties.ATK * ratio + fixed)
}
}
]
/** @type {import('../../Calculator.ts').skill['before']} */
const before = ({ calc, usefulBuffs, props }) => {
const jiayou = usefulBuffs.find(buff => buff.name === '技能:加油!')
const delta = calc.calc_value(jiayou?.value)
const ratio = calc.calc_value('T')
props.攻击力 = calc.get_ATK() + delta * (ratio - 1)
usefulBuffs.splice(0, usefulBuffs.length)
}
/** @type {import('../../Calculator.ts').Calculator['skills']} */
export const skills = [
{ name: '灼烧', type: '灼烧' },
{ name: '普攻:淑女的球棍四段', type: 'AP4' },
{
name: '亲卫队小猪:抄家伙!(弹弓)',
type: 'AZCD',
element: 'Physical',
props: {
穿透值: 0,
穿透率: 0
},
before
},
{
name: '亲卫队小猪:回旋挥击!',
type: 'AZH',
element: 'Physical',
props: {
穿透值: 0,
穿透率: 0
},
before
},
{
name: '6影小猪空中落地爆炸',
type: 'Y',
check: ({ avatar }) => avatar.rank >= 6,
fixedMultiplier: 3,
props: {
穿透值: 0,
穿透率: 0
},
before
},
{ name: '闪避反击:獠牙折转!', type: 'CF' },
{ name: '强化特殊技:全垒打短按', type: 'EQP' },
{ name: '强化特殊技:全垒打长按', type: 'EQX' },
{
name: '连携技:大满贯!',
type: 'RL',
after: ({ damage }) => damage.x(3)
},
{
name: '终结技:再见全垒打!',
type: 'RZ',
after: ({ damage }) => damage.x(3)
}
]

View file

@ -0,0 +1,39 @@
{
"skill": {
"AP4": [
2.726,2.974,3.222,3.47,3.718,3.966,4.214,4.462,4.71,4.958,5.206,5.454,5.702,5.95,6.198,6.446
],
"AZCD": [
1.75,1.91,2.07,2.23,2.39,2.55,2.71,2.87,3.03,3.19,3.35,3.51,3.67,3.83,3.99,4.15
],
"AZH": [
2.5,2.728,2.956,3.184,3.412,3.64,3.868,4.096,4.324,4.552,4.78,5.008,5.236,5.464,5.692,5.92
],
"CF": [
3.08,3.36,3.64,3.92,4.2,4.48,4.76,5.04,5.32,5.6,5.88,6.16,6.44,6.72,7,7.28
],
"EQP": [
5.084,5.547,6.01,6.473,6.936,7.399,7.862,8.325,8.788,9.251,9.714,10.177,10.64,11.103,11.566,12.029
],
"EQX": [
5.364,5.852,6.34,6.828,7.316,7.804,8.292,8.78,9.268,9.756,10.244,10.732,11.22,11.708,12.196,12.684
],
"RL": [
1.641,1.79,1.94,2.089,2.238,2.388,2.537,2.686,2.836,2.985,3.134,3.284,3.433,3.582,3.732,3.881
],
"RZ": [
5.728,6.249,6.77,7.291,7.812,8.333,8.854,9.375,9.896,10.417,10.938,11.459,11.98,12.501,13.022,13.543
]
},
"buff": {
"T": [
1.4,1.5,1.6,1.7,1.8,1.9,2
],
"E1": [
0.138,0.146,0.154,0.162,0.17,0.178,0.186,0.194,0.202,0.21,0.218,0.226,0.234,0.242,0.25,0.258
],
"E2": [
44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104
]
}
}