feat(map,hero): add hero sell function to hero box

1. 新增出售按钮与价格标签UI到HeroBoxComp
2. 实现英雄出售逻辑:移除实体、结算金币并派发事件
3. 统一使用MissionEconomy管理出售金币计算
4. 调整窗口prefab布局适配新UI元素
This commit is contained in:
panFD
2026-08-01 21:36:02 +08:00
parent 4532cb5c61
commit ad38e9904e
3 changed files with 1335 additions and 2991 deletions

View File

@@ -19,8 +19,10 @@ import { oops } from "db://oops-framework/core/Oops";
import { GameEvent } from "../common/config/GameEvent";
import { HeroInfo } from "../common/config/heroSet";
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
import { Hero } from "../hero/Hero";
import { getLvColor } from "../common/config/GameSet";
import { buildSkillDescRich } from "../common/config/HeroSkillDesc";
import { MissionEconomy } from "./MissionEconomy";
const { ccclass, property } = _decorator;
@@ -53,6 +55,14 @@ export class HeroBoxComp extends CCComp {
@property(Node)
private noHero: Node = null;
/** 出售按钮(绑定英雄时激活,点击出售该英雄) */
@property(Node)
private sell_btn: Node = null;
/** 出售价格标签(按英雄等级显示当前卖价,含驻场加成) */
@property(Label)
private sell_price_label: Label = null;
/** 技能描述富文本(多行,展示当前等级触发技能,数值高亮) */
@property(RichText)
private skill_label: RichText = null;
@@ -154,6 +164,8 @@ export class HeroBoxComp extends CCComp {
this.more_btn?.on(NodeEventType.TOUCH_CANCEL, this.onMoreBtnTouchEnd, this);
// 空槽位点击 → 打开英雄卡池
this.noHero?.on(NodeEventType.TOUCH_END, this.onNoHeroClick, this);
// 出售按钮点击 → 出售当前绑定英雄
this.sell_btn?.on(NodeEventType.TOUCH_END, this.onSellHeroClick, this);
}
onDestroy() {
@@ -165,6 +177,28 @@ export class HeroBoxComp extends CCComp {
if (this.noHero && this.noHero.isValid) {
this.noHero.off(NodeEventType.TOUCH_END, this.onNoHeroClick, this);
}
if (this.sell_btn && this.sell_btn.isValid) {
this.sell_btn.off(NodeEventType.TOUCH_END, this.onSellHeroClick, this);
}
}
/**
* 出售按钮点击:移除英雄实体、按等级结算金币并派发 HeroSell 事件。
* MissionCardComp 监听该事件后会刷新槽位,本盒自动切为空状态。
*/
private onSellHeroClick() {
if (!this.eid || !this.model) return;
const heroLv = Math.max(1, Math.floor(this.model.lv ?? 1));
// 移除 ECS 实体失败(实体已失效)则不做后续结算
if (!Hero.removeByEid(this.eid)) return;
oops.audio.playEffect("music/button");
// 统一经济管理入口:按等级计算卖价并加金币
const gold = MissionEconomy.executeSellHero(heroLv);
mLogger.log(this.debugMode, "HeroBoxComp", "onSellHeroClick", { eid: this.eid, heroLv, gold });
// 通知 MissionCardComp 更新场上英雄数量并刷新英雄盒槽位
oops.message.dispatchEvent(GameEvent.HeroSell, { eid: this.eid });
}
/**
@@ -254,6 +288,9 @@ export class HeroBoxComp extends CCComp {
if (this.noHero && this.noHero.isValid) {
this.noHero.active = false;
}
if (this.sell_btn && this.sell_btn.isValid) {
this.sell_btn.active = true;
}
this.refresh();
}
@@ -268,6 +305,13 @@ export class HeroBoxComp extends CCComp {
this.noHero.active = true;
}
if (this.sell_btn && this.sell_btn.isValid) {
this.sell_btn.active = false;
}
if (this.sell_price_label && this.sell_price_label.isValid) {
this.sell_price_label.string = "";
}
if (this.name_label && this.name_label.isValid) {
this.name_label.string = "";
}
@@ -319,6 +363,12 @@ export class HeroBoxComp extends CCComp {
this.level_label.color = getLvColor(lv);
}
// ---- 出售价格(按等级计算,含驻场 SellGold 加成) ----
if (this.sell_price_label && this.sell_price_label.isValid) {
const lv = Math.max(1, Math.floor(this.model.lv ?? 1));
this.sell_price_label.string = `${MissionEconomy.getSellGold(lv)}`;
}
// ---- AP / HP ----
const finalAp = Math.max(0, Math.floor(this.model.getFinalAp()));
const baseAp = Math.max(0, Math.floor(this.model.base_ap ?? 0));