refactor: 统一全量buff数值为百分比口径

本次变更对齐了所有buff和技能的数值结算规则:
1.  新增项目规范明确buff数值统一使用百分比/百分点结算
2.  修改技能描述配置、属性计算逻辑,将固定数值加成改为百分比计算
3.  调整buff配置的修改类型为PercentAdd,同步更新buff说明文本
4.  重构属性计算逻辑,区分百分比加成和固定加成的处理方式
5.  更新战力计算逻辑适配新的百分比口径规则
This commit is contained in:
panFD
2026-08-16 19:21:23 +08:00
parent 284d124486
commit a5ca43a62c
7 changed files with 55 additions and 46 deletions

View File

@@ -88,8 +88,8 @@ export const BuffList: Record<number, BuffConfig> = {
7001: {
id: 7001, name: "攻击强化", icon: "Stat_Attack_03",
category: BuffCategory.Buff, duration: 10, max_stack: 0,
modifiers: [{ attr: Attrs.ap, op: ModOp.Flat, value: 5 }],
info: "攻击力 +5,持续 10 秒",
modifiers: [{ attr: Attrs.ap, op: ModOp.PercentAdd, value: 5 }],
info: "攻击力提升 5%,持续 10 秒",
},
// 易伤(灼热火球附加;受到伤害时附加固定值,可被易伤抗性百分比减免)
// 注modifiers.attr 用 hp 仅为占位以通过 aggregateTimedMods 结构校验,实际易伤值由 HeroAtkSystem 按 VULNERABLE_BUFF_ID 直接汇总
@@ -124,8 +124,8 @@ export const BuffList: Record<number, BuffConfig> = {
7006: {
id: 7006, name: "减攻", icon: "Stat_Attack_01",
category: BuffCategory.Debuff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.ap, op: ModOp.Flat, value: -10 }],
info: "攻击力降低 10,持续 5 秒",
modifiers: [{ attr: Attrs.ap, op: ModOp.PercentAdd, value: -10 }],
info: "攻击力降低 10%,持续 5 秒",
},
// 出血(每层使目标被暴击率 +1%,微量伤害 DoT暴击率加成由 HeroAtkSystem 按 BLEED_BUFF_ID 层数结算)
7007: {
@@ -134,12 +134,12 @@ export const BuffList: Record<number, BuffConfig> = {
tick: { interval: 0.5, damage_or_heal: -1, scale_by_ap_pct: 0 },
info: "微量出血,每层使自身被暴击率提升 1%,可叠加,持续 5 秒",
},
// 占卜师战前攻击强化(基础档:+30/5s高阶通过 buff_value/buff_duration 覆写成长)
// 占卜师战前攻击强化(基础档:+30%/5s高阶通过 buff_value/buff_duration 覆写成长)
7111: {
id: 7111, name: "战前强攻", icon: "Stat_Attack_03",
category: BuffCategory.Buff, duration: 5, max_stack: 0,
modifiers: [{ attr: Attrs.ap, op: ModOp.Flat, value: 30 }],
info: "攻击力 +30持续 5 秒",
modifiers: [{ attr: Attrs.ap, op: ModOp.PercentAdd, value: 30 }],
info: "攻击力提升 30%,持续 5 秒",
},
// ==================== 玩家计时性强化(药水/技能用,默认 5s ====================
@@ -161,77 +161,77 @@ export const BuffList: Record<number, BuffConfig> = {
7012: {
id: 7012, name: "暴击爆发", icon: "Stat_CriticalChance_02",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.critical, op: ModOp.Flat, value: 30 }],
modifiers: [{ attr: Attrs.critical, op: ModOp.PercentAdd, value: 30 }],
info: "暴击率提升 30%,持续 5 秒",
},
// 击退距离强化(限时)
7013: {
id: 7013, name: "击退爆发", icon: "Stat_Stun_01",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.knockback_chance, op: ModOp.Flat, value: 30 }],
info: "击退距离提升 30持续 5 秒",
modifiers: [{ attr: Attrs.knockback_chance, op: ModOp.PercentAdd, value: 30 }],
info: "击退距离提升 30%,持续 5 秒",
},
// 穿透强化(限时)
7014: {
id: 7014, name: "穿透爆发", icon: "Stat_Tripleshot",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.puncture_chance, op: ModOp.Flat, value: 30 }],
modifiers: [{ attr: Attrs.puncture_chance, op: ModOp.PercentAdd, value: 30 }],
info: "穿透概率提升 30%,持续 5 秒",
},
// 攻速强化(限时,走 getEffectiveSkillCd 计时修饰)
7015: {
id: 7015, name: "攻速爆发", icon: "Stat_AttackSpeed_02",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.speed, op: ModOp.Flat, value: 40 }],
modifiers: [{ attr: Attrs.speed, op: ModOp.PercentAdd, value: 40 }],
info: "攻击速度提升 40%,持续 5 秒",
},
// 风怒强化(限时,按概率百分点)
7016: {
id: 7016, name: "风怒爆发", icon: "Stat_CriticalComboChance",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.wfuny, op: ModOp.Flat, value: 20 }],
modifiers: [{ attr: Attrs.wfuny, op: ModOp.PercentAdd, value: 20 }],
info: "风怒概率提升 20%,持续 5 秒",
},
// 击晕概率强化(限时)
7017: {
id: 7017, name: "击晕爆发", icon: "Stat_Stun_01",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.stun_chance, op: ModOp.Flat, value: 30 }],
modifiers: [{ attr: Attrs.stun_chance, op: ModOp.PercentAdd, value: 30 }],
info: "击晕概率提升 30%,持续 5 秒",
},
// 击晕抗性强化(限时)
7018: {
id: 7018, name: "击晕抗性", icon: "Stat_Armor_01",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.stun_res, op: ModOp.Flat, value: 50 }],
modifiers: [{ attr: Attrs.stun_res, op: ModOp.PercentAdd, value: 50 }],
info: "击晕抗性提升 50%,持续 5 秒",
},
// 冰冻抗性强化(限时)
7019: {
id: 7019, name: "冰冻抗性", icon: "Stat_Freeze",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.freeze_res, op: ModOp.Flat, value: 50 }],
modifiers: [{ attr: Attrs.freeze_res, op: ModOp.PercentAdd, value: 50 }],
info: "冰冻抗性提升 50%,持续 5 秒",
},
// 暴伤强化(限时)
7020: {
id: 7020, name: "暴伤爆发", icon: "Stat_Critical_01",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.critical_damage, op: ModOp.Flat, value: 30 }],
modifiers: [{ attr: Attrs.critical_damage, op: ModOp.PercentAdd, value: 30 }],
info: "暴击伤害提升 30%,持续 5 秒",
},
// 冰冻概率强化(限时)
7021: {
id: 7021, name: "冰冻概率爆发", icon: "Stat_Freeze",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.freeze_chance, op: ModOp.Flat, value: 5 }],
modifiers: [{ attr: Attrs.freeze_chance, op: ModOp.PercentAdd, value: 5 }],
info: "冰冻概率提升 5%,持续 5 秒",
},
// 穿透伤害强化(限时)
7022: {
id: 7022, name: "穿透伤害爆发", icon: "Stat_Tripleshot",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.puncture_dmg_bonus, op: ModOp.Flat, value: 30 }],
modifiers: [{ attr: Attrs.puncture_dmg_bonus, op: ModOp.PercentAdd, value: 30 }],
info: "穿透后伤害提升 30%,持续 5 秒",
},
};

