优化伤害计算等

This commit is contained in:
UCPr 2025-05-31 18:51:04 +08:00
parent 7ace8908ff
commit 95a2ee64de
50 changed files with 173 additions and 221 deletions

View file

@ -140,12 +140,12 @@ export const getPanelListOrigin = uid => {
* @returns {ZZZAvatarInfo | null}
*/
export const getPanel = (uid, name) => {
const _data = getPanelData(uid);
// 获取所有面板数据
const data = _data.map(item => new ZZZAvatarInfo(item));
// 通过名称(包括别名)获取角色 ID
const id = char.aliasToID(name);
if (!id) return null;
const _data = getPanelData(uid);
// 获取所有面板数据
const data = _data.map(item => new ZZZAvatarInfo(item));
// 通过 ID 获取角色数据
const result = data.find(item => item.id === id);
if (!result) return null;
@ -159,9 +159,9 @@ export const getPanel = (uid, name) => {
* @returns {ZZZAvatarInfo | null}
*/
export const getPanelOrigin = (uid, name) => {
const data = getPanelData(uid);
const id = char.aliasToID(name);
if (!id) return null;
const data = getPanelData(uid);
// 通过 ID 获取角色数据
const result = data.find(item => item.id === id);
if (!result) return null;

View file

@ -54,32 +54,29 @@ export class BuffManager {
buff.forEach(b => this.new(b));
return this.buffs;
}
if (!buff.name && (buff.source || this.defaultBuff.source) === 'Set' && this.defaultBuff.name && typeof buff.check === 'number')
if (!buff.name && (buff.source || this.defaultBuff.source) === '套装' && this.defaultBuff.name && typeof buff.check === 'number')
buff.name = this.defaultBuff.name + buff.check;
const oriBuff = buff;
buff = _.merge({
status: true,
isForever: false,
is: {},
...this.defaultBuff
}, buff);
if (buff.isForever)
buff.is.forever = true;
if (buff.range && !Array.isArray(buff.range))
buff.range = oriBuff.range = [buff.range];
if (!buff.source) {
if (buff.name.includes('核心') || buff.name.includes('天赋'))
buff.source = oriBuff.source = 'Talent';
buff.source = oriBuff.source = '核心被动';
else if (buff.name.includes('额外能力'))
buff.source = oriBuff.source = 'Addition';
buff.source = oriBuff.source = '额外能力';
else if (buff.name.includes('影'))
buff.source = oriBuff.source = 'Rank';
buff.source = oriBuff.source = '影画';
else if (buff.name.includes('技'))
buff.source = oriBuff.source = 'Skill';
buff.source = oriBuff.source = '技能';
}
if (!buff.name || !buff.value || !buff.source || !buffTypeEnum[buffTypeEnum[buff.type]])
return logger.warn('无效buff', buff);
if (buff.source === 'Weapon') {
if (buff.source === '音擎') {
const professionCheck = (avatar) => {
const weapon_profession = avatar.weapon?.profession;
if (!weapon_profession)
@ -89,7 +86,7 @@ export class BuffManager {
const oriCheck = typeof buff.check === 'function' && buff.check;
buff.check = ({ avatar, buffM, calc }) => professionCheck(avatar) && (!oriCheck || oriCheck({ avatar, buffM, calc }));
}
else if (buff.source === 'Rank') {
else if (buff.source === '影画') {
buff.check ??= oriBuff.check = +buff.name.match(/\d/)?.[0];
}
this.buffs.push(buff);
@ -150,9 +147,9 @@ export class BuffManager {
}
if (buff.check) {
if (typeof buff.check === 'number') {
if (buff.source === 'Set' && (this.setCount[buff.name.replace(/\d$/, '')] < buff.check))
if (buff.source === '套装' && (this.setCount[buff.name.replace(/\d$/, '')] < buff.check))
return false;
else if (buff.source === 'Rank' && (this.avatar.rank < buff.check))
else if (buff.source === '影画' && (this.avatar.rank < buff.check))
return false;
}
else if (valueOcalc) {

View file

@ -20,16 +20,8 @@ export type element = keyof typeof elementEnum
/** 异常类型 */
export type anomaly = keyof typeof anomalyEnum
/**
* Buff来源
* @Weapon
* @Set
* @Rank
* @Talent
* @Addition
* @Skill
*/
export type buffSource = 'Weapon' | 'Set' | 'Rank' | 'Talent' | 'Addition' | 'Skill'
/** Buff来源 */
export type buffSource = '音擎' | '套装' | '技能' | '影画' | '核心被动' | '额外能力'
export enum buffTypeEnum {
// 通用乘区
@ -48,8 +40,6 @@ export type buffType = keyof typeof buffTypeEnum
export interface buff {
/** Buff状态true生效false无效 */
status: boolean
/** Buff是否常驻 */
isForever?: boolean
/** Buff名称 */
name: string
/** Buff来源 */
@ -57,34 +47,35 @@ export interface buff {
/** Buff增益的类型 */
type: buffType
/**
* Buff增益数值
* Buff增益数值
* @number
* -
* - buff增益类型为**/////** **<1**则将此值理解为**初始属性****百分比提高**
* @array
* buff.source自动选择对应等级/source
* - Weapon
* - Talent/Addition
* @function
*
* @string
* buff提高值可能随技能/data.json的"buff"value即为键名
* @array
* buff.source自动选择对应等级/source
* -
* -
* @function
*
*/
value: number | (({ avatar, buffM, calc }: {
value: number | string | number[] | (({ avatar, buffM, calc }: {
avatar: ZZZAvatarInfo
buffM: BuffManager
calc: Calculator
}) => number) | string | number[]
}) => number)
/**
* Buff增益技能类型****
* - **redirect****range**
* - **redirect****range****redirect**
* - 使**include****exclude**
*/
range?: string[] | anomaly[] | "追加攻击"[]
/**
* Buff增益技能类型****
* - **range**
* - **range****include**buff对全部技能生
* - **range****include**buff对**exclude**
* - **range****include**buff生效
* - **redirect****range****include****include****redirect**
*/
@ -100,7 +91,7 @@ export interface buff {
/**
* buff是否生效
* @function
*
*
* @number
* - buff.source为Set时>=
* - buff.source为Rank时>=
@ -112,8 +103,6 @@ export interface buff {
}) => boolean) | number
/** Buff描述符 */
is: {
/** 是否常驻 @default false*/
forever?: boolean
/** 是否团队增益 @default false */
team?: boolean
/** 为团队增益时,同名效果是否可叠加 @default false */
@ -148,29 +137,26 @@ export class BuffManager {
return this.buffs
}
// 简化参数
if (!buff.name && (buff.source || this.defaultBuff.source) === 'Set' && this.defaultBuff.name && typeof buff.check === 'number')
if (!buff.name && (buff.source || this.defaultBuff.source) === '套装' && this.defaultBuff.name && typeof buff.check === 'number')
buff.name = this.defaultBuff.name + buff.check
const oriBuff = buff
buff = _.merge({
status: true,
isForever: false,
is: {},
...this.defaultBuff
}, buff)
if (buff.isForever)
buff.is.forever = true
if (buff.range && !Array.isArray(buff.range))
buff.range = oriBuff.range = [buff.range]
if (!buff.source) {
if (buff.name.includes('核心') || buff.name.includes('天赋')) buff.source = oriBuff.source = 'Talent'
else if (buff.name.includes('额外能力')) buff.source = oriBuff.source = 'Addition'
else if (buff.name.includes('影')) buff.source = oriBuff.source = 'Rank'
else if (buff.name.includes('技')) buff.source = oriBuff.source = 'Skill'
if (buff.name.includes('核心') || buff.name.includes('天赋')) buff.source = oriBuff.source = '核心被动'
else if (buff.name.includes('额外能力')) buff.source = oriBuff.source = '额外能力'
else if (buff.name.includes('影')) buff.source = oriBuff.source = '影画'
else if (buff.name.includes('技')) buff.source = oriBuff.source = '技能'
}
if (!buff.name || !buff.value || !buff.source || !buffTypeEnum[buffTypeEnum[buff.type]])
return logger.warn('无效buff', buff)
// 武器buff职业检查
if (buff.source === 'Weapon') {
// 音擎buff职业检查
if (buff.source === '音擎') {
const professionCheck = (avatar: ZZZAvatarInfo) => {
const weapon_profession = avatar.weapon?.profession
if (!weapon_profession) return true
@ -179,7 +165,7 @@ export class BuffManager {
const oriCheck = typeof buff.check === 'function' && buff.check
buff.check = ({ avatar, buffM, calc }) => professionCheck(avatar) && (!oriCheck || oriCheck({ avatar, buffM, calc }))
// 影画buff影画数检查
} else if (buff.source === 'Rank') {
} else if (buff.source === '影画') {
buff.check ??= oriBuff.check = +buff.name.match(/\d/)!?.[0]
}
this.buffs.push(buff)
@ -248,8 +234,8 @@ export class BuffManager {
}
if (buff.check) {
if (typeof buff.check === 'number') {
if (buff.source === 'Set' && (this.setCount[buff.name.replace(/\d$/, '')] < buff.check)) return false
else if (buff.source === 'Rank' && (this.avatar.rank < buff.check)) return false
if (buff.source === '套装' && (this.setCount[buff.name.replace(/\d$/, '')] < buff.check)) return false
else if (buff.source === '影画' && (this.avatar.rank < buff.check)) return false
} else if (valueOcalc) {
if (weakMapCheck.has(buff)) {
// console.log(`depth${depth} ${buff.name}${weakMapCheck.get(buff)}`)

View file

@ -38,7 +38,7 @@ export class Calculator {
buffM;
avatar;
skills = [];
usefulBuffs = [];
usefulBuffResults = new Map();
cache = Object.create(null);
props = {};
skill;
@ -173,8 +173,8 @@ export class Calculator {
critDMG: BasicArea * 暴击伤害 * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea,
expectDMG: BasicArea * CriticalArea * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea
};
const damage = { skill, usefulBuffs: _.sortBy(this.usefulBuffs, ['type', 'value']).reverse(), props, areas, result };
this.usefulBuffs = [];
const damage = { skill, usefulBuffs: _.sortBy(Array.from(this.usefulBuffResults.values()), ['type', 'value']).reverse(), props, areas, result };
this.usefulBuffResults.clear();
if (skill.after) {
damage.add = (d) => {
if (typeof d === 'string')
@ -266,14 +266,19 @@ export class Calculator {
const base = {};
types.forEach(t => base[t] = (t.includes('百分比') || ['异常掌控', '冲击力', '能量自动回复'].includes(t)) ? this.avatar.base_properties[prop.nameZHToNameEN(t.replace('百分比', ''))] * mainBaseValueData[t][0] : mainBaseValueData[t][0]);
logger.debug(logger.red('词条变化值:'), base);
const buffs = types.map(t => ({
name: t,
shortName: prop.nameToShortName3(t),
type: (t.includes('属性伤害加成') ? '增伤' : t.replace('百分比', '')),
value: base[t],
element: t.includes('属性伤害加成') ? prop.nameZHToNameEN(t).replace('DMGBonus', '') : undefined,
valueBase: mainBaseValueData[t][1]
}));
const buffs = types.map(t => {
const data = {
name: t,
shortName: prop.nameToShortName3(t),
type: (t.includes('属性伤害加成') ? '增伤' : t.replace('百分比', '')),
value: base[t],
element: (t.includes('属性伤害加成') ? prop.nameZHToNameEN(t).replace('DMGBonus', '') : ''),
valueBase: mainBaseValueData[t][1]
};
if (!data.element)
delete data.element;
return data;
});
buffs.push({
name: '空白对照',
shortName: '对照组',
@ -392,12 +397,11 @@ export class Calculator {
const anomalyData = this.get_AnomalyData(skill?.type.slice(0, 2));
if (!anomalyData)
return;
let Multiplier = anomalyData.multiplier;
if (times !== 1 && anomalyData.duration && anomalyData.interval) {
if (!times && anomalyData.duration && anomalyData.interval) {
const AnomalyDuration = this.get_AnomalyDuration(skill, usefulBuffs, anomalyData.duration);
times ||= Math.floor((AnomalyDuration * 10) / (anomalyData.interval * 10));
Multiplier = anomalyData.multiplier * times;
times = Math.floor((AnomalyDuration * 10) / (anomalyData.interval * 10));
}
const Multiplier = anomalyData.multiplier * (times || 1);
logger.debug(`倍率:${Multiplier}`);
return Multiplier;
}
@ -432,9 +436,9 @@ export class Calculator {
if (!Array.isArray(value) || !buff)
return 0;
switch (buff.source) {
case 'Weapon': return value[this.avatar.weapon.star - 1] || 0;
case 'Talent':
case 'Addition': return value[this.get_SkillLevel('T') - 1] || 0;
case '音擎': return value[this.avatar.weapon.star - 1] || 0;
case '核心被动':
case '额外能力': return value[this.get_SkillLevel('T') - 1] || 0;
}
}
default: return 0;
@ -448,18 +452,12 @@ export class Calculator {
type
}, this).reduce((previousValue, buff) => {
const { value } = buff;
let add = 0;
if (isRatio && typeof value === 'number' && Math.abs(value) < 1) {
add = value * initial;
}
else {
add = this.calc_value(value, buff);
if (Math.abs(add) < 1 && isRatio && (typeof value === 'string' || Array.isArray(value)))
add *= initial;
}
if (!this.usefulBuffs.find(b => b.name === buff.name && b.type === buff.type && add === buff.value))
this.usefulBuffs.push({ ...buff, value: add });
logger.debug(`\tBuff${buff.name}${buff.range || '全类型'}增加${add}${buff.element || ''}${type}`);
let add = this.calc_value(value, buff);
if (isRatio && Math.abs(add) < 1 && (typeof value === 'number' || typeof value === 'string' || Array.isArray(value)))
add *= initial;
if (!this.usefulBuffResults.has(buff))
this.usefulBuffResults.set(buff, { ...buff, value: add });
logger.debug(`\tBuff${buff.name}${(buff.include ? (buff.range ? [buff.range, buff.include] : buff.include) : buff.range) || '全类型'}增加${add}${buff.element || ''}${type}`);
return previousValue + add;
}, initial);
}

View file

@ -175,7 +175,8 @@ export class Calculator {
readonly buffM: BuffManager
readonly avatar: ZZZAvatarInfo
readonly skills: skill[] = []
private usefulBuffs: buff[] = []
/** 对当前所计算的技能有用的buff、计算后的buff */
private readonly usefulBuffResults: Map<buff, buff> = new Map()
private cache: { [type: string]: damage } = Object.create(null)
private props: Exclude<damage['props'], undefined> = {}
/** 当前正在计算的技能 */
@ -325,8 +326,8 @@ export class Calculator {
critDMG: BasicArea * ! * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea,
expectDMG: BasicArea * CriticalArea * BoostArea * VulnerabilityArea * ResistanceArea * DefenceArea
}
const damage: damage = { skill, usefulBuffs: _.sortBy(this.usefulBuffs, ['type', 'value']).reverse(), props, areas, result }
this.usefulBuffs = []
const damage: damage = { skill, usefulBuffs: _.sortBy(Array.from(this.usefulBuffResults.values()), ['type', 'value']).reverse(), props, areas, result }
this.usefulBuffResults.clear()
if (skill.after) {
damage.add = (d) => {
if (typeof d === 'string') d = this.calc_skill(d)
@ -387,7 +388,13 @@ export class Calculator {
const base: { [type: string]: number } = {}
types.forEach(t => base[t] = t.includes('百分比') ? this.avatar.base_properties[prop.nameZHToNameEN(t.replace('百分比', '')) as keyof ZZZAvatarInfo['base_properties']] * subBaseValueData[t][0] : subBaseValueData[t][0])
logger.debug('词条变化值:', base)
const buffs = types.map(t => ({
const buffs: {
name: subStatKeys
shortName: string
type: buff['type']
value: number
valueBase: typeof subBaseValueData[subStatKeys][1]
}[] = types.map(t => ({
name: t,
shortName: prop.nameToShortName3(t),
type: t.replace('百分比', '') as buff['type'],
@ -432,14 +439,25 @@ export class Calculator {
const base: { [type: string]: number } = {}
types.forEach(t => base[t] = (t.includes('百分比') || ['异常掌控', '冲击力', '能量自动回复'].includes(t)) ? this.avatar.base_properties[prop.nameZHToNameEN(t.replace('百分比', '')) as keyof ZZZAvatarInfo['base_properties']] * mainBaseValueData[t][0] : mainBaseValueData[t][0])
logger.debug(logger.red('词条变化值:'), base)
const buffs = types.map(t => ({
name: t,
shortName: prop.nameToShortName3(t),
type: (t.includes('属性伤害加成') ? '增伤' : t.replace('百分比', '')) as buff['type'],
value: base[t],
element: t.includes('属性伤害加成') ? prop.nameZHToNameEN(t).replace('DMGBonus', '') : undefined,
valueBase: mainBaseValueData[t][1]
}))
const buffs: {
name: mainStatKeys
shortName: string
type: buff['type']
value: number
element?: element
valueBase: typeof mainBaseValueData[mainStatKeys][1]
}[] = types.map(t => {
const data: typeof buffs[number] = {
name: t,
shortName: prop.nameToShortName3(t),
type: (t.includes('属性伤害加成') ? '增伤' : t.replace('百分比', '')) as buff['type'],
value: base[t],
element: (t.includes('属性伤害加成') ? prop.nameZHToNameEN(t).replace('DMGBonus', '') : '') as element,
valueBase: mainBaseValueData[t][1]
}
if (!data.element) delete data.element
return data
})
buffs.push({
// @ts-expect-error
name: '空白对照',
@ -465,21 +483,25 @@ export class Calculator {
})
}
/* 计算已注册技能差异 */
/**
*
* - buff形式两两组合进行差异计算
* @param buffs buffs
* @returns `buffs.length * buffs.length`2
*/
calc_differences<B extends Partial<buff>>(
buffs: B[],
skill: skill['type']
): { add: B, del: B, damage: damage, difference: number }[][]
/* 计算技能差异 */
/**
*
* @param buffs buffs
* @returns `buffs.length * buffs.length`2
*/
calc_differences<B extends Partial<buff>>(
buffs: B[],
skill?: skill
): { add: B, del: B, damage: damage, difference: number }[][]
/**
* buff形式两两组合进行差异计算
* @param buffs buffs
* @returns `buffs.length维`
*/
calc_differences<B extends buff>(
buffs: B[],
skill?: skill['type'] | skill
@ -574,9 +596,9 @@ export class Calculator {
return Multiplier
}
/** 获取角色自身**出伤**异常的异常数据 */
/** 获取角色自身`出伤异常`的异常数据 */
get_AnomalyData(): typeof AnomalyData[number]
/** 获取角色自身**指定**异常的异常数据 */
/** 获取角色自身`指定异常`的异常数据 */
get_AnomalyData(anomaly: anomaly): typeof AnomalyData[number]
get_AnomalyData(anomaly?: anomaly) {
if (!anomaly) {
@ -598,12 +620,12 @@ export class Calculator {
get_AnomalyMultiplier(skill: skill, usefulBuffs: buff[], times = 0) {
const anomalyData = this.get_AnomalyData(skill?.type.slice(0, 2) as anomaly)
if (!anomalyData) return
let Multiplier = anomalyData.multiplier
if (times !== 1 && anomalyData.duration && anomalyData.interval) {
// 未指定触发次数时,自动计算最大触发次数
if (!times && anomalyData.duration && anomalyData.interval) {
const AnomalyDuration = this.get_AnomalyDuration(skill, usefulBuffs, anomalyData.duration)
times ||= Math.floor((AnomalyDuration * 10) / (anomalyData.interval * 10))
Multiplier = anomalyData.multiplier * times
times = Math.floor((AnomalyDuration * 10) / (anomalyData.interval * 10))
}
const Multiplier = anomalyData.multiplier * (times || 1)
logger.debug(`倍率:${Multiplier}`)
return Multiplier
}
@ -637,9 +659,9 @@ export class Calculator {
case 'object': {
if (!Array.isArray(value) || !buff) return 0
switch (buff.source) {
case 'Weapon': return value[this.avatar.weapon.star - 1] || 0
case 'Talent':
case 'Addition': return value[this.get_SkillLevel('T') - 1] || 0
case '音擎': return value[this.avatar.weapon.star - 1] || 0
case '核心被动':
case '额外能力': return value[this.get_SkillLevel('T') - 1] || 0
}
}
default: return 0
@ -648,7 +670,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 {
return this.props[type] ??= this.buffM._filter(usefulBuffs, {
@ -658,17 +680,13 @@ export class Calculator {
type
}, this).reduce((previousValue, buff) => {
const { value } = buff
let add = 0
if (isRatio && typeof value === 'number' && Math.abs(value) < 1) { // 绝对值小于1时认为是百分比
add = value * initial
} else {
add = this.calc_value(value, buff)
if (Math.abs(add) < 1 && isRatio && (typeof value === 'string' || Array.isArray(value)))
add *= initial
}
if (!this.usefulBuffs.find(b => b.name === buff.name && b.type === buff.type && add === buff.value))
this.usefulBuffs.push({ ...buff, value: add })
logger.debug(`\tBuff${buff.name}${buff.range || '全类型'}增加${add}${buff.element || ''}${type}`)
let add = this.calc_value(value, buff)
// 启用isRatio时若计算值绝对值小于1按照百分比提高处理
if (isRatio && Math.abs(add) < 1 && (typeof value === 'number' || typeof value === 'string' || Array.isArray(value)))
add *= initial
if (!this.usefulBuffResults.has(buff))
this.usefulBuffResults.set(buff, { ...buff, value: add })
logger.debug(`\tBuff${buff.name}${(buff.include ? (buff.range ? [buff.range, buff.include] : buff.include) : buff.range) || '全类型'}增加${add}${buff.element || ''}${type}`)
return previousValue + add
}, initial)
}

View file

@ -24,7 +24,7 @@
> 将崽底层日志模式切换为**debug**模式,可在控制台查看评分计算详细过程;且会自动监听现有评分计算文件实时热更新。可按需开启
在函数体中,可根据玩家角色数据**动态选用**不同的权重方案
在函数体中,可根据玩家角色数据**动态选用**不同的权重方案。参考[薇薇安评分规则](./character/薇薇安/score.js)
- 函数参数:[ZZZAvatarInfo](../avatar.js#L173)(角色数据)
@ -72,7 +72,7 @@
### 认识buff
每个buff由各项[buff参数](./BuffManager.ts#L48)组成,重要参数:
每个buff由各项[buff参数](./BuffManager.ts#L40)组成,重要参数:
```js
{
@ -83,20 +83,20 @@
/** Buff增益的类型 */
type: buffType
/**
* Buff增益数值可为数值、数组、函数、字符串
* Buff增益数值可为数值、字符串、数组、函数
* @number
* - 一般情况下此值即为提高值
* - 当buff增益类型为攻击力/冲击力/异常精通/异常掌控/防御力/生命值时,若此值<1则将此值理解为初始属性的百分比提高
* @array
* 根据buff.source自动选择对应等级/星级的值同上支持百分比提高支持的source
* - Weapon武器星级进阶
* - Talent/Addition天赋核心技等级
* @function
* 函数返回值则为提高值
* @string
* 角色自身的buff提高值可能随技能/天赋等级提高而提高此时可以于data.json的"buff"中添加对应的倍率信息同上支持百分比提高此时value即为键名其首字母必须为对应技能的基类参考技能类型命名标准
* @array
* 根据buff.source自动选择对应等级/星级的值同上支持百分比提高支持的source
* - 音擎:音擎星级(进阶)
* - 核心被动、额外能力:核心技等级
* @function
* 函数返回值即为提高值
*/
value: number | number[] | Function | string
value: number | string | number[] | Function
/**
* Buff增益技能类型生效范围参考技能类型命名标准
* - 当技能参数不存在redirect时range作用范围向后覆盖
@ -112,9 +112,9 @@
- **name**Buff名称。可重复
- **source**Buff来源。用于管理buff、简化参数、判断生效条件等。查看[buff来源](./BuffManager.ts#L32)
- **source**Buff来源。用于管理buff、简化参数、判断生效条件等。查看[buff来源](./BuffManager.ts#L24)
- **type**Buff增益的类型。查看[增益类型](./BuffManager.ts#L34)
- **type**Buff增益的类型。查看[增益类型](./BuffManager.ts#L26)
- **value**Buff增益值。具体解释如上述
@ -122,7 +122,7 @@
- **element**Buff增益属性类型可为字符串或字符串数组。该参数用于鉴别不同buff的生效属性比如只对冰属性伤害生效。查看[属性类型](./BuffManager.ts#L5)
- buff存在更多的参数用于处理各种情况详见[buff参数](./BuffManager.ts#L48)
- buff存在更多的参数用于处理各种情况详见[buff参数](./BuffManager.ts#L40)
### 注册buff

View file

@ -130,7 +130,7 @@ export function weapon_buff(weapon, buffM) {
const m = calcFnc.weapon[name];
if (!m)
return;
buffM.default({ name, source: 'Weapon' });
buffM.default({ name, source: '音擎' });
if (m.buffs)
buffM.new(m.buffs);
if (m.calc)
@ -138,7 +138,7 @@ export function weapon_buff(weapon, buffM) {
buffM.default({});
}
export function set_buff(equips, buffM) {
buffM.default({ name: '', source: 'Set' });
buffM.default({ name: '', source: '套装' });
const setCount = {};
for (const equip of equips) {
if (equip.equipment_type == 5) {
@ -148,7 +148,6 @@ export function set_buff(equips, buffM) {
name: '驱动盘5号位',
type: '增伤',
value: Number(equip.main_properties[0].base.replace('%', '')) / 100,
isForever: true,
element: elementEnum[index]
});
}

View file

@ -160,7 +160,7 @@ export function weapon_buff(weapon: ZZZAvatarInfo['weapon'], buffM: BuffManager)
logger.debug('武器:' + name)
const m = calcFnc.weapon[name]
if (!m) return
buffM.default({ name, source: 'Weapon' })
buffM.default({ name, source: '音擎' })
if (m.buffs) buffM.new(m.buffs)
if (m.calc) m.calc(buffM, weapon.star)
buffM.default({})
@ -168,7 +168,7 @@ export function weapon_buff(weapon: ZZZAvatarInfo['weapon'], buffM: BuffManager)
/** 套装加成 */
export function set_buff(equips: ZZZAvatarInfo['equip'], buffM: BuffManager) {
buffM.default({ name: '', source: 'Set' })
buffM.default({ name: '', source: '套装' })
const setCount: { [name: string]: number } = {}
for (const equip of equips) {
if (equip.equipment_type == 5) {
@ -180,7 +180,6 @@ export function set_buff(equips: ZZZAvatarInfo['equip'], buffM: BuffManager) {
name: '驱动盘5号位',
type: '增伤',
value: Number(equip.main_properties[0].base.replace('%', '')) / 100,
isForever: true,
element: elementEnum[index]
})
}

View file

@ -8,8 +8,7 @@ export const buffs = [
{
name: '2影',
type: '攻击力',
value: 0.15,
isForever: true
value: 0.15
},
{
name: '4影',

View file

@ -14,14 +14,12 @@ export const buffs = [
name: '6影',
type: '暴击率',
value: 1,
isForever: true,
range: ['EQQ', 'LT']
},
{
name: '6影',
type: '增伤',
value: 1,
isForever: true,
range: ['EQQ', 'LT']
},
{

View file

@ -15,7 +15,6 @@ export const buffs = [
name: '核心被动:破晓',
type: '暴击率',
value: 'T1',
isForever: true,
range: ['CCQ']
},
{

View file

@ -17,27 +17,23 @@
// buffM.new({
// name: '2影',
// type: '增伤',
// isForever: true,
// value: 0.30,
// range: ['AP', 'CF']
// })
// buffM.new({
// name: '2影',
// type: '暴击率',
// isForever: true,
// value: 0.15
// })
// buffM.new({
// name: '4影',
// type: '增伤',
// isForever: true,
// value: 0.30,
// range: ['TP']
// })
// buffM.new({
// name: '6影',
// type: '增伤',
// isForever: true,
// value: 0.30,
// range: ['AX']
// })
@ -45,14 +41,12 @@
// buffM.new({
// name: '额外能力:同沐霜雪',
// type: '增伤',
// isForever: true,
// value: 0.6,
// range: ['AX']
// })
// buffM.new({
// name: '额外能力:同沐霜雪',
// type: '无视抗性',
// isForever: true,
// value: 0.3,
// range: ['AX']
// })
@ -102,41 +96,35 @@ export const buffs = [
{
name: '2影',
type: '暴击率',
isForever: true,
value: 0.15
},
{
name: '2影',
type: '增伤',
isForever: true,
value: 0.30,
range: ['AP', 'CF']
},
{
name: '4影',
type: '增伤',
isForever: true,
value: 0.30,
range: ['TP']
},
{
name: '6影',
type: '增伤',
isForever: true,
value: 0.30,
range: ['AX']
},
{
name: '额外能力:同沐霜雪',
type: '增伤',
isForever: true,
value: 0.6,
range: ['AX']
},
{
name: '额外能力:同沐霜雪',
type: '无视抗性',
isForever: true,
value: 0.3,
range: ['AX']
},

View file

@ -9,7 +9,6 @@ export const buffs = [
name: '2影',
type: '倍率',
value: 0.05,
isForever: true,
range: ['强化E极性紊乱']
},
{

View file

@ -28,7 +28,6 @@ export const buffs = [
name: '核心被动:燃油特调',
type: '增伤',
value: ({ calc }) => Math.min(30, calc.get_AnomalyProficiency() / 10) * 0.01,
isForever: true,
range: ['TY', 'Y6Y']
},
{

View file

@ -4,7 +4,6 @@ export const buffs = [
name: '2影',
type: '增伤',
value: 0.25,
isForever: true,
range: ['CF']
},
{

View file

@ -17,6 +17,7 @@ export const buffs = [
/** @type {import('../../Calculator.ts').Calculator['skills']} */
export const skills = [
{ name: '强击', isMain: true, type: '强击' },
{ name: '紊乱', type: '紊乱' },
{ name: '普攻:准备发车四段', type: 'AP4' },
{ name: '闪避反击:动力漂移', type: 'CF' },
{ name: '强化特殊技:引擎转(每圈)', type: 'EQZ' },

View file

@ -22,7 +22,8 @@ export const buffs = [
{
name: '4影',
type: '异常增伤',
value: 0.18
value: 0.18,
exclude: ['紊乱']
},
{
name: '6影',

View file

@ -10,7 +10,6 @@ export const buffs = [
name: '1影',
type: '增伤',
value: 0.3,
isForever: true,
range: ['AQ5Q']
},
{

View file

@ -29,8 +29,7 @@ export const buffs = [
name: '6影',
type: '增伤',
value: 0.4,
element: 'Ether',
isForever: true
element: 'Ether'
},
{
name: '额外能力:预言之泪',

View file

@ -0,0 +1,5 @@
/** @type {import('../../avatar.ts')['scoreFnc'][string]} */
export default function (avatar) {
if (avatar.rank >= 4)
return ['高影画', { "暴击伤害": 0.25 }]
}

View file

@ -4,7 +4,6 @@ export const buffs = [
name: '6影',
type: '暴击伤害',
value: 0.6,
isForever: true,
range: ['Y6']
},
{

View file

@ -3,8 +3,7 @@ export const buffs = [
{
name: '2影',
type: '暴击率',
value: 0.12,
isForever: true
value: 0.12
},
{
name: '4影',

View file

@ -14,8 +14,7 @@ export const buffs = [
name: '6影',
type: '暴击伤害',
value: 1,
range: ['AQ'],
isForever: true
range: ['AQ']
},
{
name: '6影',
@ -25,7 +24,6 @@ export const buffs = [
{
name: '额外能力:阳关三叠',
type: '攻击力',
isForever: true,
value: ({ calc }) => Math.max(0, Math.min((calc.get_Impact() - 120) * 6, 600))
},
{
@ -36,7 +34,7 @@ export const buffs = [
},
{
name: '闪络',
source: 'Skill',
source: '技能',
type: '增伤',
value: 0.01 * 25,
range: ['AQ']

View file

@ -4,8 +4,7 @@ export const buffs = [
type: '增伤',
value: 0.15,
check: 2,
range: ['CC', '追加攻击'],
isForever: true
range: ['CC', '追加攻击']
},
{
type: '攻击力',

View file

@ -12,7 +12,6 @@
// name: name + '4',
// type: '暴击伤害',
// value: 0.3,
// isForever: true,
// check: ({ buffM, calc }) => calc.get_AnomalyMastery() >= 115
// })
// buffM.new({
@ -31,7 +30,6 @@ export const buffs = [
name: '折枝剑歌4',
type: '暴击伤害',
value: 0.3,
isForever: true,
check: ({ buffM, calc }) => buffM.setCount.折枝剑歌 >= 4 && calc.get_AnomalyMastery() >= 115
},
{

View file

@ -3,14 +3,12 @@ export const buffs = [
{
type: '增伤',
value: 0.1,
isForever: true,
element: 'Ice',
check: 2
},
{
type: '增伤',
value: 0.2,
isForever: true,
range: ['A', 'CC'],
check: 4
},

View file

@ -3,7 +3,6 @@ export const buffs = [
{
type: '增伤',
value: 0.2,
isForever: true,
range: ['RZ'],
check: 4
},

View file

@ -3,7 +3,6 @@ export const buffs = [
{
type: '增伤',
value: 0.15,
isForever: true,
element: ['Electric', 'Fire'],
check: 4
},

View file

@ -3,14 +3,12 @@ export const buffs = [
{
type: '增伤',
value: 0.1,
isForever: true,
element: 'Ether',
check: 2
},
{
type: '暴击伤害',
value: 0.2,
isForever: true,
check: 4
},
{

View file

@ -4,7 +4,6 @@ export const buffs = [
type: '增伤',
value: 0.1,
element: 'Fire',
isForever: true,
check: 2
},
{

View file

@ -4,7 +4,6 @@ export const buffs = [
type: '增伤',
value: 0.1,
check: 2,
isForever: true,
element: 'Physical'
},
{

View file

@ -4,7 +4,6 @@ export const buffs = [
type: '增伤',
value: 0.1,
check: 2,
isForever: true,
element: 'Electric'
},
{

View file

@ -3,7 +3,6 @@ export const buffs = [
{
type: '增伤',
value: [0.12, 0.14, 0.16, 0.18, 0.2],
isForever: true,
range: ['A', 'CC', 'CF']
}
]

View file

@ -2,8 +2,7 @@
export const buffs = [
{
type: '生命值',
value: [0.08, 0.092, 0.104, 0.116, 0.128],
isForever: true
value: [0.08, 0.092, 0.104, 0.116, 0.128]
},
{
type: '攻击力',

View file

@ -2,7 +2,6 @@
export const buffs = [
{
type: '攻击力',
value: [0.075, 0.086, 0.097, 0.108, 0.12],
isForever: true
value: [0.075, 0.086, 0.097, 0.108, 0.12]
}
]

View file

@ -3,8 +3,7 @@ export const buffs = [
{
type: '增伤',
value: [0.15, 0.175, 0.2, 0.22, 0.24],
element: 'Ice',
isForever: true
element: 'Ice'
},
{
type: '攻击力',

View file

@ -2,8 +2,7 @@
export const buffs = [
{
type: '攻击力',
value: [0.12, 0.15, 0.18, 0.21, 0.24],
isForever: true
value: [0.12, 0.15, 0.18, 0.21, 0.24]
},
{
type: '异常精通',

View file

@ -3,7 +3,6 @@ export const buffs = [
{
type: '增伤',
value: [0.15, 0.175, 0.2, 0.22, 0.24],
element: 'Electric',
isForever: true
element: 'Electric'
}
]

View file

@ -2,8 +2,7 @@
export const buffs = [
{
type: '暴击伤害',
value: [0.5, 0.575, 0.65, 0.725, 0.8],
isForever: true
value: [0.5, 0.575, 0.65, 0.725, 0.8]
},
{
type: '无视抗性',

View file

@ -2,8 +2,7 @@
export const buffs = [
{
type: '生命值',
value: [0.08, 0.09, 0.1, 0.11, 0.125],
isForever: true
value: [0.08, 0.09, 0.1, 0.11, 0.125]
},
{
type: '冲击力',

View file

@ -2,14 +2,12 @@
export const buffs = [
{
type: '暴击率',
value: [0.1, 0.115, 0.13, 0.145, 0.16],
isForever: true
value: [0.1, 0.115, 0.13, 0.145, 0.16]
},
{
type: '增伤',
value: [0.4, 0.46, 0.52, 0.58, 0.64],
element: 'Electric',
isForever: true,
range: ['CC']
},
{

View file

@ -3,8 +3,7 @@ export const buffs = [
{
type: '增伤',
value: [0.25, 0.315, 0.38, 0.445, 0.5],
element: 'Ice',
isForever: true
element: 'Ice'
},
{
type: '暴击率',

View file

@ -2,8 +2,7 @@
export const buffs = [
{
type: '暴击伤害',
value: [0.3, 0.345, 0.39, 0.435, 0.48],
isForever: true
value: [0.3, 0.345, 0.39, 0.435, 0.48]
},
{
type: '暴击伤害',

View file

@ -2,8 +2,7 @@
export const buffs = [
{
type: '攻击力',
value: [0.06, 0.069, 0.078, 0.087, 0.096],
isForever: true
value: [0.06, 0.069, 0.078, 0.087, 0.096]
},
{
type: '增伤',

View file

@ -3,8 +3,7 @@ export const buffs = [
{
type: '增伤',
value: [0.2, 0.25, 0.3, 0.35, 0.4],
element: 'Physical',
isForever: true
element: 'Physical'
},
{
type: '增伤',

View file

@ -2,8 +2,7 @@
export const buffs = [
{
type: '暴击率',
value: [0.15, 0.188, 0.226, 0.264, 0.3],
isForever: true
value: [0.15, 0.188, 0.226, 0.264, 0.3]
},
{
type: '增伤',

View file

@ -7,8 +7,7 @@
// export function calc(buffM, star) {
// buffM.new({
// type: '暴击伤害',
// value: [0.5, 0.57, 0.65, 0.72, 0.8][star - 1],
// isForever: true
// value: [0.5, 0.57, 0.65, 0.72, 0.8][star - 1]
// })
// buffM.new({
// type: '增伤',
@ -23,8 +22,7 @@
export const buffs = [
{
type: '暴击伤害',
value: [0.5, 0.57, 0.65, 0.72, 0.8],
isForever: true
value: [0.5, 0.57, 0.65, 0.72, 0.8]
},
{
type: '增伤',

View file

@ -501,7 +501,7 @@
grid-template-columns: 1fr 1fr 1fr;
}
.damage .buff-list .buff-tr {
grid-template-columns: 0.7fr 5fr 3fr 2fr;
grid-template-columns: 0.7fr 5fr 1.8fr 2.5fr 1.8fr;
}
.damage .buff-list .buff-td:nth-child(2) {
background: rgba(0, 0, 0, 0.2);

View file

@ -208,6 +208,7 @@
<div class="tr buff-tr titlebar no-zzz-font">
<div class="td buff-td">%</div>
<div class="td buff-td">名称</div>
<div class="td buff-td">来源</div>
<div class="td buff-td">增益类型</div>
<div class="td buff-td">增益值</div>
</div>
@ -215,6 +216,7 @@
<div class="tr buff-tr titlebar">
<div class="td buff-td">{{index+1}}</div>
<div class="td buff-td no-zzz-font">{{buff.name}}</div>
<div class="td buff-td no-zzz-font">{{buff.source}}</div>
<div class="td buff-td no-zzz-font">{{buff.type}}</div>
<div class="td buff-td">{{buff.value % 1 == 0 ? buff.value < 2 ? buff.value.toFixed(2) : buff.value : buff.value.toFixed(2)}}</div>
</div>

View file

@ -499,7 +499,7 @@
/* buff统计 */
.buff-list {
.buff-tr {
grid-template-columns: 0.7fr 5fr 3fr 2fr;
grid-template-columns: 0.7fr 5fr 1.8fr 2.5fr 1.8fr;
}
.buff-td {