refactor: 统一全量buff数值为百分比口径
本次变更对齐了所有buff和技能的数值结算规则: 1. 新增项目规范明确buff数值统一使用百分比/百分点结算 2. 修改技能描述配置、属性计算逻辑,将固定数值加成改为百分比计算 3. 调整buff配置的修改类型为PercentAdd,同步更新buff说明文本 4. 重构属性计算逻辑,区分百分比加成和固定加成的处理方式 5. 更新战力计算逻辑适配新的百分比口径规则
This commit is contained in:
@@ -67,6 +67,7 @@ alwaysApply: true
|
||||
1. **技能底座纯净化**:SkillSet 中的技能只定义基础行为(伤害、弹道、命中),**禁止**在基础配置中写死 `timed_buff_id` / `buff_type` 等效果字段
|
||||
2. **效果由引用处注入**:英雄/怪物引用技能时,通过 `HSkillInfo.overrides` 按需附加 debuff/buff,实现"同一技能、不同效果"
|
||||
3. **数值覆盖优先**:`ap`(伤害百分比)、`hit_count`、`crt` 等数值差异,统一由 `overrides` 覆写,而非新建相似技能
|
||||
4. **Buff 统一百分比口径**:无论永久 buff(`buff_type`)还是计时 buff(`timed_buff_id`),修饰数值均按百分比/百分点结算;`ap`/`hp_max` 按基础值相对放大,概率类属性按百分点累加
|
||||
|
||||
## SkillSet 配置规范
|
||||
|
||||
|
||||
@@ -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 秒",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user