feat: 实现DoT灼烧技能与debuff图标系统

本次提交完成了以下核心改动:
1.  调整fb-1~fb-6技能预制件的攻击偏移坐标,优化技能弹道位置
2.  新增DoT伤害机制,支持周期伤害/治疗的独立结算
3.  为Buff系统添加施法者属性快照,让DoT暴击、控制判定更准确
4.  新增顶栏debuff图标显示功能,支持灼烧等负面状态可视化
5.  为破晓先知等英雄替换为新的灼烧火球技能6104
6.  修复fb-2预制件的配置字段顺序与多余属性问题
This commit is contained in:
panFD
2026-08-15 14:36:38 +08:00
parent 8e5c0d3852
commit e8c6a7ca6a
17 changed files with 4118 additions and 970 deletions

View File

@@ -1,7 +1,9 @@
import { _decorator, ProgressBar, Sprite, UIOpacity, Vec3, v3, tween, Tween, Color, clamp } 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 } from "../common/config/BuffSet";
import { FacSet, FightSet } from "../common/config/GameSet";
const { ccclass, property } = _decorator;
@@ -35,6 +37,10 @@ export class HeroTopBarComp extends CCComp {
// ==================== 内部引用 ====================
private topOpacity: UIOpacity = null!;
private basePos: Vec3 = v3();
/** debuff 容器节点top 下的 debuff 子节点,按名字管理各 debuff 图标) */
private debuffNode: Node = null!;
/** 当前点亮的 debuff 图标节点名集合(用于 diff避免每帧重复 set active */
private activeDebuffNames: Set<string> = new Set();
// ==================== 配置 ====================
private hp_height: number = 90;
@@ -87,6 +93,15 @@ export class HeroTopBarComp extends CCComp {
this.node.getChildByName("lv")!.active = false;
this.node.active = true;
// debuff 图标容器(无该节点的旧 prefab 容错为 null
this.debuffNode = this.node.getChildByName("debuff")!;
this.activeDebuffNames.clear();
if (this.debuffNode) {
for (const child of this.debuffNode.children) {
child.active = false;
}
}
this.setTopBarOpacity(false);
this.hpShow();
this.shieldShow(model.shield);
@@ -120,6 +135,51 @@ export class HeroTopBarComp extends CCComp {
this.shieldProgressBar.node.active = shield > 0;
}
/**
* buffId → debuff 图标节点名映射(节点名为 top.prefab debuff 容器下的子节点名)。
* 仅伤害类 debuff 需要图标;未映射的 buff 不显示。
*/
private static readonly DEBUFF_ICON_MAP: Record<number, string> = {
7002: "FireDamage", // 灼烧
};
/**
* 刷新 debuff 图标显隐:按 BuffComp 中当前生效的 debuff 种类点亮对应图标。
* 由 HeroViewComp 在 dirty_buffs 脏标记时调用;与上次状态做 diff避免重复 set active。
* @param buffComp 目标的 buff 组件(无 BuffComp 时全部隐藏)
*/
public debuffShow(buffComp: BuffComp | null): void {
if (!this.debuffNode) return;
// 收集当前生效的、有图标映射的 debuff 节点名
const wantActive = new Set<string>();
if (buffComp) {
for (const [buffId, layers] of buffComp.buffs) {
if (layers.length === 0) continue;
const cfg = BuffList[buffId];
// 只显示伤害类 debufftick 负值)与控制类 debuff普通 Buff 不占用 debuff 栏
if (!cfg || cfg.category === BuffCategory.Buff) continue;
const nodeName = HeroTopBarComp.DEBUFF_ICON_MAP[buffId];
if (nodeName) wantActive.add(nodeName);
}
}
// diff先隐藏不再需要的再点亮新增的
for (const name of this.activeDebuffNames) {
if (!wantActive.has(name)) {
const child = this.debuffNode.getChildByName(name);
if (child) child.active = false;
}
}
for (const name of wantActive) {
if (!this.activeDebuffNames.has(name)) {
const child = this.debuffNode.getChildByName(name);
if (child) child.active = true;
}
}
this.activeDebuffNames = wantActive;
}
/** 激活顶栏(高亮 + 延迟恢复闲置透明度) */
public activateTopBar(): void {
this.setTopBarOpacity(true);
@@ -165,6 +225,12 @@ export class HeroTopBarComp extends CCComp {
/** 对象池回收 / 组件重置时调用 */
public reset(): void {
this.unscheduleAllCallbacks();
this.activeDebuffNames.clear();
if (this.debuffNode && this.debuffNode.isValid) {
for (const child of this.debuffNode.children) {
child.active = false;
}
}
if (this.node && this.node.isValid) {
Tween.stopAllByTarget(this.node);
this.node.setPosition(this.basePos);