feat(hero&buff): 新增限时最大生命Buff与配套技能

新增7029生命爆发Buff和对应6517技能,实现限时提升最大生命功能:
1.  Buff生效时按增量等量回血,到期自动钳回血量防止溢血
2.  血条显示逻辑适配动态最大生命值变化
3.  新增血量与最终最大生命同步方法统一处理边界情况
This commit is contained in:
pan
2026-09-07 11:16:02 +08:00
parent 852976d54b
commit 922ca7318d
5 changed files with 58 additions and 3 deletions

View File

@@ -278,4 +278,13 @@ export const BuffList: Record<number, BuffConfig> = {
modifiers: [{ attr: Attrs.thorns_rate, op: ModOp.PercentAdd, value: 10 }],
info: "受到攻击时反弹 10% 所受伤害,可叠加,持续 5 秒",
},
// ==================== 生命上限系 ====================
// 生命爆发(限时提升最大生命;生效时按增量等量回血,到期钳回,由 HeroAttrsComp.syncHpWithFinalMax 统一结算)
7029: {
id: 7029, name: "生命爆发", icon: "29-Endure",
category: BuffCategory.Buff, duration: 5, max_stack: 1,
modifiers: [{ attr: Attrs.hp_max, op: ModOp.PercentAdd, value: 30 }],
info: "最大生命值提升 30%,并立即回复等量生命,持续 5 秒",
},
};

View File

@@ -541,8 +541,12 @@ export const SkillSet: Record<number, SkillConfig> = {
uuid: 6516, name: "次级反伤", sp_name: "buff_wind", icon: "75-Shield-Stun", TGroup: TGroup.Self, readyAnm: "up_blue", endAnm: "", act: "atk",
DTType: DTType.single, kind: SkillKind.Support, ap: 0, 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, info: "次级反伤技能,效果由引用处 overrides 注入",
},
6517: {
uuid: 6517, name: "生命爆发", sp_name: "buff_wind", icon: "29-Endure", 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,
RType: RType.fixed, EType: EType.animationEnd, buff_type: Attrs.hp_max, timed_buff_id: 7029, info: "全体友方最大生命值提升30%, 持续5秒",
}
};
//***************驻场技能配置***************
export enum FieldSkillType {

View File

@@ -106,6 +106,12 @@ export class HeroAttrsComp extends ecs.Comp {
dirty_shield: boolean = false; // 护盾变更标记
dirty_lv: boolean = false; // 等级变更标记
/**
* 最终最大生命(getFinalHpMax)的最近快照,用于计时 hp_max buff 生效/到期时的血量同步。
* null 表示尚未建立快照(初始化/对象池复用后首次 syncHpWithFinalMax 仅记录不结算)。
*/
private _lastFinalHpMax: number | null = null;
// ==================== 技能距离缓存 ====================
maxSkillDistance: number = 0; // 最远技能攻击距离(缓存,受MP影响)
minSkillDistance: number = 0; // 最近技能攻击距离(缓存,不受MP影响,用于停止位置判断)
@@ -168,6 +174,35 @@ export class HeroAttrsComp extends ecs.Comp {
return value
}
/**
* 同步当前血量与最终最大生命的偏差(计时 hp_max buff 的生效/到期结算钩子)。
*
* Why: 计时 buff 的上限增减不回写 hp_max 字段,若不做同步:
* - 生效时血条比例骤降(分母变大、分子不变),满血单位表现为"掉血",体验极差;
* - 到期时 hp 可能超过回落后的新上限,出现"溢血"。
* 策略:上限增量按等量回血(与永久路径 add_hp_max 口径一致,满血也有收益);
* 上限回落时钳回新上限,借出的生命随到期自然收回。
* 单点快照 diff 覆盖生效/到期/驱散/叠层全部路径,BuffManager/BuffSystem 无需感知。
*/
syncHpWithFinalMax() {
const finalMax = this.getFinalHpMax();
// 首次调用仅建立快照,避免初始化/对象池复用时误回血
if (this._lastFinalHpMax === null) {
this._lastFinalHpMax = finalMax;
return;
}
const delta = finalMax - this._lastFinalHpMax;
if (delta === 0) return;
if (delta > 0) {
// 等量回血。直接写 this.hp 而非走 add_hp,避免 add_hp 内 clamp → getFinalHpMax 的递归
this.hp += delta;
} else if (this.hp > finalMax) {
this.hp = finalMax; // 上限回落,钳回防溢血
}
this._lastFinalHpMax = finalMax;
this.dirty_hp = true; // 驱动血条刷新
}
add_ap(value: number) {
this.ap += value
return value
@@ -700,6 +735,8 @@ export class HeroAttrsComp extends ecs.Comp {
this.dirty_hp = false;
this.dirty_shield = false;
this.dirty_lv = false;
// 重置计时 hp_max buff 的血量同步快照(下次 syncHpWithFinalMax 重新建立基准)
this._lastFinalHpMax = null;
}
}

View File

@@ -119,8 +119,11 @@ export class HeroTopBarComp extends CCComp {
/** 更新血量进度条 */
public hpShow(): void {
if (!this._model || !this.hpProgressBar) return;
// 计时 hp_max buff 的增删不走 dirty_hp,显示前先做上限-血量同步(等量回血/到期钳回)
this._model.syncHpWithFinalMax();
const hp = this._model.hp;
const hpMax = this._model.hp_max;
// 分母用 getFinalHpMax:计时 hp_max buff 的上限加成需实时反映到血条
const hpMax = this._model.getFinalHpMax();
let targetProgress = hpMax > 0 ? hp / hpMax : 0;
targetProgress = clamp(targetProgress, 0, 1);

View File

@@ -155,6 +155,8 @@ export class HeroViewComp extends CCComp {
const buffComp = this.ent.has(BuffComp) ? this.ent.get(BuffComp) : null;
if (buffComp && buffComp.dirty_buffs) {
this.topBar.debuffShow(buffComp);
// hp_max 计时 buff 的生效/到期会改变血条上限,同步刷新血条(内部走 syncHpWithFinalMax)
this.topBar.hpShow();
buffComp.dirty_buffs = false;
}
}