refactor(hero): 重构英雄数值系统,支持品质系数与12级职业属性加成

1. 调整英雄最大等级为99,实现近似无限升级
2. 新增防御属性加成系统,补充def_bonus相关配置与计算
3. 引入英雄品质系数机制,相邻品质基础属性相差5%
4. 新增12级职业属性专项加成:坦克加防、战士辅助加血、输出加攻
5. 更新英雄设计文档与配置示例,统一数值计算逻辑
6. 重构成长计算函数,支持防御属性成长与加成
This commit is contained in:
panFD
2026-09-01 20:47:36 +08:00
parent d943bc05ce
commit 1dbb3bd90d
6 changed files with 185 additions and 68 deletions

View File

@@ -5,7 +5,7 @@ import { smc } from "../common/SingletonModuleComp";
import { HeroAttrsComp } from "./HeroAttrsComp";
import { HeroViewComp } from "./HeroViewComp";
import { BoxSet, FacSet, FightSet, IndexSet } from "../common/config/GameSet";
import { HeroInfo, resolveFormationTargetX, resolveTriggerByLv, resolveFieldByLv, resolveReviveByLv, resolveSkillOverrides, calcGrowBonus, HeroDisVal } from "../common/config/heroSet";
import { HeroInfo, resolveFormationTargetX, resolveTriggerByLv, resolveFieldByLv, resolveReviveByLv, resolveSkillOverrides, calcGrowBonus, HeroDisVal, getHeroQualityCoef, getEffectiveStats, HERO_LV12_SPECIAL_LV, HERO_LV12_BASE_LV, HERO_LV12_SPECIAL_ATTR } from "../common/config/heroSet";
import { GameEvent } from "../common/config/GameEvent";
import { SkillTriggerType, HType } from "../common/config/heroSet";
import { SkillTriggerHelper } from "./SkillTriggerHelper";
@@ -140,15 +140,18 @@ export class Hero extends ecs.Entity {
model.revive = hero.revive;
model.ap_bonus = hero.ap_bonus;
model.hp_bonus = hero.hp_bonus;
model.def_bonus = hero.def_bonus;
// 基础属性:固定基础值,成长完全由 grow_type 指数递增提供(替代旧 ×2^(lv-1) 翻倍)
// 基础属性:固定基础值 × 品质系数(相邻品质差 5%),成长由 grow_type 线性递增提供
// TODO: 局外升级机制落地后,此处基础值将与存档强化累加重算
let base_ap = hero.ap;
let base_hp = hero.hp;
const qualityCoef = getHeroQualityCoef(hero.card_lv ?? 1);
let base_ap = Math.round(hero.ap * qualityCoef);
let base_hp = Math.round(hero.hp * qualityCoef);
let base_def = Math.round(hero.def * qualityCoef);
model.base_ap = base_ap;
model.base_hp = base_hp;
model.defense = hero.def;
model.defense = base_def;
// 英雄享受驻场百分比加成,怪物保持基础值
if (model.fac === FacSet.HERO) {
@@ -179,11 +182,12 @@ export class Hero extends ecs.Entity {
model.runtime_field = resolveFieldByLv(model.field, hero_lv);
model.runtime_revive = resolveReviveByLv(model.revive, hero_lv);
// 应用额外属性加成(成长类型每级递增 + hp_bonus/ap_bonus 一次性奖励累加)
// 应用额外属性加成(成长类型每级递增 + hp/ap/def_bonus 一次性奖励累加)
// 成长增量:仅英雄生效(model.fac 已为 HERO),按 grow_type 递增曲线累计
const grow = calcGrowBonus(hero, hero_lv);
model.hp += grow.hp; model.hp_max += grow.hp;
model.ap += grow.ap;
model.defense += grow.def;
if (model.hp_bonus) {
let hpExtra = 0;
for (const e of model.hp_bonus) { if (e.lv <= hero_lv) hpExtra += e.value; }
@@ -194,6 +198,21 @@ export class Hero extends ecs.Entity {
for (const e of model.ap_bonus) { if (e.lv <= hero_lv) apExtra += e.value; }
model.ap += apExtra;
}
if (model.def_bonus) {
let defExtra = 0;
for (const e of model.def_bonus) { if (e.lv <= hero_lv) defExtra += e.value; }
model.defense += defExtra;
}
// lv12 职业属性专项:达到 12 级时按职业对单项基础属性 +50%
// 基数为 lv11 当前等级有效值(基础 + 成长 + lv9 bonus,不含 lv12 自身),仅英雄生效
if (model.fac === FacSet.HERO && hero_lv >= HERO_LV12_SPECIAL_LV && model.role !== undefined) {
const lv11 = getEffectiveStats(hero, HERO_LV12_BASE_LV);
const attr = HERO_LV12_SPECIAL_ATTR[model.role];
if (attr === "def") model.defense += Math.round(lv11.def * 0.5);
else if (attr === "hp") { const add = Math.round(lv11.hp * 0.5); model.hp += add; model.hp_max += add; }
else if (attr === "ap") model.ap += Math.round(lv11.ap * 0.5);
}
// 天赋加成层:全局天赋(一阶基础/三阶超强全局)全局生效,职业天赋(二阶专精/三阶超强职业)按 role 过滤(仅英雄生效,怪物跳过)
// Why: 放在成长/bonus 之后、光环乘区之后,以基础快照为基数叠加,避免与乘区叠加成乘法膨胀

View File

@@ -54,9 +54,10 @@ export class HeroAttrsComp extends ecs.Comp {
/** 驻场光环(按 lv 解锁,存活期间全局生效) */
[SkillTriggerType.Field]?: LvFieldEntry[];
[SkillTriggerType.Revive]?: LvReviveEntry[];
/** 额外攻击/生命加成(按 lv 累加) */
/** 额外攻击/生命/防御加成(按 lv 累加) */
ap_bonus?: LvBonusEntry[];
hp_bonus?: LvBonusEntry[];
def_bonus?: LvBonusEntry[];
// ==================== 运行时解析缓存(按当前等级 resolve 后的有效列表) ====================
/** 当前等级下生效的攻击触发条目(供 SkillTriggerHelper 消费) */
@@ -633,6 +634,7 @@ export class HeroAttrsComp extends ecs.Comp {
this.revive = undefined;
this.ap_bonus = undefined;
this.hp_bonus = undefined;
this.def_bonus = undefined;
this.runtime_atking = undefined;
this.runtime_atked = undefined;
this.runtime_call = undefined;