refactor(英雄管理): 将英雄与金币数据迁移至全局任务数据
- 移除 Hero.ts 中手动维护的 hero_num 计数逻辑 - 在 SingletonModuleComp 的 mission_data 中添加 hero_max_num、hero_extend_max_num 字段 - 重构 MissionCardComp,使其通过 smc.vmdata.mission_data 读写英雄数量、金币等状态 - 新增辅助方法统一数据访问与同步,避免状态分散管理
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -62,6 +62,8 @@ export class SingletonModuleComp extends ecs.Comp {
|
|||||||
mission_data:{
|
mission_data:{
|
||||||
mon_num:0,//怪物数量
|
mon_num:0,//怪物数量
|
||||||
hero_num:0,//英雄数量
|
hero_num:0,//英雄数量
|
||||||
|
hero_max_num:5,//英雄可召唤上限
|
||||||
|
hero_extend_max_num:6,//英雄可拓展上限
|
||||||
wave_time_num:0,//波次时间
|
wave_time_num:0,//波次时间
|
||||||
in_fight:false,
|
in_fight:false,
|
||||||
fight_time:0,//战斗时间
|
fight_time:0,//战斗时间
|
||||||
@@ -236,4 +238,4 @@ export class SingletonModuleComp extends ecs.Comp {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export var smc: SingletonModuleComp = ecs.getSingleton(SingletonModuleComp);
|
export var smc: SingletonModuleComp = ecs.getSingleton(SingletonModuleComp);
|
||||||
|
|||||||
@@ -150,8 +150,6 @@ export class Hero extends ecs.Entity {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.start();
|
.start();
|
||||||
// 维护关卡内英雄数量统计
|
|
||||||
smc.vmdata.mission_data.hero_num++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 重置入口:复用 destroy 的释放流程 */
|
/** 重置入口:复用 destroy 的释放流程 */
|
||||||
@@ -197,10 +195,6 @@ export class BattleEntityLifecycleSystem extends ecs.ComblockSystem
|
|||||||
if (heroAttrs) {
|
if (heroAttrs) {
|
||||||
mLogger.log(heroAttrs.debugMode, 'BattleEntityLifecycle', `${label}离开世界: ${heroAttrs.hero_name}`);
|
mLogger.log(heroAttrs.debugMode, 'BattleEntityLifecycle', `${label}离开世界: ${heroAttrs.hero_name}`);
|
||||||
if (heroAttrs.fac === FacSet.HERO) {
|
if (heroAttrs.fac === FacSet.HERO) {
|
||||||
const missionData = smc.vmdata?.mission_data;
|
|
||||||
if (missionData) {
|
|
||||||
missionData.hero_num = Math.max(0, (missionData.hero_num ?? 0) - 1);
|
|
||||||
}
|
|
||||||
oops.message.dispatchEvent(GameEvent.HeroDead, {
|
oops.message.dispatchEvent(GameEvent.HeroDead, {
|
||||||
eid: e.eid,
|
eid: e.eid,
|
||||||
model: heroAttrs
|
model: heroAttrs
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { CardComp } from "./CardComp";
|
|||||||
import { oops } from "db://oops-framework/core/Oops";
|
import { oops } from "db://oops-framework/core/Oops";
|
||||||
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
||||||
import { HInfoComp } from "./HInfoComp";
|
import { HInfoComp } from "./HInfoComp";
|
||||||
|
import { smc } from "../common/SingletonModuleComp";
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@@ -50,14 +51,8 @@ export class MissionCardComp extends CCComp {
|
|||||||
private cardComps: CardComp[] = [];
|
private cardComps: CardComp[] = [];
|
||||||
/** 当前卡池等级(仅影响抽卡来源,不直接改卡槽现有内容) */
|
/** 当前卡池等级(仅影响抽卡来源,不直接改卡槽现有内容) */
|
||||||
private poolLv: number = CARD_POOL_INIT_LEVEL;
|
private poolLv: number = CARD_POOL_INIT_LEVEL;
|
||||||
private coin: number = CardInitCoins;
|
|
||||||
private readonly heroInfoItemGap: number = 86;
|
private readonly heroInfoItemGap: number = 86;
|
||||||
private heroInfoSyncTimer: number = 0;
|
private heroInfoSyncTimer: number = 0;
|
||||||
private readonly heroDefaultMaxCount: number = 5;
|
|
||||||
private readonly heroExtendMaxCount: number = 6;
|
|
||||||
private heroMaxCount: number = this.heroDefaultMaxCount;
|
|
||||||
private heroCurrentCount: number = 0;
|
|
||||||
private heroNumLabel: Label | null = null;
|
|
||||||
private heroInfoItems: Map<number, {
|
private heroInfoItems: Map<number, {
|
||||||
node: Node,
|
node: Node,
|
||||||
model: HeroAttrsComp,
|
model: HeroAttrsComp,
|
||||||
@@ -86,9 +81,13 @@ export class MissionCardComp extends CCComp {
|
|||||||
/** 任务开始时:重置卡池等级、清空4槽、显示面板 刷新一次卡池*/
|
/** 任务开始时:重置卡池等级、清空4槽、显示面板 刷新一次卡池*/
|
||||||
onMissionStart() {
|
onMissionStart() {
|
||||||
this.poolLv = CARD_POOL_INIT_LEVEL;
|
this.poolLv = CARD_POOL_INIT_LEVEL;
|
||||||
this.coin = CardInitCoins
|
const missionData = this.getMissionData();
|
||||||
this.heroMaxCount = this.heroDefaultMaxCount;
|
if (missionData) {
|
||||||
this.heroCurrentCount = 0;
|
missionData.coin = CardInitCoins;
|
||||||
|
missionData.hero_num = 0;
|
||||||
|
missionData.hero_max_num = 5;
|
||||||
|
missionData.hero_extend_max_num = 6;
|
||||||
|
}
|
||||||
this.clearHeroInfoPanels();
|
this.clearHeroInfoPanels();
|
||||||
this.layoutCardSlots();
|
this.layoutCardSlots();
|
||||||
this.clearAllCards();
|
this.clearAllCards();
|
||||||
@@ -98,7 +97,6 @@ export class MissionCardComp extends CCComp {
|
|||||||
this.resetButtonScale(this.cards_chou);
|
this.resetButtonScale(this.cards_chou);
|
||||||
this.resetButtonScale(this.cards_up);
|
this.resetButtonScale(this.cards_up);
|
||||||
this.updatePoolLvUI();
|
this.updatePoolLvUI();
|
||||||
this.updateCoinUI();
|
|
||||||
this.updateHeroNumUI(false, false);
|
this.updateHeroNumUI(false, false);
|
||||||
this.node.active = true;
|
this.node.active = true;
|
||||||
const cards = this.buildDrawCards();
|
const cards = this.buildDrawCards();
|
||||||
@@ -151,9 +149,10 @@ export class MissionCardComp extends CCComp {
|
|||||||
}
|
}
|
||||||
private onCoinAdd(args:any){
|
private onCoinAdd(args:any){
|
||||||
const v = typeof args === 'number' ? args : (args?.delta ?? args?.value ?? 0);
|
const v = typeof args === 'number' ? args : (args?.delta ?? args?.value ?? 0);
|
||||||
this.coin = Math.max(0, (this.coin ?? 0) + v);
|
if (v === 0) return;
|
||||||
|
this.setMissionCoin(this.getMissionCoin() + v);
|
||||||
this.updatePoolLvUI();
|
this.updatePoolLvUI();
|
||||||
this.updateCoinUI();
|
this.playCoinChangeAnim(v > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 解除按钮监听,避免节点销毁后回调泄漏 */
|
/** 解除按钮监听,避免节点销毁后回调泄漏 */
|
||||||
@@ -174,9 +173,10 @@ export class MissionCardComp extends CCComp {
|
|||||||
const eid = Number(payload?.eid ?? 0);
|
const eid = Number(payload?.eid ?? 0);
|
||||||
const model = payload?.model as HeroAttrsComp | undefined;
|
const model = payload?.model as HeroAttrsComp | undefined;
|
||||||
if (!eid || !model) return;
|
if (!eid || !model) return;
|
||||||
const before = this.heroCurrentCount;
|
const before = this.getAliveHeroCount();
|
||||||
this.ensureHeroInfoPanel(eid, model);
|
this.ensureHeroInfoPanel(eid, model);
|
||||||
this.updateHeroNumUI(true, this.heroCurrentCount > before);
|
const after = this.getAliveHeroCount();
|
||||||
|
this.updateHeroNumUI(true, after > before);
|
||||||
}
|
}
|
||||||
|
|
||||||
private onHeroDead() {
|
private onHeroDead() {
|
||||||
@@ -188,11 +188,12 @@ export class MissionCardComp extends CCComp {
|
|||||||
const payload = args ?? event;
|
const payload = args ?? event;
|
||||||
if (!payload) return;
|
if (!payload) return;
|
||||||
const current = this.getAliveHeroCount();
|
const current = this.getAliveHeroCount();
|
||||||
this.heroCurrentCount = current;
|
this.syncMissionHeroData(current);
|
||||||
if (current >= this.heroMaxCount) {
|
const heroMax = this.getMissionHeroMaxNum();
|
||||||
|
if (current >= heroMax) {
|
||||||
payload.cancel = true;
|
payload.cancel = true;
|
||||||
payload.reason = "hero_limit";
|
payload.reason = "hero_limit";
|
||||||
oops.gui.toast(`英雄已满 (${current}/${this.heroMaxCount})`);
|
oops.gui.toast(`英雄已满 (${current}/${heroMax})`);
|
||||||
this.playHeroNumDeniedAnim();
|
this.playHeroNumDeniedAnim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,7 +247,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const cost = this.getUpgradeCost(this.poolLv);
|
const cost = this.getUpgradeCost(this.poolLv);
|
||||||
const currentCoin = this.coin ?? 0;
|
const currentCoin = this.getMissionCoin();
|
||||||
if (currentCoin < cost) {
|
if (currentCoin < cost) {
|
||||||
oops.gui.toast(`金币不足,升级需要${cost}`);
|
oops.gui.toast(`金币不足,升级需要${cost}`);
|
||||||
this.updatePoolLvUI();
|
this.updatePoolLvUI();
|
||||||
@@ -257,14 +258,14 @@ export class MissionCardComp extends CCComp {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.coin = currentCoin - cost;
|
this.setMissionCoin(currentCoin - cost);
|
||||||
this.poolLv += 1;
|
this.poolLv += 1;
|
||||||
this.updateCoinUI();
|
this.playCoinChangeAnim(false);
|
||||||
this.updatePoolLvUI();
|
this.updatePoolLvUI();
|
||||||
mLogger.log(this.debugMode, "MissionCardComp", "pool level up", {
|
mLogger.log(this.debugMode, "MissionCardComp", "pool level up", {
|
||||||
poolLv: this.poolLv,
|
poolLv: this.poolLv,
|
||||||
cost,
|
cost,
|
||||||
leftCoin: this.coin
|
leftCoin: this.getMissionCoin()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,7 +360,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
}
|
}
|
||||||
private canUpPool() {
|
private canUpPool() {
|
||||||
if (this.poolLv >= CARD_POOL_MAX_LEVEL) return false;
|
if (this.poolLv >= CARD_POOL_MAX_LEVEL) return false;
|
||||||
const currentCoin = this.coin ?? 0;
|
const currentCoin = this.getMissionCoin();
|
||||||
return currentCoin >= this.getUpgradeCost(this.poolLv);
|
return currentCoin >= this.getUpgradeCost(this.poolLv);
|
||||||
}
|
}
|
||||||
/** 更新升级按钮上的等级文案,反馈当前卡池层级 */
|
/** 更新升级按钮上的等级文案,反馈当前卡池层级 */
|
||||||
@@ -388,11 +389,17 @@ export class MissionCardComp extends CCComp {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateCoinUI() {
|
private playCoinChangeAnim(isIncrease: boolean) {
|
||||||
if (!this.coins_node) return;
|
if (!this.coins_node || !this.coins_node.isValid) return;
|
||||||
const label = this.coins_node.getChildByName("num")?.getComponent(Label);
|
const target = this.coins_node.getChildByName("num") || this.coins_node;
|
||||||
if (!label) return;
|
if (!target || !target.isValid) return;
|
||||||
label.string = `${this.coin ?? 0}`;
|
const peak = isIncrease ? 1.16 : 1.08;
|
||||||
|
Tween.stopAllByTarget(target);
|
||||||
|
target.setScale(1, 1, 1);
|
||||||
|
tween(target)
|
||||||
|
.to(0.08, { scale: new Vec3(peak, peak, 1) })
|
||||||
|
.to(0.1, { scale: new Vec3(1, 1, 1) })
|
||||||
|
.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getUpgradeCost(lv: number): number {
|
private getUpgradeCost(lv: number): number {
|
||||||
@@ -488,26 +495,32 @@ export class MissionCardComp extends CCComp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.heroInfoSyncTimer = 0;
|
this.heroInfoSyncTimer = 0;
|
||||||
this.heroCurrentCount = 0;
|
this.syncMissionHeroData(0);
|
||||||
this.updateHeroNumUI(false, false);
|
this.updateHeroNumUI(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setHeroMaxCount(max: number) {
|
public setHeroMaxCount(max: number) {
|
||||||
const next = Math.max(this.heroDefaultMaxCount, Math.min(this.heroExtendMaxCount, Math.floor(max || this.heroDefaultMaxCount)));
|
const missionData = this.getMissionData();
|
||||||
if (next === this.heroMaxCount) return;
|
if (!missionData) return;
|
||||||
this.heroMaxCount = next;
|
const min = 5;
|
||||||
|
const limit = Math.max(min, missionData.hero_extend_max_num ?? 6);
|
||||||
|
const next = Math.max(min, Math.min(limit, Math.floor(max || min)));
|
||||||
|
if (next === missionData.hero_max_num) return;
|
||||||
|
missionData.hero_max_num = next;
|
||||||
this.updateHeroNumUI(true, false);
|
this.updateHeroNumUI(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public tryExpandHeroMax(add: number = 1): boolean {
|
public tryExpandHeroMax(add: number = 1): boolean {
|
||||||
const next = this.heroMaxCount + Math.max(0, Math.floor(add));
|
const missionData = this.getMissionData();
|
||||||
const before = this.heroMaxCount;
|
if (!missionData) return false;
|
||||||
|
const before = this.getMissionHeroMaxNum();
|
||||||
|
const next = before + Math.max(0, Math.floor(add));
|
||||||
this.setHeroMaxCount(next);
|
this.setHeroMaxCount(next);
|
||||||
return this.heroMaxCount > before;
|
return this.getMissionHeroMaxNum() > before;
|
||||||
}
|
}
|
||||||
|
|
||||||
public canUseHeroCard(): boolean {
|
public canUseHeroCard(): boolean {
|
||||||
return this.getAliveHeroCount() < this.heroMaxCount;
|
return this.getAliveHeroCount() < this.getMissionHeroMaxNum();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getAliveHeroCount(): number {
|
private getAliveHeroCount(): number {
|
||||||
@@ -522,15 +535,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private updateHeroNumUI(animate: boolean, isIncrease: boolean) {
|
private updateHeroNumUI(animate: boolean, isIncrease: boolean) {
|
||||||
this.heroCurrentCount = this.getAliveHeroCount();
|
this.syncMissionHeroData();
|
||||||
if (!this.hero_num_node || !this.hero_num_node.isValid) return;
|
|
||||||
const numNode = this.hero_num_node.getChildByName("num");
|
|
||||||
if (!this.heroNumLabel) {
|
|
||||||
this.heroNumLabel = numNode?.getComponent(Label) || numNode?.getComponentInChildren(Label) || null;
|
|
||||||
}
|
|
||||||
if (this.heroNumLabel) {
|
|
||||||
this.heroNumLabel.string = `${this.heroCurrentCount}/${this.heroMaxCount}`;
|
|
||||||
}
|
|
||||||
if (!animate || !isIncrease) return;
|
if (!animate || !isIncrease) return;
|
||||||
this.playHeroNumGainAnim();
|
this.playHeroNumGainAnim();
|
||||||
}
|
}
|
||||||
@@ -561,6 +566,38 @@ export class MissionCardComp extends CCComp {
|
|||||||
.start();
|
.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getMissionData(): any {
|
||||||
|
return smc?.vmdata?.mission_data ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getMissionHeroNum(): number {
|
||||||
|
const missionData = this.getMissionData();
|
||||||
|
return Math.max(0, Math.floor(missionData?.hero_num ?? 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private getMissionCoin(): number {
|
||||||
|
const missionData = this.getMissionData();
|
||||||
|
return Math.max(0, Math.floor(missionData?.coin ?? 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private setMissionCoin(value: number) {
|
||||||
|
const missionData = this.getMissionData();
|
||||||
|
if (!missionData) return;
|
||||||
|
missionData.coin = Math.max(0, Math.floor(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private getMissionHeroMaxNum(): number {
|
||||||
|
const missionData = this.getMissionData();
|
||||||
|
return Math.max(5, Math.floor(missionData?.hero_max_num ?? 5));
|
||||||
|
}
|
||||||
|
|
||||||
|
private syncMissionHeroData(count?: number) {
|
||||||
|
const missionData = this.getMissionData();
|
||||||
|
if (!missionData) return;
|
||||||
|
const safeCount = Math.max(0, Math.floor(count ?? this.getAliveHeroCount()));
|
||||||
|
missionData.hero_num = safeCount;
|
||||||
|
}
|
||||||
|
|
||||||
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
/** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
||||||
reset() {
|
reset() {
|
||||||
this.clearHeroInfoPanels();
|
this.clearHeroInfoPanels();
|
||||||
|
|||||||
Reference in New Issue
Block a user