View File

@@ -57,16 +57,16 @@ export const SkillDescSet: Record<number, SkillDescConfig> = {
verb: "", unit: "", permField: "ap",
templPerm: "{target}回复攻击力{value}%生命",
},
// 6401 攻击强化:永久 ap=攻击;计时 buff_value=攻击
// 6401 攻击强化:永久 ap=攻击%;计时 buff_value=攻击%
6401: {
verb: "攻击力", unit: "", permField: "ap", timedField: "buff_value",
templPerm: "{target}{verb}永久+{value}",
templTimed: "{target}{verb}+{value}, 持续{dur}秒",
verb: "攻击力", unit: "%", permField: "ap", timedField: "buff_value",
templPerm: "{target}{verb}永久+{value}{unit}",
templTimed: "{target}{verb}+{value}{unit}, 持续{dur}秒",
},
// 6402 生命强化ap = 最大生命
// 6402 生命强化ap = 最大生命%
6402: {
verb: "最大生命", unit: "", permField: "ap",
templPerm: "{target}{verb}永久+{value}",
verb: "最大生命", unit: "%", permField: "ap",
templPerm: "{target}{verb}永久+{value}{unit}",
},
// 6403 暴击强化:永久 ap=暴击%;计时 buff_value=暴击%
6403: {

View File

@@ -357,12 +357,12 @@ export const SkillSet: Record<number, SkillConfig> = {
6401: {
uuid: 6401, name: "攻击强化", sp_name: "buff_wind", icon: "Stat_Attack_03", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 5, hit_count: 1, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.ap, info: "全体友方攻击力提升5, 持续1次",
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.ap, info: "全体友方攻击力提升5%, 持续1次",
},
6402: {
uuid: 6402, name: "生命强化", sp_name: "buff_wind", icon: "Stat_Hp_02", TGroup: TGroup.Team, readyAnm: "up_hp", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 20, hit_count: 1, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.hp_max, info: "全体友方最大生命值提升20, 持续1次",
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.hp_max, info: "全体友方最大生命值提升20%, 持续1次",
},
6403: {
uuid: 6403, name: "暴击强化", sp_name: "buff_wind", icon: "Stat_CriticalChance_02", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk",
@@ -407,7 +407,7 @@ export const SkillSet: Record<number, SkillConfig> = {
6411: {
uuid: 6411, name: "穿透伤害强化", sp_name: "buff_wind", icon: "Stat_Tripleshot", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 10, hit_count: 1, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.puncture_dmg_bonus, info: "全体友方穿透后伤害提升10%(百分点), 永久生效",
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.puncture_dmg_bonus, info: "全体友方穿透后伤害提升10%, 永久生效",
},
6501: {
uuid: 6501, name: "复活", sp_name: "buff_wind", icon: "Stat_HolyDamage", TGroup: TGroup.Self, readyAnm: "up_ap", endAnm: "", act: "atk",
@@ -416,7 +416,7 @@ export const SkillSet: Record<number, SkillConfig> = {
},
// ==================== 计时性强化技能(药水底座,统一 5s走 timed_buff_id ====================
// 注ap 字段在此类技能中无意义,修饰数值由 BuffList 配置hit_count=99 确保覆盖全队。
// 注ap 字段在此类技能中无意义,修饰数值由 BuffList 配置PercentAdd 百分比口径)hit_count=99 确保覆盖全队。
6502: {
uuid: 6502, name: "计时回血", sp_name: "buff_wind", icon: "Stat_PotionBoost", TGroup: TGroup.Team, readyAnm: "up_green", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 3, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
@@ -435,7 +435,7 @@ export const SkillSet: Record<number, SkillConfig> = {
6505: {
uuid: 6505, name: "击退爆发", sp_name: "buff_wind", icon: "Stat_Stun_01", TGroup: TGroup.Team, readyAnm: "up_blue", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 0, hit_count: 3, hitcd: 0.2, speed: 720, with: 0, ready: 0.2, EAnm: 0, DAnm: "", IType: IType.support,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.knockback_chance, timed_buff_id: 7013, info: "全体友方击退距离提升30, 持续5秒",
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.knockback_chance, timed_buff_id: 7013, info: "全体友方击退距离提升30%, 持续5秒",
},
6506: {
uuid: 6506, name: "穿透爆发", sp_name: "buff_wind", icon: "Stat_Tripleshot", TGroup: TGroup.Team, readyAnm: "up_ap", endAnm: "", act: "atk",

View File

@@ -1114,7 +1114,7 @@ function calcBuffPermanentEquivalent(buff: BuffConfig, apEff: number, cd: number
}
/** 计算 Support 类技能单次触发的效果价值 */
function calcSupportEffectValue(config: SkillConfig, apEff: number, cd: number, seconds: number): number {
function calcSupportEffectValue(config: SkillConfig, hpEff: number, apEff: number, cd: number, seconds: number): number {
const weights = HERO_POWER_WEIGHTS;
const value = config.ap || 0;
@@ -1131,10 +1131,12 @@ function calcSupportEffectValue(config: SkillConfig, apEff: number, cd: number,
switch (config.buff_type) {
case Attrs.ap:
return (value / cd) * weights.W_DPS_PER_SEC * seconds;
// 永久 buff 已改为百分比口径value 是百分比,需先换算为基础 ap 的绝对增量
return ((value / 100) * apEff / cd) * weights.W_DPS_PER_SEC * seconds;
case Attrs.hp_max:
case Attrs.hp:
return value * weights.W_HP;
// 永久 buff 已改为百分比口径value 是百分比,需先换算为基础 hp 的绝对增量
return (value / 100) * hpEff * weights.W_HP;
case Attrs.critical:
return (value / 100) * (apEff / cd) * 0.5 * weights.W_DPS_PER_SEC * seconds;
case Attrs.critical_damage:
@@ -1154,7 +1156,7 @@ function calcSupportEffectValue(config: SkillConfig, apEff: number, cd: number,
/** 计算单条技能配置单次触发的效果价值 */
function calcSkillEffectValue(skill: SkillConfig, overrides: SkillOverrides | undefined, hero: heroInfo, targetLv: number, seconds: number): number {
const { ap: apEff } = getEffectiveStats(hero, targetLv);
const { hp: hpEff, ap: apEff } = getEffectiveStats(hero, targetLv);
const cd = getAttackCd(hero);
const config = overrides ? mergeSkillParams(skill, overrides) : skill;
const weights = HERO_POWER_WEIGHTS;
@@ -1168,7 +1170,7 @@ function calcSkillEffectValue(skill: SkillConfig, overrides: SkillOverrides | un
// 护盾为数值减免型1 点护盾 ≈ 1 点预期伤害减免
return (config.ap || 0) * weights.W_shield;
case SkillKind.Support:
return calcSupportEffectValue(config, apEff, cd, seconds);
return calcSupportEffectValue(config, hpEff, apEff, cd, seconds);
default:
return 0;
}

View File

@@ -82,7 +82,7 @@ export class HeroAttrsComp extends ecs.Comp {
knockback_chance: number = 0; // 击退强化(原击退概率,现转换为击退距离增量)
knockback_distance: number = 0; // 击退距离强化
knockback_res: number = 0; // 击退抗性(削减击退距离增量)
crit_damage: number = 0; // 额外暴击伤害
critical_damage: number = 0; // 额外暴击伤害(与 Attrs.critical_damage 同名,供 add_special_attr 动态累加)
puncture_chance: number = 0; // 穿透概率
puncture_dmg_bonus: number = 0; // 穿透后伤害增量(百分点,乘算加成)
wfuny: number = 0; // 风怒
@@ -334,8 +334,8 @@ export class HeroAttrsComp extends ecs.Comp {
/** 英雄实时暴击伤害 = 基础额外暴伤 + 驻场暴伤。 */
public getRuntimeCritDamageBonus(): number {
if (this.fac !== FacSet.HERO) return this.crit_damage;
return this.crit_damage + HeroAttrsComp.getFieldPercentValue(FieldSkillType.HeroCritDamage);
if (this.fac !== FacSet.HERO) return this.critical_damage;
return this.critical_damage + HeroAttrsComp.getFieldPercentValue(FieldSkillType.HeroCritDamage);
}
/** 攻速加成通过缩短普通攻击技能 CD 生效,正值越高,攻击越快。 */
@@ -606,7 +606,7 @@ export class HeroAttrsComp extends ecs.Comp {
this.knockback_chance = 0;
this.knockback_distance = 0;
this.knockback_res = 0;
this.crit_damage = 0;
this.critical_damage = 0;
this.revived_count = 0;
this.invincible_time = 0;
this.puncture_chance = 0;

View File

@@ -551,18 +551,24 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
return;
}
// 永久 buff 的数值直接取 config.ap已由 SkillConfig/SkillOverrides 提供最终值)
// 永久 buff 统一按百分比结算:攻击/生命按基础值相对放大,其余按百分点累加
const totalBuffValue = config.ap;
switch (config.buff_type) {
case Attrs.ap:
model.add_ap(totalBuffValue);
case Attrs.ap: {
// 攻击力按基础 ap 的百分比提升
const addAp = Math.floor(model.ap * totalBuffValue / 100);
model.add_ap(addAp);
break;
case Attrs.hp_max:
model.add_hp_max(totalBuffValue);
}
case Attrs.hp_max: {
// 最大生命按基础 hp_max 的百分比提升
const addHp = Math.floor(model.hp_max * totalBuffValue / 100);
model.add_hp_max(addHp);
break;
}
default:
// 除了 hp_max 和 ap其他固定属性走统一的 add_special_attr 方法
// 暴击/击晕/穿透/攻速等概率类属性按百分点直接累加
model.add_special_attr(config.buff_type, totalBuffValue);
break;
}