refactor(hero): 重构护盾数值逻辑,使用快照最大值作为进度分母

1. 新增shield_max字段存储护盾获得时的快照值,作为护盾进度条固定分母
2. 修改add_shield方法为覆盖式设置护盾,新增注释说明设计原因
3. 移除HeroTopBarComp中冗余的NumberFormatter导入和动态创建的护盾数值标签
4. 重构护盾进度条更新逻辑,使用快照值计算进度,修复原进度条异常问题
This commit is contained in:
panFD
2026-09-13 13:40:32 +08:00
parent 3b744fc3f2
commit 4f749c9a81
2 changed files with 19 additions and 31 deletions

View File

@@ -40,6 +40,8 @@ export class HeroAttrsComp extends ecs.Comp {
speed: number = 100; // 基础移动速度
dis: number = 100; // 基础距离
shield: number = 0; // 当前护盾
/** 护盾获得时的快照值,作为护盾进度条分母(护盾为覆盖语义,分母不能随扣盾变化) */
shield_max: number = 0;
defense: number = 0; // 防御(除法递减模型减伤,见 getFinalDefense)
// ==================== 攻击属性 (补充) ====================
@@ -161,12 +163,16 @@ export class HeroAttrsComp extends ecs.Comp {
}
return addValue;
}
/**
* 设置护盾值(覆盖语义,不累加)。
*
* Why 覆盖而非累加:新护盾直接替换旧护盾,避免多源护盾无限叠加导致数值膨胀。
* @param value 新的护盾值(<=0 时视为清空护盾)
*/
add_shield(value: number) {
const oldShield = this.shield;
const addValue = Math.max(0, Math.floor(value));
if (addValue <= 0) return;
this.shield += addValue;
if (this.shield < 0) this.shield = 0;
this.shield = Math.max(0, Math.floor(value));
// 覆盖为新护盾时刷新快照分母;清空护盾时分母归零
this.shield_max = this.shield;
this.dirty_shield = true; // 标记护盾需要更新
}
add_hp_max(value: number) {
@@ -694,6 +700,7 @@ export class HeroAttrsComp extends ecs.Comp {
this.speed = 100;
this.dis = 100;
this.shield = 0;
this.shield_max = 0;
this.defense = 0;
// 重置新增属性

View File

@@ -1,10 +1,10 @@
import { _decorator, ProgressBar, Sprite, UIOpacity, UITransform, Vec3, v3, tween, Tween, Color, clamp, Node, Label, LabelOutline } from "cc";
import { _decorator, ProgressBar, Sprite, UIOpacity, Vec3, v3, tween, Tween, Color, clamp, Node } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { HeroAttrsComp } from "./HeroAttrsComp";
import { BuffComp } from "./BuffComp";
import { BuffList, BuffCategory, DEBUFF_ICON_MAP } from "../common/config/BuffSet";
import { FacSet, NumberFormatter } from "../common/config/GameSet";
import { FacSet } from "../common/config/GameSet";
const { ccclass, property } = _decorator;
@@ -44,8 +44,6 @@ export class HeroTopBarComp extends CCComp {
private debuffNode: Node = null!;
/** 当前点亮的 debuff 图标节点名集合(用于 diff,避免每帧重复 set active) */
private activeDebuffNames: Set<string> = new Set();
/** 护盾数值文本(护盾条节点下动态创建,显示当前护盾数值) */
private shieldLabel: Label = null!;
// ==================== 配置 ====================
private hp_height: number = 90;
@@ -143,9 +141,9 @@ export class HeroTopBarComp extends CCComp {
/**
* 更新护盾数值条。
*
* Why 进度按 shield / max(hpMax, shield) 计算:护盾无固定上限,
* 写死满条会导致受击时进度条不动;以血条上限为分母可在护盾被削减时实时反映下降,
* 同时护盾条作为血条之上的覆盖层,视觉上表现为护盾先行消耗。
* Why 分母用 shield_max 快照而非实时值:护盾为覆盖语义且可能远超血条上限,
* 若分母随扣盾变小,进度条会永远满格不动;以护盾获得时的值为分母,
* 扣盾时进度实时下降,覆盖新护盾时回到满格。
* @param shield 当前护盾值(可为 0,此时隐藏护盾条)
*/
public shieldShow(shield: number = 0): void {
@@ -154,25 +152,8 @@ export class HeroTopBarComp extends CCComp {
this.shieldProgressBar.node.active = active;
if (!active) return;
// 进度分母取护盾与血条上限的较大值,保证比例稳定在 [0,1] 且随扣盾实时下降
const hpMax = this._model ? this._model.getFinalHpMax() : 0;
const divisor = Math.max(hpMax, shield, 1);
this.shieldProgressBar.progress = clamp(shield / divisor, 0, 1);
// 数值文本:懒加载创建,随护盾条节点一起显隐
if (!this.shieldLabel) {
const labelNode = new Node("shield_num");
const ui = labelNode.addComponent(UITransform);
labelNode.setParent(this.shieldProgressBar.node);
this.shieldLabel = labelNode.addComponent(Label);
this.shieldLabel.fontSize = 10;
this.shieldLabel.lineHeight = 10;
this.shieldLabel.color = new Color("#FFFFFF");
const outline = labelNode.addComponent(LabelOutline);
outline.color = new Color("#000000");
outline.width = 1;
}
this.shieldLabel.string = NumberFormatter.formatNumber(Math.floor(shield));
const divisor = this._model ? this._model.shield_max : 0;
this.shieldProgressBar.progress = divisor > 0 ? clamp(shield / divisor, 0, 1) : 1;
}
/**