feat: 新增英雄基础属性存档与UI属性加成显示
1. 新增base_ap和base_hp属性存储英雄原始基础攻防属性 2. 实现属性加成差值显示,展示当前属性与基础属性的差异 3. 重构英雄信息UI,新增名字、关闭按钮等节点绑定 4. 调整英雄预制体布局,适配新的UI展示需求 5. 补充战斗触发类型注释文档
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -73,6 +73,19 @@ export enum MonStart {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
call 召唤后触发 降临
|
||||
dead 死亡后触发 遗志
|
||||
fstart 战斗开始 先手
|
||||
fend 战斗结束 终战
|
||||
field 驻场 光环
|
||||
atking 攻击后触发 追击
|
||||
atked 受击后触发 反击
|
||||
revive 复活触发 涅槃
|
||||
|
||||
**/
|
||||
|
||||
/**
|
||||
* 英雄/怪物基础信息接口
|
||||
*/
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user