refactor(skill&atk): 优化伤害飘字与debuff图标显示逻辑
1. 调整fb-1、fb-3、fb-5、fb-6技能预制体的攻击偏移与跑动类型参数 2. 重构debuff图标映射逻辑,提取公共常量供多模块复用 3. 为DoT伤害飘字添加debuff图标显示功能,统一伤害与debuff展示流程 4. 修复tooltip预制体默认激活状态问题
This commit is contained in:
@@ -252,8 +252,8 @@
|
|||||||
"__id__": 11
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"atk_x": 20,
|
"atk_x": 20,
|
||||||
"atk_y": 35,
|
"atk_y": 20,
|
||||||
"runType": 0,
|
"runType": 1,
|
||||||
"endType": 2,
|
"endType": 2,
|
||||||
"speed": 720,
|
"speed": 720,
|
||||||
"time": 0,
|
"time": 0,
|
||||||
|
|||||||
@@ -252,8 +252,8 @@
|
|||||||
"__id__": 11
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"atk_x": 20,
|
"atk_x": 20,
|
||||||
"atk_y": 30,
|
"atk_y": 20,
|
||||||
"runType": 0,
|
"runType": 1,
|
||||||
"endType": 2,
|
"endType": 2,
|
||||||
"speed": 720,
|
"speed": 720,
|
||||||
"time": 0,
|
"time": 0,
|
||||||
|
|||||||
@@ -252,7 +252,7 @@
|
|||||||
"__id__": 11
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"atk_x": 20,
|
"atk_x": 20,
|
||||||
"atk_y": 30,
|
"atk_y": 20,
|
||||||
"runType": 0,
|
"runType": 0,
|
||||||
"endType": 2,
|
"endType": 2,
|
||||||
"speed": 720,
|
"speed": 720,
|
||||||
|
|||||||
@@ -252,7 +252,7 @@
|
|||||||
"__id__": 11
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"atk_x": 20,
|
"atk_x": 20,
|
||||||
"atk_y": 30,
|
"atk_y": 20,
|
||||||
"runType": 0,
|
"runType": 0,
|
||||||
"endType": 2,
|
"endType": 2,
|
||||||
"speed": 720,
|
"speed": 720,
|
||||||
|
|||||||
@@ -942,7 +942,7 @@
|
|||||||
"__id__": 30
|
"__id__": 30
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": false,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 32
|
"__id__": 32
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { getMonsterGoldDrop } from "../map/RogueConfig";
|
|||||||
import { MissionEconomy } from "../map/MissionEconomy";
|
import { MissionEconomy } from "../map/MissionEconomy";
|
||||||
import { MoveComp } from "./MoveComp";
|
import { MoveComp } from "./MoveComp";
|
||||||
import { buffManager, BuffApplyOverrides } from "./BuffManager";
|
import { buffManager, BuffApplyOverrides } from "./BuffManager";
|
||||||
|
import { DEBUFF_ICON_MAP } from "./HeroTopBarComp";
|
||||||
|
|
||||||
/** 最终伤害数据接口
|
/** 最终伤害数据接口
|
||||||
* 用于封装一次攻击计算的所有结果数据
|
* 用于封装一次攻击计算的所有结果数据
|
||||||
@@ -196,8 +197,9 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
|||||||
// ✅ 触发视图层表现(伤害数字、受击动画、冰冻、击晕、击退)
|
// ✅ 触发视图层表现(伤害数字、受击动画、冰冻、击晕、击退)
|
||||||
if (targetView) {
|
if (targetView) {
|
||||||
if (isDot) {
|
if (isDot) {
|
||||||
// DoT:只飘伤害数字 + 刷新血条,不播受击动画/音效/击退
|
// DoT:只飘伤害数字 + 刷新血条,不播受击动画/音效/击退;
|
||||||
targetView.showDamage(damage, isCrit);
|
// s_uuid 位置是 buffId,据此激活 loss_life/hp/debuff 下的对应 debuff 图标
|
||||||
|
targetView.showDamage(damage, isCrit, DEBUFF_ICON_MAP[damageEvent.s_uuid] ?? "");
|
||||||
} else {
|
} else {
|
||||||
// 击退:受击默认后退,击退属性不再作为概率,而是转换为后退距离的增量
|
// 击退:受击默认后退,击退属性不再作为概率,而是转换为后退距离的增量
|
||||||
// 击退增量 = 施法者击退强化(原击退概率)- 被攻击者击退抗性 + 击退距离强化
|
// 击退增量 = 施法者击退强化(原击退概率)- 被攻击者击退抗性 + 击退距离强化
|
||||||
|
|||||||
@@ -20,6 +20,15 @@ const { ccclass, property } = _decorator;
|
|||||||
* 数据流:HeroViewComp 将 HeroAttrsComp 引用传入,本组件通过 model 读取属性。
|
* 数据流:HeroViewComp 将 HeroAttrsComp 引用传入,本组件通过 model 读取属性。
|
||||||
* 注意:英雄根节点下的 "shielded" 是护盾特效动画节点,由 HeroViewComp 管理,不在本组件职责内。
|
* 注意:英雄根节点下的 "shielded" 是护盾特效动画节点,由 HeroViewComp 管理,不在本组件职责内。
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* buffId → debuff 图标节点名映射(节点名为 top.prefab / tooltip.prefab debuff 容器下的子节点名,两处同名)。
|
||||||
|
* 仅伤害类 debuff 需要图标;未映射的 buff 不显示。
|
||||||
|
* 导出供 HeroTopBarComp(头顶 debuff 栏)与 HeroAtkSystem(DoT 飘字图标)共用。
|
||||||
|
*/
|
||||||
|
export const DEBUFF_ICON_MAP: Record<number, string> = {
|
||||||
|
7002: "FireDamage", // 灼烧
|
||||||
|
};
|
||||||
|
|
||||||
@ccclass('HeroTopBarComp')
|
@ccclass('HeroTopBarComp')
|
||||||
@ecs.register('HeroTopBar', false)
|
@ecs.register('HeroTopBar', false)
|
||||||
export class HeroTopBarComp extends CCComp {
|
export class HeroTopBarComp extends CCComp {
|
||||||
@@ -135,14 +144,6 @@ export class HeroTopBarComp extends CCComp {
|
|||||||
this.shieldProgressBar.node.active = shield > 0;
|
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 种类点亮对应图标。
|
* 刷新 debuff 图标显隐:按 BuffComp 中当前生效的 debuff 种类点亮对应图标。
|
||||||
* 由 HeroViewComp 在 dirty_buffs 脏标记时调用;与上次状态做 diff,避免重复 set active。
|
* 由 HeroViewComp 在 dirty_buffs 脏标记时调用;与上次状态做 diff,避免重复 set active。
|
||||||
@@ -159,7 +160,7 @@ export class HeroTopBarComp extends CCComp {
|
|||||||
const cfg = BuffList[buffId];
|
const cfg = BuffList[buffId];
|
||||||
// 只显示伤害类 debuff(tick 负值)与控制类 debuff;普通 Buff 不占用 debuff 栏
|
// 只显示伤害类 debuff(tick 负值)与控制类 debuff;普通 Buff 不占用 debuff 栏
|
||||||
if (!cfg || cfg.category === BuffCategory.Buff) continue;
|
if (!cfg || cfg.category === BuffCategory.Buff) continue;
|
||||||
const nodeName = HeroTopBarComp.DEBUFF_ICON_MAP[buffId];
|
const nodeName = DEBUFF_ICON_MAP[buffId];
|
||||||
if (nodeName) wantActive.add(nodeName);
|
if (nodeName) wantActive.add(nodeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ export class HeroViewComp extends CCComp {
|
|||||||
private damageQueue: Array<{
|
private damageQueue: Array<{
|
||||||
damage: number,
|
damage: number,
|
||||||
isCrit: boolean,
|
isCrit: boolean,
|
||||||
|
debuffIcon: string,
|
||||||
}> = [];
|
}> = [];
|
||||||
private isProcessingDamage: boolean = false;
|
private isProcessingDamage: boolean = false;
|
||||||
private damageInterval: number = 0.01; // 伤害数字显示间隔
|
private damageInterval: number = 0.01; // 伤害数字显示间隔
|
||||||
@@ -209,7 +210,7 @@ export class HeroViewComp extends CCComp {
|
|||||||
Tooltip.load(pos, TooltipTypes.skill, value, s_uuid, this.node, 1, this.model?.fac ?? FacSet.MON, triggerType);
|
Tooltip.load(pos, TooltipTypes.skill, value, s_uuid, this.node, 1, this.model?.fac ?? FacSet.MON, triggerType);
|
||||||
}
|
}
|
||||||
/** 血量提示(伤害数字) */
|
/** 血量提示(伤害数字) */
|
||||||
private hp_tip(type: number = 1, value: string = "", s_uuid: number = 1001, y: number = 0) {
|
private hp_tip(type: number = 1, value: string = "", s_uuid: number = 1001, y: number = 0, debuffIcon: string = "") {
|
||||||
let x = this.node.position.x;
|
let x = this.node.position.x;
|
||||||
// 获取怪物高度的一半,定位到中心点
|
// 获取怪物高度的一半,定位到中心点
|
||||||
let halfHeight = 0;
|
let halfHeight = 0;
|
||||||
@@ -221,7 +222,7 @@ export class HeroViewComp extends CCComp {
|
|||||||
// 起点设为怪物中心偏下位置,使其在血条下方
|
// 起点设为怪物中心偏下位置,使其在血条下方
|
||||||
let ny = this.node.position.y + halfHeight - 15;
|
let ny = this.node.position.y + halfHeight - 15;
|
||||||
let pos = v3(x, ny, 0);
|
let pos = v3(x, ny, 0);
|
||||||
Tooltip.load(pos, type, value, s_uuid, this.node.parent, 1, this.model?.fac ?? FacSet.MON);
|
Tooltip.load(pos, type, value, s_uuid, this.node.parent, 1, this.model?.fac ?? FacSet.MON, "", debuffIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 护盾减免提示 */
|
/** 护盾减免提示 */
|
||||||
@@ -449,11 +450,11 @@ export class HeroViewComp extends CCComp {
|
|||||||
|
|
||||||
|
|
||||||
/** 显示伤害数字 */
|
/** 显示伤害数字 */
|
||||||
|
showDamage(damage: number, isCrit: boolean, debuffIcon: string = "") {
|
||||||
showDamage(damage: number, isCrit: boolean) {
|
|
||||||
this.damageQueue.push({
|
this.damageQueue.push({
|
||||||
damage,
|
damage,
|
||||||
isCrit,
|
isCrit,
|
||||||
|
debuffIcon,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,7 +465,7 @@ export class HeroViewComp extends CCComp {
|
|||||||
this.isProcessingDamage = true;
|
this.isProcessingDamage = true;
|
||||||
const damageInfo = this.damageQueue.shift()!;
|
const damageInfo = this.damageQueue.shift()!;
|
||||||
|
|
||||||
this.showDamageImmediate(damageInfo.damage, damageInfo.isCrit);
|
this.showDamageImmediate(damageInfo.damage, damageInfo.isCrit, damageInfo.debuffIcon);
|
||||||
|
|
||||||
// 设置延时处理下一个伤
|
// 设置延时处理下一个伤
|
||||||
this.scheduleOnce(() => {
|
this.scheduleOnce(() => {
|
||||||
@@ -473,7 +474,7 @@ export class HeroViewComp extends CCComp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 立即显示伤害效果 */
|
/** 立即显示伤害效果 */
|
||||||
private showDamageImmediate(damage: number, isCrit: boolean) {
|
private showDamageImmediate(damage: number, isCrit: boolean, debuffIcon: string = "") {
|
||||||
if (!this.model) return;
|
if (!this.model) return;
|
||||||
|
|
||||||
const damageText = NumberFormatter.formatNumber(Math.max(0, Math.floor(damage)));
|
const damageText = NumberFormatter.formatNumber(Math.max(0, Math.floor(damage)));
|
||||||
@@ -481,7 +482,7 @@ export class HeroViewComp extends CCComp {
|
|||||||
if (isCrit) {
|
if (isCrit) {
|
||||||
this.hp_tip(TooltipTypes.crit, damageText);
|
this.hp_tip(TooltipTypes.crit, damageText);
|
||||||
} else {
|
} else {
|
||||||
this.hp_tip(TooltipTypes.life, damageText);
|
this.hp_tip(TooltipTypes.life, damageText, 1001, 0, debuffIcon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reset() {
|
reset() {
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export class Tooltip extends ecs.Entity {
|
|||||||
this.remove(TooltipCom);
|
this.remove(TooltipCom);
|
||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
static load(pos: Vec3 = Vec3.ZERO,type:number=1,vaule:string="",s_uuid:number=1001,parent:any=null,cd:number=1,fac:number=FacSet.MON,triggerType:string="") {
|
static load(pos: Vec3 = Vec3.ZERO,type:number=1,vaule:string="",s_uuid:number=1001,parent:any=null,cd:number=1,fac:number=FacSet.MON,triggerType:string="",debuffIcon:string="") {
|
||||||
let node: Node;
|
let node: Node;
|
||||||
if (Tooltip.pool.size() > 0) {
|
if (Tooltip.pool.size() > 0) {
|
||||||
node = Tooltip.pool.get()!;
|
node = Tooltip.pool.get()!;
|
||||||
@@ -75,7 +75,7 @@ export class Tooltip extends ecs.Entity {
|
|||||||
node.active = true;
|
node.active = true;
|
||||||
|
|
||||||
var sv = node.getComponent(TooltipCom)!;
|
var sv = node.getComponent(TooltipCom)!;
|
||||||
sv.init(type, vaule, s_uuid, fac, triggerType);
|
sv.init(type, vaule, s_uuid, fac, triggerType, debuffIcon);
|
||||||
|
|
||||||
// this.add(sv); // 不要添加到单例实体上,否则会覆盖或导致单例被销毁
|
// this.add(sv); // 不要添加到单例实体上,否则会覆盖或导致单例被销毁
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ export class TooltipCom extends CCComp {
|
|||||||
fac: number = FacSet.MON;
|
fac: number = FacSet.MON;
|
||||||
/** 当前技能喊话对应的触发类型(空字符串表示普通主动技能) */
|
/** 当前技能喊话对应的触发类型(空字符串表示普通主动技能) */
|
||||||
triggerType: string = "";
|
triggerType: string = "";
|
||||||
|
/** DoT 飘字需激活的 debuff 图标节点名(loss_life/hp/debuff 下的子节点,如 FireDamage);空串=普通伤害 */
|
||||||
|
debuffIcon: string = "";
|
||||||
|
|
||||||
// 动画参数配置
|
// 动画参数配置
|
||||||
private readonly popDuration = 0.15;
|
private readonly popDuration = 0.15;
|
||||||
@@ -43,12 +45,13 @@ export class TooltipCom extends CCComp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 初始化并播放动画 */
|
/** 初始化并播放动画 */
|
||||||
init(type: number, value: string, uuid: number, fac: number = FacSet.MON, triggerType: string = "") {
|
init(type: number, value: string, uuid: number, fac: number = FacSet.MON, triggerType: string = "", debuffIcon: string = "") {
|
||||||
this.stype = type;
|
this.stype = type;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.s_uuid = uuid;
|
this.s_uuid = uuid;
|
||||||
this.fac = fac;
|
this.fac = fac;
|
||||||
this.triggerType = triggerType;
|
this.triggerType = triggerType;
|
||||||
|
this.debuffIcon = debuffIcon;
|
||||||
|
|
||||||
// 初始化或获取 UIOpacity 组件
|
// 初始化或获取 UIOpacity 组件
|
||||||
this._uiOpacity = this.node.getComponent(UIOpacity);
|
this._uiOpacity = this.node.getComponent(UIOpacity);
|
||||||
@@ -94,6 +97,7 @@ export class TooltipCom extends CCComp {
|
|||||||
this.node.setPosition(v3(this.node.position.x + offsetX, currentY));
|
this.node.setPosition(v3(this.node.position.x + offsetX, currentY));
|
||||||
this.node.setSiblingIndex(topSiblingIndex);
|
this.node.setSiblingIndex(topSiblingIndex);
|
||||||
this.setupLabel(this.fac === FacSet.HERO ? "hloss" : "loss_life", "hp", this.value);
|
this.setupLabel(this.fac === FacSet.HERO ? "hloss" : "loss_life", "hp", this.value);
|
||||||
|
this.setupDebuffIcon(); // DoT 伤害时点亮 loss_life/hp/debuff 下的对应图标
|
||||||
scaleMax = 1.5;
|
scaleMax = 1.5;
|
||||||
break;
|
break;
|
||||||
case TooltipTypes.health: // 治疗
|
case TooltipTypes.health: // 治疗
|
||||||
@@ -164,6 +168,20 @@ export class TooltipCom extends CCComp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DoT 伤害飘字:激活 loss_life/hp/debuff 下指定的 debuff 图标子节点。
|
||||||
|
* 仅怪物普通伤害(loss_life)路径调用;debuffIcon 为空或未找到节点时静默跳过。
|
||||||
|
*/
|
||||||
|
private setupDebuffIcon() {
|
||||||
|
if (!this.debuffIcon) return;
|
||||||
|
const debuffNode = this.node.getChildByName("loss_life")?.getChildByName("hp")?.getChildByName("debuff");
|
||||||
|
if (!debuffNode) return;
|
||||||
|
// 先全部隐藏(对象池复用防残留),再点亮目标图标
|
||||||
|
for (const child of debuffNode.children) {
|
||||||
|
child.active = child.name === this.debuffIcon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据技能触发类型激活对应的背景标识节点
|
* 根据技能触发类型激活对应的背景标识节点
|
||||||
* 仅 TooltipTypes.skill 走此分支,其他飘字类型不受影响
|
* 仅 TooltipTypes.skill 走此分支,其他飘字类型不受影响
|
||||||
|
|||||||
Reference in New Issue
Block a user