feat: 新增英雄基础属性存档与UI属性加成显示

1.  新增base_ap和base_hp属性存储英雄原始基础攻防属性
2.  实现属性加成差值显示,展示当前属性与基础属性的差异
3.  重构英雄信息UI,新增名字、关闭按钮等节点绑定
4.  调整英雄预制体布局,适配新的UI展示需求
5.  补充战斗触发类型注释文档
This commit is contained in:
walkpan
2026-05-24 23:21:35 +08:00
parent dfaa55b864
commit 518a9a1ce9
5 changed files with 293 additions and 226 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -73,6 +73,19 @@ export enum MonStart {
}
/**
call 召唤后触发 降临
dead 死亡后触发 遗志
fstart 战斗开始 先手
fend 战斗结束 终战
field 驻场 光环
atking 攻击后触发 追击
atked 受击后触发 反击
revive 复活触发 涅槃
**/
/**
* 英雄/怪物基础信息接口
*/

View File

@@ -127,6 +127,9 @@ export class Hero extends ecs.Entity {
// 使用指数增长公式等级2时为原来的3倍等级3时为原来的9倍 (若需线性增长可改为 hero.ap * (1 + (model.lv - 1) * (FightSet.H_HERO_POW - 1)))
let base_ap = hero.ap * Math.pow(FightSet.MERGE_NEED, model.lv - 1);
let base_hp = hero.hp * Math.pow(FightSet.MERGE_NEED, model.lv - 1);
model.base_ap = base_ap;
model.base_hp = base_hp;
// 应用天赋加成
if (model.fac === FacSet.HERO) {

View File

@@ -23,6 +23,8 @@ export class HeroAttrsComp extends ecs.Comp {
type: number = 0; // 0近战 1远程 2辅助
fac: number = 0; // 0:hero 1:monster
// ==================== 基础属性(有初始值) ====================
base_ap: number = 0; // 原始基础攻击(无任何加成)
base_hp: number = 0; // 原始基础血量(无任何加成)
ap: number = 0; // 基础攻击
hp: number = 100; // 基础血量
hp_max: number = 100; // 最大血量
@@ -309,6 +311,8 @@ export class HeroAttrsComp extends ecs.Comp {
this.lv = 1;
this.type = 0;
this.fac = 0;
this.base_ap = 0;
this.base_hp = 0;
this.ap = 0;
this.hp = 100;
this.hp_max = 100;

View File

@@ -51,27 +51,44 @@ export class HInfoComp extends CCComp {
/** 英雄 idle 动画图标节点 */
@property(Node)
icon_node=null!
/** 出售按钮节点(预留,当前交互已注释) */
/** 出售按钮节点 */
@property(Node)
sell_node=null!
/** 普通品质边框 */
/** 关闭窗口按钮节点 */
@property(Node)
NF_node=null!
close_node=null!
/** 英雄名字节点 */
@property(Node)
Name_node=null!
/** 高品质边框 */
@property(Node)
HF_node=null!
info_node=null!
@property(Node)
lv_node=null!
@property(Node)
ap_node=null!
@property(Node)
hp_node=null!
/** 绑定的英雄 ECS 实体 ID */
private eid: number = 0;
/** 绑定的英雄属性数据模型引用 */
private model: HeroAttrsComp | null = null;
/** 英雄名字标签缓存引用 */
private nameLabel: Label | null = null;
/** AP 标签缓存引用 */
private apLabel: Label | null = null;
/** AP 加成标签缓存引用 */
private apPlusLabel: Label | null = null;
/** HP 标签缓存引用 */
private hpLabel: Label | null = null;
/** HP 加成标签缓存引用 */
private hpPlusLabel: Label | null = null;
/** 图标视觉令牌(异步加载竞态保护) */
private iconVisualToken: number = 0;
/** 当前显示的英雄 UUID避免相同 UUID 重复加载动画) */
@@ -161,12 +178,39 @@ export class HInfoComp extends CCComp {
this.updateHeroAnimation(this.icon_node, heroUuid, this.iconVisualToken);
}
// ---- 名字标签 ----
if (this.nameLabel) {
this.nameLabel.string = this.model.hero_name ?? "";
}
// ---- 数值标签 ----
if (this.apLabel) {
this.apLabel.string = `${Math.max(0, Math.floor(this.model.ap ?? 0))}`;
const currentAp = Math.max(0, Math.floor(this.model.ap ?? 0));
const baseAp = Math.max(0, Math.floor(this.model.base_ap ?? 0));
this.apLabel.string = `${currentAp}`;
if (this.apPlusLabel) {
const diff = currentAp - baseAp;
if (diff !== 0) {
this.apPlusLabel.string = diff > 0 ? `(+${diff})` : `(${diff})`;
this.apPlusLabel.node.active = true;
} else {
this.apPlusLabel.node.active = false;
}
}
}
if (this.hpLabel) {
this.hpLabel.string = `${Math.max(0, Math.floor(this.model.hp_max ?? 0))}`;
const currentHp = Math.max(0, Math.floor(this.model.hp_max ?? 0));
const baseHp = Math.max(0, Math.floor(this.model.base_hp ?? 0));
this.hpLabel.string = `${currentHp}`;
if (this.hpPlusLabel) {
const diff = currentHp - baseHp;
if (diff !== 0) {
this.hpPlusLabel.string = diff > 0 ? `(+${diff})` : `(${diff})`;
this.hpPlusLabel.node.active = true;
} else {
this.hpPlusLabel.node.active = false;
}
}
}
}
@@ -182,11 +226,16 @@ export class HInfoComp extends CCComp {
/** 缓存 AP / HP Label 引用,避免每次刷新都遍历节点树 */
private cacheLabels() {
if (!this.apLabel) {
this.apLabel = this.findLabelByPath(["ap", "val"]);
if (!this.nameLabel && this.Name_node) {
this.nameLabel = this.Name_node.getComponent(Label) || this.Name_node.getComponentInChildren(Label);
}
if (!this.hpLabel) {
this.hpLabel = this.findLabelByPath(["hp", "val"]);
if (!this.apLabel && this.ap_node) {
this.apLabel = this.ap_node.getChildByName("val")?.getComponent(Label) || null;
this.apPlusLabel = this.ap_node.getChildByName("plus")?.getComponent(Label) || null;
}
if (!this.hpLabel && this.hp_node) {
this.hpLabel = this.hp_node.getChildByName("val")?.getComponent(Label) || null;
this.hpPlusLabel = this.hp_node.getChildByName("plus")?.getComponent(Label) || null;
}
}
@@ -255,16 +304,29 @@ export class HInfoComp extends CCComp {
private bindEvents() {
this.sell_node?.on(Button.EventType.CLICK, this.onSellHero, this);
this.node.on(NodeEventType.TOUCH_END, this.onOpenIBox, this);
this.close_node?.on(Button.EventType.CLICK, this.onClosePanel, this);
// this.node.on(NodeEventType.TOUCH_END, this.onOpenIBox, this);
}
private unbindEvents() {
if (this.sell_node && this.sell_node.isValid) {
this.sell_node.off(Button.EventType.CLICK, this.onSellHero, this);
}
if (this.node && this.node.isValid) {
this.node.off(NodeEventType.TOUCH_END, this.onOpenIBox, this);
if (this.close_node && this.close_node.isValid) {
this.close_node.off(Button.EventType.CLICK, this.onClosePanel, this);
}
// if (this.node && this.node.isValid) {
// this.node.off(NodeEventType.TOUCH_END, this.onOpenIBox, this);
// }
}
/**
* 点击关闭按钮时关闭英雄信息面板
*/
private onClosePanel() {
if (this.isClosing) return;
this.isClosing = true;
oops.gui.remove(UIID.HInfo);
}
/**