diff --git a/assets/script/game/common/config/BuffSet.ts b/assets/script/game/common/config/BuffSet.ts index b4a57c27..6231bc99 100644 --- a/assets/script/game/common/config/BuffSet.ts +++ b/assets/script/game/common/config/BuffSet.ts @@ -278,4 +278,13 @@ export const BuffList: Record = { 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 秒", + }, }; diff --git a/assets/script/game/common/config/SkillSet.ts b/assets/script/game/common/config/SkillSet.ts index 2e353f97..a21511c7 100644 --- a/assets/script/game/common/config/SkillSet.ts +++ b/assets/script/game/common/config/SkillSet.ts @@ -541,8 +541,12 @@ export const SkillSet: Record = { 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 { @@ -597,7 +601,7 @@ export const FieldSkillSet: Record = { 7021: { uuid: 7021, name: "反伤光环", icon: "75-Shield-Stun", type: FieldSkillType.HeroThornsDmg, info: "英雄固定反伤提升" }, 7022: { uuid: 7022, name: "反伤比例光环", icon: "75-Shield-Stun", type: FieldSkillType.HeroThornsRate, info: "英雄比例反伤提升(百分点)" }, - + 7014: { uuid: 7014, name: "召唤强化", icon: "9-Battle-Roar", type: FieldSkillType.SummonCount, info: "召唤触发技能次数提升" }, 7015: { uuid: 7015, name: "死亡强化", icon: "102-Rise", type: FieldSkillType.DeadCount, info: "死亡触发技能次数提升" }, 7016: { uuid: 7016, name: "开场强化", icon: "64-Prominance", type: FieldSkillType.StartCount, info: "战斗开始触发技能次数提升" }, diff --git a/assets/script/game/hero/HeroAttrsComp.ts b/assets/script/game/hero/HeroAttrsComp.ts index 3f1f1004..b7e37d10 100644 --- a/assets/script/game/hero/HeroAttrsComp.ts +++ b/assets/script/game/hero/HeroAttrsComp.ts @@ -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; } } diff --git a/assets/script/game/hero/HeroTopBarComp.ts b/assets/script/game/hero/HeroTopBarComp.ts index 6ed1d505..0035f0f7 100644 --- a/assets/script/game/hero/HeroTopBarComp.ts +++ b/assets/script/game/hero/HeroTopBarComp.ts @@ -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); diff --git a/assets/script/game/hero/HeroViewComp.ts b/assets/script/game/hero/HeroViewComp.ts index 129d50ea..d999ae70 100644 --- a/assets/script/game/hero/HeroViewComp.ts +++ b/assets/script/game/hero/HeroViewComp.ts @@ -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; } }